package cmd import ( "fmt" "os" "path/filepath" "git.membo.co.uk/dtomlinson/gitlocal/internal/config" "git.membo.co.uk/dtomlinson/gitlocal/internal/git" "github.com/spf13/cobra" ) var revertAll bool var revertCmd = &cobra.Command{ Use: "revert [path]", Short: "Revert .gitlocal back to .git", Long: `Revert renames .gitlocal back to .git in the specified directory. If no path is provided, uses the current directory. Use --all to revert all tracked repositories from the config.`, Args: cobra.MaximumNArgs(1), RunE: runRevert, } func init() { revertCmd.Flags().BoolVarP(&revertAll, "all", "a", false, "Revert all tracked repositories") } func runRevert(cmd *cobra.Command, args []string) error { cfg, err := config.Load() if err != nil { return fmt.Errorf("failed to load config: %w", err) } if revertAll { return revertAllRepos(cfg) } // Determine target path targetPath := "." if len(args) > 0 { targetPath = args[0] } // Get absolute path absPath, err := filepath.Abs(targetPath) if err != nil { return fmt.Errorf("failed to get absolute path: %w", err) } return revertSingle(absPath, cfg) } func revertSingle(path string, cfg *config.Config) error { if !git.IsGitLocalRepo(path) { return fmt.Errorf("no .gitlocal directory found at %s", path) } if git.IsGitRepo(path) { return fmt.Errorf(".git already exists at %s", path) } // Revert if err := git.Revert(path); err != nil { return err } // Remove from config cfg.RemoveRepo(path) if err := cfg.Save(); err != nil { return fmt.Errorf("failed to save config: %w", err) } fmt.Printf("✓ Reverted: %s\n", path) return nil } func revertAllRepos(cfg *config.Config) error { if len(cfg.Repos) == 0 { fmt.Println("No repositories to revert") return nil } fmt.Printf("Reverting %d repositories\n\n", len(cfg.Repos)) reverted := 0 failed := 0 // Create a copy of repos to iterate over, since we'll be modifying the config repos := make([]config.Repo, len(cfg.Repos)) copy(repos, cfg.Repos) for _, repo := range repos { if !git.IsGitLocalRepo(repo.Path) { fmt.Fprintf(os.Stderr, "⊘ Skipped (no .gitlocal found): %s\n", repo.Path) // Remove from config even if .gitlocal doesn't exist cfg.RemoveRepo(repo.Path) continue } if git.IsGitRepo(repo.Path) { fmt.Fprintf(os.Stderr, "⊘ Skipped (.git exists): %s\n", repo.Path) continue } if err := git.Revert(repo.Path); err != nil { fmt.Fprintf(os.Stderr, "✗ Failed to revert %s: %v\n", repo.Path, err) failed++ continue } cfg.RemoveRepo(repo.Path) fmt.Printf("✓ Reverted: %s\n", repo.Path) reverted++ } if err := cfg.Save(); err != nil { return fmt.Errorf("failed to save config: %w", err) } fmt.Printf("\nSuccessfully reverted %d repositories", reverted) if failed > 0 { fmt.Printf(" (%d failed)", failed) } fmt.Println() return nil }