package main import ( "context" "fmt" "log" "os" "os/exec" "path/filepath" "strings" "github.com/urfave/cli/v3" ) func exists(path string) bool { _, err := os.Stat(path) return !os.IsNotExist(err) } func Getwtd() (string, error) { hd, err := os.UserHomeDir() if err != nil { return "", err } wtd := filepath.Join(hd, ".wt") if !exists(wtd) { if err := os.Mkdir(wtd, 0o755); err != nil { return "", err } } return wtd, nil } func GetWorktree(cwd string, name string) (string, error) { wtd, err := Getwtd() if err != nil { return "", err } project := filepath.Base(cwd) return filepath.Join(wtd, project, name), nil } func Init(ctx context.Context, cmd *cli.Command) error { fmt.Println("init") cwd, err := os.Getwd() if err != nil { return err } wtd, err := Getwtd() if err != nil { return err } if cmd.Args().Get(0) != "" { cwd, err = filepath.Abs(cmd.Args().Get(0)) if err != nil { return err } } if !exists(cwd) { return fmt.Errorf("%s does not exists", cwd) } project := filepath.Join(wtd, filepath.Base(cwd)) if !exists(project) { if err := os.Mkdir(project, 0o755); err != nil { return err } c := exec.Command("git", "branch", "--show-current") c.Dir = cwd out, err := c.Output() if err != nil { return err } branch := strings.TrimSpace(string(out)) worktree := filepath.Join(project, branch) if err := os.Rename(cwd, worktree); err != nil { return err } if err := os.Symlink(worktree, cwd); err != nil { return err } } return nil } func Switch(ctx context.Context, cmd *cli.Command) error { branch := strings.TrimSpace(cmd.Args().Get(0)) if len(branch) == 0 { return fmt.Errorf("no worktree name given") } cwd, err := os.Getwd() if err != nil { return err } worktree, err := GetWorktree(cwd, branch) if err != nil { return err } if !exists(worktree) { if err := exec.Command("git", "worktree", "add", worktree, branch).Run(); err != nil { return err } } if _, err := os.Lstat(cwd); err == nil { if err := os.Remove(cwd); err != nil { return err } } return os.Symlink(worktree, cwd) } func List(ctx context.Context, cmd *cli.Command) error { wtd, err := Getwtd() if err != nil { return err } project, err := os.Getwd() if err != nil { return err } dirs, err := os.ReadDir(filepath.Join(wtd, filepath.Base(project))) if err != nil { return err } for i := range dirs { fmt.Println(dirs[i].Name()) } return nil } func main() { cmd := cli.Command{ Name: "wt", Commands: []*cli.Command{ { Name: "init", Action: Init, }, { Name: "clone", }, { Name: "list", Action: List, }, { Name: "switch", Action: Switch, }, }, } if err := cmd.Run(context.Background(), os.Args); err != nil { log.Fatal(err) } }