diff --git a/backup/cmd/run.go b/backup/cmd/run.go index 2cbd603..cc133ea 100644 --- a/backup/cmd/run.go +++ b/backup/cmd/run.go @@ -15,7 +15,7 @@ func buildRunCommand() *cobra.Command { rsyncPath, _ := cmd.Flags().GetString("rsync-path") cfg := internal.LoadResolvedConfig(configPath) - logger, logPath := internal.CreateMainLogger() + logger, logPath := internal.CreateMainLogger(configPath, false) command := internal.NewSyncCommand(rsyncPath, logPath) cfg.Apply(command, logger) diff --git a/backup/cmd/simulate.go b/backup/cmd/simulate.go index d03e694..eb4ab83 100644 --- a/backup/cmd/simulate.go +++ b/backup/cmd/simulate.go @@ -15,7 +15,7 @@ func buildSimulateCommand() *cobra.Command { rsyncPath, _ := cmd.Flags().GetString("rsync-path") cfg := internal.LoadResolvedConfig(configPath) - logger, logPath := internal.CreateMainLogger() + logger, logPath := internal.CreateMainLogger(configPath, true) command := internal.NewSimulateCommand(rsyncPath, logPath) cfg.Apply(command, logger) diff --git a/backup/internal/helper.go b/backup/internal/helper.go index 02f573f..ad7f839 100644 --- a/backup/internal/helper.go +++ b/backup/internal/helper.go @@ -4,6 +4,7 @@ package internal import ( "log" "os" + "path/filepath" "strings" "time" ) @@ -14,6 +15,13 @@ type Path struct { Exclusions []string `yaml:"exclusions"` } +func GetConfigTitle(configPath string) string { + filename := filepath.Base(configPath) + filename = strings.TrimSuffix(filename, ".yaml") + + return filename +} + func NormalizePath(path string) string { return strings.TrimSuffix(strings.ReplaceAll(path, "//", "/"), "/") } @@ -21,8 +29,11 @@ func NormalizePath(path string) string { const LogFilePermission = 0644 const LogDirPermission = 0755 -func getLogPath() string { - logPath := "logs/sync-" + time.Now().Format("2006-01-02T15-04-05") +func getLogPath(simulate bool, title string) string { + logPath := "logs/sync-" + time.Now().Format("2006-01-02T15-04-05") + "-" + GetConfigTitle(title) + if simulate { + logPath += "-sim" + } err := os.MkdirAll(logPath, LogDirPermission) if err != nil { @@ -32,8 +43,8 @@ func getLogPath() string { return logPath } -func CreateMainLogger() (*log.Logger, string) { - logPath := getLogPath() +func CreateMainLogger(configPath string, simulate bool) (*log.Logger, string) { + logPath := getLogPath(simulate, configPath) overallLogPath := logPath + "/summary.log" diff --git a/backup/internal/rsync.go b/backup/internal/rsync.go index f5b39aa..03b12a6 100644 --- a/backup/internal/rsync.go +++ b/backup/internal/rsync.go @@ -3,6 +3,7 @@ package internal import ( "errors" "fmt" + "os" "path/filepath" "strings" ) @@ -37,6 +38,26 @@ func (c SharedCommand) RunWithArgs(job Job, args []string) JobStatus { return Success } +func (c SharedCommand) RunWithArgsAndCaptureOutput(job Job, args []string, logPath string) JobStatus { + c.PrintArgs(job, args) + + out, err := c.Shell.Execute(c.BinPath, args...) + + // Write output to log file for simulate commands + if logPath != "" { + writeErr := os.WriteFile(logPath, out, LogFilePermission) + if writeErr != nil { + fmt.Printf("Warning: Failed to write output to log file %s: %v\n", logPath, writeErr) + } + } + + if err != nil { + return Failure + } + + return Success +} + func (c SharedCommand) GetVersionInfo() (string, string, error) { rsyncPath := c.BinPath diff --git a/backup/internal/rsync_simulate.go b/backup/internal/rsync_simulate.go index ae1253c..ddcb527 100644 --- a/backup/internal/rsync_simulate.go +++ b/backup/internal/rsync_simulate.go @@ -12,7 +12,7 @@ func NewSimulateCommand(binPath string, logPath string) SimulateCommand { return SimulateCommand{ SharedCommand: SharedCommand{ BinPath: binPath, - BaseLogPath: logPath + "-sim", + BaseLogPath: logPath, Shell: &OsExec{}, }, } @@ -20,7 +20,8 @@ func NewSimulateCommand(binPath string, logPath string) SimulateCommand { func (c SimulateCommand) Run(job Job) JobStatus { logPath := fmt.Sprintf("%s/job-%s.log", c.BaseLogPath, job.Name) - args := ArgumentsForJob(job, logPath, true) + // Don't use --log-file in simulate mode as rsync doesn't log file changes to it in dry-run + args := ArgumentsForJob(job, "", true) - return c.RunWithArgs(job, args) + return c.RunWithArgsAndCaptureOutput(job, args, logPath) } diff --git a/backup/internal/test/helper_test.go b/backup/internal/test/helper_test.go index 42c3f54..03a7aa2 100644 --- a/backup/internal/test/helper_test.go +++ b/backup/internal/test/helper_test.go @@ -24,3 +24,21 @@ func TestNormalizePath(t *testing.T) { assert.Equal(t, test.expected, result) } } + +func TestCreateMainLogger_Title_IsPresent(t *testing.T) { + logger, logPath := CreateMainLogger("title", true) + assert.Contains(t, logPath, "title") + assert.NotNil(t, logger, "Logger should not be nil") +} + +func TestCreateMainLogger_IsSimulate_HasSimSuffix(t *testing.T) { + logger, logPath := CreateMainLogger("", true) + assert.Contains(t, logPath, "-sim") + assert.NotNil(t, logger, "Logger should not be nil") +} + +func TestCreateMainLogger_NotSimulate_HasNoSimSuffix(t *testing.T) { + logger, logPath := CreateMainLogger("", false) + assert.NotContains(t, logPath, "-sim") + assert.NotNil(t, logger, "Logger should not be nil") +} diff --git a/backup/internal/test/rsync_test.go b/backup/internal/test/rsync_test.go index 951ea1c..c06e0d8 100644 --- a/backup/internal/test/rsync_test.go +++ b/backup/internal/test/rsync_test.go @@ -123,12 +123,3 @@ func TestGetVersionInfo_IncompletePath(t *testing.T) { assert.Empty(t, versionInfo) assert.Empty(t, fullpath) } - -func TestNewSimulateCommand_BaseLogPath_ShallHaveSimSuffix(t *testing.T) { - binPath := "/usr/bin/simulate" - logPath := "/var/log/simulate" - - simulateCmd := NewSimulateCommand(binPath, logPath) - - assert.Equal(t, logPath+"-sim", simulateCmd.BaseLogPath) -}