arche / internal/cli/cmd_co.go

commit 154431fd
 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}