|
| 1 | +package checkpoint |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "fmt" |
| 6 | + "os/exec" |
| 7 | + "strings" |
| 8 | + |
| 9 | + "github.com/spf13/cobra" |
| 10 | + "go.devnw.com/canary/internal/storage" |
| 11 | + "go.devnw.com/canary/cli/internal/utils" |
| 12 | +) |
| 13 | + |
| 14 | +// CANARY: REQ=CBIN-128; FEATURE="CheckpointCmd"; ASPECT=CLI; STATUS=IMPL; OWNER=canary; UPDATED=2025-10-16 |
| 15 | +var CheckpointCmd = &cobra.Command{ |
| 16 | + Use: "checkpoint <name> [description]", |
| 17 | + Short: "Create a state snapshot checkpoint", |
| 18 | + Long: `Create a checkpoint to capture current state of all tokens. |
| 19 | +
|
| 20 | +Checkpoints include: |
| 21 | +- Counts by status (STUB, IMPL, TESTED, BENCHED) |
| 22 | +- Commit hash and timestamp |
| 23 | +- Full JSON snapshot of all tokens |
| 24 | +
|
| 25 | +Useful for tracking progress over time.`, |
| 26 | + Args: cobra.MinimumNArgs(1), |
| 27 | + RunE: func(cmd *cobra.Command, args []string) error { |
| 28 | + dbPath, _ := cmd.Flags().GetString("db") |
| 29 | + name := args[0] |
| 30 | + description := "" |
| 31 | + if len(args) > 1 { |
| 32 | + description = strings.Join(args[1:], " ") |
| 33 | + } |
| 34 | + |
| 35 | + db, err := storage.Open(dbPath) |
| 36 | + if err != nil { |
| 37 | + return fmt.Errorf("open database: %w", err) |
| 38 | + } |
| 39 | + |
| 40 | + defer db.Close() |
| 41 | + |
| 42 | + // Get current commit hash |
| 43 | + commitHash := "" |
| 44 | + if gitCmd := exec.Command("git", "rev-parse", "HEAD"); gitCmd.Dir == "" { |
| 45 | + if output, err := gitCmd.Output(); err == nil { |
| 46 | + commitHash = strings.TrimSpace(string(output)) |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + // Load project config for ID pattern filtering |
| 51 | + cfg, _ := utils.LoadProjectConfig() |
| 52 | + idPattern := "" |
| 53 | + if cfg != nil && cfg.Requirements.IDPattern != "" { |
| 54 | + idPattern = cfg.Requirements.IDPattern |
| 55 | + } |
| 56 | + |
| 57 | + // Get all tokens for snapshot |
| 58 | + tokens, err := db.ListTokens(nil, idPattern, "", 0) |
| 59 | + if err != nil { |
| 60 | + return fmt.Errorf("get tokens: %w", err) |
| 61 | + } |
| 62 | + |
| 63 | + snapshotJSON, err := json.Marshal(tokens) |
| 64 | + if err != nil { |
| 65 | + return fmt.Errorf("marshal snapshot: %w", err) |
| 66 | + } |
| 67 | + |
| 68 | + if err := db.CreateCheckpoint(name, description, commitHash, string(snapshotJSON)); err != nil { |
| 69 | + return fmt.Errorf("create checkpoint: %w", err) |
| 70 | + } |
| 71 | + |
| 72 | + fmt.Printf("✅ Created checkpoint: %s\n", name) |
| 73 | + if commitHash != "" { |
| 74 | + fmt.Printf("Commit: %s\n", commitHash[:8]) |
| 75 | + } |
| 76 | + fmt.Printf("Tokens: %d\n", len(tokens)) |
| 77 | + |
| 78 | + return nil |
| 79 | + }, |
| 80 | +} |
0 commit comments