diff --git a/AGENTS.md b/AGENTS.md index e4923f2..12c071a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -181,6 +181,7 @@ Config is JSON (HJSON with comments supported). Default path depends on OS: | backup_timeout | `60` | Stream timeout in minutes (1-1440) | | compression_level | `9` | Gzip level (1-9) | | exclude_patterns | `[]` | Regex patterns to exclude from backup | +| filename_prefix | `backup` | Prefix for backup filename in Content-Disposition header | ## Architecture & Key Patterns @@ -278,4 +279,3 @@ Init scripts provided in `contrib/`: See `TODO.org` for current backlog: - Consider alternative compression algorithms (bz2, xz, lzo, lz4) -- Configurable filename prefix for `Content-Disposition` header diff --git a/README.md b/README.md index dd46ef7..3746f51 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ AI suggests to fill this section with useful information, despite that all optio | backup_timeout | 60 | Timeout in minutes for backup streaming operations. | If a backup takes longer than this, the connection will be terminated. Useful for large backups. Range: 1-1440 minutes (1 day max). | | compression_level | 9 | Gzip compression level for tar.gz archives. | 1 (fastest) to 9 (best compression). Higher values produce smaller files but take longer to compress. | | exclude_patterns | [] | Regex patterns to exclude from backup. | E.g., `[".*\\.tmp$", "/node_modules/"]`. Files matching any pattern are skipped. | +| filename_prefix | "backup" | Prefix for backup filename in Content-Disposition header. | E.g., "mybackup" produces `mybackup-20260325-092341.tar.gz`. | ## Best practices diff --git a/TODO.org b/TODO.org index 11966d2..94b6422 100644 --- a/TODO.org +++ b/TODO.org @@ -9,6 +9,6 @@ - [ ] lz4 for speed, xz for better compression - [ ] Add compression_algorithm config option -** TODO Configurable filename prefix - - [ ] Move "backup" prefix to config (currently hardcoded in newServer.go) - - [ ] Default: "backup", e.g., "backup-20260325-092341.tar.gz" +** DONE Configurable filename prefix + - [X] Move "backup" prefix to config (currently hardcoded in newServer.go) + - [X] Default: "backup", e.g., "backup-20260325-092341.tar.gz" diff --git a/data/config_example.json b/data/config_example.json index 6386e15..c8cdb8d 100644 --- a/data/config_example.json +++ b/data/config_example.json @@ -33,5 +33,17 @@ "directories": [ "/path/to/directory1", "/path/to/directory2" - ] + ], + + /* Backup streaming timeout in minutes. */ + "backup_timeout": 60, + + /* Gzip compression level (1-9, where 9 is best compression). */ + "compression_level": 9, + + /* Regex patterns to exclude from backup. */ + "exclude_patterns": [], + + /* Prefix for backup filename in Content-Disposition header. */ + "filename_prefix": "backup" } diff --git a/internal/backer/loadConfig.go b/internal/backer/loadConfig.go index 9dcebd6..5dbbe5c 100644 --- a/internal/backer/loadConfig.go +++ b/internal/backer/loadConfig.go @@ -128,6 +128,13 @@ func LoadConfig(path string) error { return errors.New("Option password is not set") } + // FilenamePrefix: default. + if C.FilenamePrefix == "" { + C.FilenamePrefix = "backup" + + log.Warnf("Config option filename_prefix is not set, fallback to %s", C.FilenamePrefix) + } + // Compile exclude patterns. excludePatterns = make([]*regexp.Regexp, 0, len(C.ExcludePatterns)) diff --git a/internal/backer/loadConfig_test.go b/internal/backer/loadConfig_test.go index 39ea0bb..8058435 100644 --- a/internal/backer/loadConfig_test.go +++ b/internal/backer/loadConfig_test.go @@ -170,6 +170,27 @@ func TestLoadConfigNoHTTPS(t *testing.T) { } } +// TestLoadConfigFilenamePrefixCustom tests custom filename prefix. +func TestLoadConfigFilenamePrefixCustom(t *testing.T) { + config := `{ + "user": "test", + "password": "test", + "directories": ["../../test_data/test1/foo"], + "nohttps": true, + "filename_prefix": "mybackup" + }` + tmpFile := writeTempConfig(t, config) + + err := LoadConfig(tmpFile) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if C.FilenamePrefix != "mybackup" { + t.Errorf("C.FilenamePrefix should be mybackup, got %s", C.FilenamePrefix) + } +} + // TestLoadConfigDefaultValues tests default values are set correctly. func TestLoadConfigDefaultValues(t *testing.T) { config := `{ @@ -201,6 +222,10 @@ func TestLoadConfigDefaultValues(t *testing.T) { if C.LogLevel != "info" { t.Errorf("C.LogLevel should default to info, got %s", C.LogLevel) } + + if C.FilenamePrefix != "backup" { + t.Errorf("C.FilenamePrefix should default to backup, got %s", C.FilenamePrefix) + } } // writeTempConfig is a helper to write a temp config file for testing. diff --git a/internal/backer/newServer.go b/internal/backer/newServer.go index efea9fe..92c8fe0 100644 --- a/internal/backer/newServer.go +++ b/internal/backer/newServer.go @@ -82,7 +82,7 @@ func NewServer(configPath string) (*http.Server, error) { }() timestamp := time.Now().Format("20060102-150405") - filename := fmt.Sprintf("backup-%s.tar.gz", timestamp) + filename := fmt.Sprintf("%s-%s.tar.gz", C.FilenamePrefix, timestamp) w.Header().Set("Content-Disposition", "attachment; filename="+filename) w.Header().Set("Content-Type", "application/octet-stream") diff --git a/internal/backer/types.go b/internal/backer/types.go index 0b8cf1d..5f7390d 100644 --- a/internal/backer/types.go +++ b/internal/backer/types.go @@ -17,6 +17,7 @@ type ( BackupTimeout int `json:"backup_timeout"` // Timeout in minutes for backup streaming. CompressionLevel int `json:"compression_level"` // Gzip compression level (1-9, default 9). ExcludePatterns []string `json:"exclude_patterns"` // Regex patterns to exclude from backup. + FilenamePrefix string `json:"filename_prefix"` // Prefix for backup filename (default: "backup"). } ) diff --git a/llms.txt b/llms.txt index 4c6faba..214b199 100644 --- a/llms.txt +++ b/llms.txt @@ -61,6 +61,7 @@ curl -u user:pass https://server:8086/archive -o backup.tar.gz | backup_timeout | 60 | Stream timeout in minutes (1-1440) | | compression_level | 9 | Gzip level (1-9) | | exclude_patterns | [] | Regex patterns to exclude from backup | +| filename_prefix | backup | Prefix for backup filename in Content-Disposition header | ## Key Patterns