162 lines
2.8 KiB
Go
162 lines
2.8 KiB
Go
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)
|
|
}
|
|
}
|