diff options
| -rw-r--r-- | cmd/gitsyncer/main.go | 46 | ||||
| -rw-r--r-- | internal/cli/flags.go | 19 | ||||
| -rw-r--r-- | internal/state/state.go | 79 | ||||
| -rw-r--r-- | internal/version/version.go | 2 |
4 files changed, 145 insertions, 1 deletions
diff --git a/cmd/gitsyncer/main.go b/cmd/gitsyncer/main.go index 9828776..f27cff6 100644 --- a/cmd/gitsyncer/main.go +++ b/cmd/gitsyncer/main.go @@ -6,8 +6,23 @@ import ( "path/filepath" "codeberg.org/snonux/gitsyncer/internal/cli" + "codeberg.org/snonux/gitsyncer/internal/state" ) +// saveBatchRunState saves the batch run timestamp if this is a batch run +func saveBatchRunState(flags *cli.Flags) { + if flags.BatchRun && flags.BatchRunStateManager != nil && flags.BatchRunState != nil { + flags.BatchRunState.UpdateBatchRunTime() + if err := flags.BatchRunStateManager.Save(flags.BatchRunState); err != nil { + fmt.Fprintf(os.Stderr, "Warning: Failed to save batch run state: %v\n", err) + } else { + stateFile := filepath.Join(flags.WorkDir, ".gitsyncer-state.json") + fmt.Printf("Batch run completed successfully. State saved to: %s\n", stateFile) + fmt.Println("Next batch run allowed after one week.") + } + } +} + func main() { // Parse command-line flags flags := cli.ParseFlags() @@ -43,6 +58,32 @@ func main() { flags.WorkDir = cfg.WorkDir } + // Handle --batch-run flag: check if it has run within the past week + if flags.BatchRun { + stateManager := state.NewManager(flags.WorkDir) + s, err := stateManager.Load() + if err != nil { + fmt.Fprintf(os.Stderr, "Warning: Failed to load state: %v\n", err) + // Continue anyway on first run + } + + if s.HasRunWithinWeek() { + fmt.Printf("Batch run was already executed within the past week (last run: %s).\n", s.LastBatchRun.Format("2006-01-02 15:04:05")) + stateFile := filepath.Join(flags.WorkDir, ".gitsyncer-state.json") + fmt.Printf("State file location: %s\n", stateFile) + fmt.Println("Skipping batch run. Use --full and --showcase directly to force execution.") + os.Exit(0) + } + + // If we get here, we can proceed with the batch run + fmt.Println("Starting weekly batch run (--full --showcase)...") + + // Update the state to record this batch run (we'll save it after successful completion) + // Store the state manager for later use + flags.BatchRunStateManager = stateManager + flags.BatchRunState = s + } + // Handle delete repository flag if flags.DeleteRepo != "" { os.Exit(cli.HandleDeleteRepo(cfg, flags.DeleteRepo)) @@ -108,6 +149,11 @@ func main() { } } + // Save batch run state if this was a successful batch run + if exitCode == 0 { + saveBatchRunState(flags) + } + os.Exit(exitCode) } diff --git a/internal/cli/flags.go b/internal/cli/flags.go index 7640398..3a9990f 100644 --- a/internal/cli/flags.go +++ b/internal/cli/flags.go @@ -4,6 +4,8 @@ import ( "flag" "os" "path/filepath" + + "codeberg.org/snonux/gitsyncer/internal/state" ) // Flags holds all command-line flag values @@ -27,6 +29,11 @@ type Flags struct { Backup bool Showcase bool Force bool + BatchRun bool + + // Internal fields for batch run state management (not set by flags) + BatchRunStateManager *state.Manager + BatchRunState *state.State } // ParseFlags parses command-line flags and returns the flags struct @@ -54,6 +61,7 @@ func ParseFlags() *Flags { flag.BoolVar(&f.Backup, "backup", false, "enable syncing to backup locations") flag.BoolVar(&f.Showcase, "showcase", false, "generate project showcase using Claude after syncing") flag.BoolVar(&f.Force, "force", false, "force regeneration of cached data") + flag.BoolVar(&f.BatchRun, "batch-run", false, "enable --full and --showcase (runs only once per week)") flag.Parse() @@ -76,5 +84,16 @@ func ParseFlags() *Flags { f.CreateCodebergRepos = true } + // Handle --batch-run flag by enabling --full and --showcase + if f.BatchRun { + f.FullSync = true + f.Showcase = true + // Since we set FullSync, it will trigger the above logic too + f.SyncCodebergPublic = true + f.SyncGitHubPublic = true + f.CreateGitHubRepos = true + f.CreateCodebergRepos = true + } + return f }
\ No newline at end of file diff --git a/internal/state/state.go b/internal/state/state.go new file mode 100644 index 0000000..af90879 --- /dev/null +++ b/internal/state/state.go @@ -0,0 +1,79 @@ +package state + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "time" +) + +// State represents the persistent state of gitsyncer +type State struct { + LastBatchRun time.Time `json:"lastBatchRun"` +} + +// Manager handles state persistence +type Manager struct { + filePath string +} + +// NewManager creates a new state manager +func NewManager(workDir string) *Manager { + return &Manager{ + filePath: filepath.Join(workDir, ".gitsyncer-state.json"), + } +} + +// Load reads the state from disk +func (m *Manager) Load() (*State, error) { + data, err := os.ReadFile(m.filePath) + if err != nil { + if os.IsNotExist(err) { + // Return empty state if file doesn't exist + return &State{}, nil + } + return nil, fmt.Errorf("failed to read state file: %w", err) + } + + var state State + if err := json.Unmarshal(data, &state); err != nil { + return nil, fmt.Errorf("failed to parse state file: %w", err) + } + + return &state, nil +} + +// Save writes the state to disk +func (m *Manager) Save(state *State) error { + data, err := json.MarshalIndent(state, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal state: %w", err) + } + + // Ensure directory exists + dir := filepath.Dir(m.filePath) + if err := os.MkdirAll(dir, 0755); err != nil { + return fmt.Errorf("failed to create state directory: %w", err) + } + + // Write state file + if err := os.WriteFile(m.filePath, data, 0644); err != nil { + return fmt.Errorf("failed to write state file: %w", err) + } + + return nil +} + +// HasRunWithinWeek checks if the last batch run was within the past week +func (s *State) HasRunWithinWeek() bool { + if s.LastBatchRun.IsZero() { + return false + } + return time.Since(s.LastBatchRun) < 7*24*time.Hour +} + +// UpdateBatchRunTime updates the last batch run timestamp to now +func (s *State) UpdateBatchRunTime() { + s.LastBatchRun = time.Now() +}
\ No newline at end of file diff --git a/internal/version/version.go b/internal/version/version.go index e817f13..03181e4 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -7,7 +7,7 @@ import ( var ( // Version is the current version of gitsyncer - Version = "0.4.0" + Version = "0.5.0" // GitCommit is the git commit hash at build time GitCommit = "unknown" |
