1package cli
2
3import (
4 "fmt"
5 "os"
6
7 "arche/internal/gitcompat"
8 "arche/internal/object"
9 "arche/internal/wc"
10
11 "github.com/spf13/cobra"
12)
13
14var coCmd = &cobra.Command{
15 Use: "co <change-id|hash|bookmark>",
16 Aliases: []string{"checkout", "switch"},
17 Short: "Check out a commit by change ID, hash prefix, or bookmark",
18 Long: `Update the working directory to reflect the named commit. HEAD is updated to
19that commit's change ID. Since HEAD always contains a change ID (never a
20bookmark name), there is no "detached HEAD" state - every checkout is
21structurally identical.`,
22 Args: cobra.ExactArgs(1),
23 RunE: func(cmd *cobra.Command, args []string) error {
24 r := openRepo()
25 defer r.Close()
26
27 commitID, err := resolveRef(r, args[0])
28 if err != nil {
29 return err
30 }
31
32 c, err := r.ReadCommit(commitID)
33 if err != nil {
34 return err
35 }
36
37 w := wc.New(r)
38 newChangeID := object.FormatChangeID(c.ChangeID)
39 if err := w.Materialize(c.TreeID, newChangeID); err != nil {
40 return fmt.Errorf("materialize: %w", err)
41 }
42
43 if err := r.WriteHead(newChangeID); err != nil {
44 return err
45 }
46
47 if r.Cfg.Git.Enabled {
48 if err := gitcompat.CheckoutCommit(r.Root, r.ArcheDir(), commitID); err != nil {
49 fmt.Fprintf(os.Stderr, "arche: git checkout failed: %v\n", err)
50 }
51 }
52
53 fmt.Printf("Checked out ch:%s -- %s\n", c.ChangeID, c.Message)
54 bms, _ := r.Store.ListBookmarks()
55 var hasBM bool
56 for _, bm := range bms {
57 if bm.CommitID == commitID {
58 hasBM = true
59 fmt.Printf(" (bookmark: %s)\n", bm.Name)
60 }
61 }
62 if !hasBM {
63 fmt.Println(" No bookmark points here. Create one with: arche bookmark set <name>")
64 }
65 return nil
66 },
67}