Skip to content

Commit a06e4e3

Browse files
committed
Completed MVP. Needs testing.
- Renamed list package to ls. - Added rm command. - Added mv command. - Refactored command exit handling. - Updated README.
1 parent 6b8fb37 commit a06e4e3

File tree

9 files changed

+344
-27
lines changed

9 files changed

+344
-27
lines changed

README.md

+22-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
Git Extension For Worktree Management
44

5+
## Caveat Emptor
6+
7+
This is very new code. It has not had extensive testing. Use in full knowledge
8+
there may be bugs.
9+
510
## Purpose
611

712
This helper is intended to assist in managing git worktrees in a workflow based
@@ -26,6 +31,10 @@ Commands are:
2631
- List the worktrees in the project.
2732
- `mk`
2833
- Add a worktree to the project.
34+
- `mv`
35+
- Move a worktree within the project.
36+
- `rm`
37+
- Remove a worktree from the project.
2938

3039
## Project Layout
3140

@@ -47,15 +56,16 @@ graph TD
4756
## Git Worktree Coverage
4857

4958
The goal is to cover the `git worktree` commands essential to a worktree-based
50-
workflow. Not every command is likely to be implemented.
51-
52-
| Git Worktree Command | git-wt Command | Notes |
53-
| -------------------- | -------------- | ----------------------- |
54-
| list | ls | No arguments supported. |
55-
| add | mk | Not implemented yet. |
56-
| remove | rm | Not implemented yet. |
57-
| move | mv | Not implemented yet. |
58-
| prune | tbd | Under review. |
59-
| lock | n/a | No intent to implement. |
60-
| unlock | n/a | No intent to implement. |
61-
| repair | n/a | No intent to implement. |
59+
workflow. Not every command is likely to be implemented, or implemented with all
60+
possible flags.
61+
62+
| Git Worktree Command | git-wt Command | Notes |
63+
| -------------------- | -------------- | ----------------------------------------- |
64+
| list | ls | No arguments supported. |
65+
| add | mk | Does not implement locks or guess-remote. |
66+
| remove | rm | Full implementation. |
67+
| move | mv | Full implementation. |
68+
| prune | tbd | Under review. |
69+
| lock | n/a | No intent to implement. |
70+
| unlock | n/a | No intent to implement. |
71+
| repair | n/a | No intent to implement. |

internal/cmn/cmn.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ import (
99
"slices"
1010
)
1111

12+
type (
13+
CfgMk struct {
14+
Branch string
15+
BranchReset string
16+
CheckoutNo bool
17+
Force bool
18+
Track bool
19+
Quiet bool
20+
} // Configuration for 'mk' command.
21+
22+
CfgRm struct {
23+
Force bool
24+
} // Configuration for 'rm' command.
25+
26+
CfgMv struct {
27+
Force bool
28+
} // Configuration for 'mv' command.
29+
)
30+
1231
var (
1332
Basename string // Base name of the program; injected during compile.
1433
Version string // Version of the program; injected during compile.
@@ -95,7 +114,7 @@ func walkUpTree(path string) (string, error) {
95114
continue
96115
} else {
97116
ProjectDir = target
98-
Debug("%s: project dir: %s", funcName, ProjectDir)
117+
Debug("%s: project dir: %s\n", funcName, ProjectDir)
99118
Debug("%s: end\n", funcName)
100119
return filename, nil
101120
}

internal/cobra/cl/command.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func run(cmd *cobra.Command, args []string) error {
3434
cmn.Debug("%s: %s: retrieving default branch from remote\n", command, funcName)
3535
defaultBranch, err := git.GetDefaultBranch(args[0])
3636
if err != nil {
37-
cmn.Exit(11, "could not retrieve default branch: %v", err.Error())
37+
return fmt.Errorf("could not retrieve default branch: %v", err.Error())
3838
}
3939
cmn.Debug("%s: run: defaultBranch: %v\n", command, defaultBranch)
4040

@@ -46,13 +46,13 @@ func run(cmd *cobra.Command, args []string) error {
4646
// Clone the repository.
4747
err = git.Clone(args[0], defaultBranch, clonePath)
4848
if err != nil {
49-
cmn.Exit(12, "could not clone repo: %v", err.Error())
49+
return fmt.Errorf("could not clone repo: %v", err.Error())
5050
}
5151

5252
// Write config file to project path.
5353
err = cmn.WriteConfig(repo, defaultBranch)
5454
if err != nil {
55-
cmn.Exit(13, "error writing config file: %v", err.Error())
55+
return fmt.Errorf("error writing config file: %v", err.Error())
5656
}
5757

5858
fmt.Printf("Clone complete.\n")

internal/cobra/list/command.go internal/cobra/ls/command.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Package list implements the list subcommand for git-wt.
2-
package list
2+
package ls
33

44
import (
55
"fmt"
@@ -27,7 +27,7 @@ func run(cmd *cobra.Command, args []string) error {
2727

2828
output, err := git.WorktreeList()
2929
if err != nil {
30-
cmn.Exit(20, "error listing worktrees: %s", err.Error())
30+
return fmt.Errorf("error listing worktrees: %s", err.Error())
3131
}
3232
fmt.Print(string(output))
3333

internal/cobra/mk/command.go

+61-5
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,83 @@
22
package mk
33

44
import (
5+
"fmt"
6+
57
"github.com/jason-dour/git-wt/internal/cmn"
8+
"github.com/jason-dour/git-wt/internal/git"
69
"github.com/spf13/cobra"
710
)
811

912
var (
10-
command = "mk" // Command name.
11-
Cmd = &cobra.Command{
12-
Use: command + " repo_url",
13+
command = "mk" // Command name.
14+
config *cmn.CfgMk = &cmn.CfgMk{} // Configuration for the command.
15+
Cmd = &cobra.Command{
16+
Use: command + " worktree_name commit-ish",
1317
Short: "Add a worktree to the project.",
1418
Long: cmn.Basename + " " + command + " - Add a worktree to the project.",
15-
Args: cobra.ExactArgs(1),
19+
Args: cobra.ExactArgs(2),
1620
Aliases: []string{"make"},
1721
RunE: run,
18-
} // Cobra command definition for the 'clone' command.
22+
} // Cobra command definition for the 'mk' command.
1923
)
2024

25+
// init performs initialization for the 'mk' command.
26+
func init() {
27+
Cmd.PersistentFlags().BoolVar(&config.Track, "track", false, "set up tracking mode")
28+
Cmd.PersistentFlags().StringVarP(&config.Branch, "b", "b", "", "create a new branch")
29+
Cmd.PersistentFlags().StringVarP(&config.BranchReset, "B", "B", "", "create or reset a branch")
30+
Cmd.PersistentFlags().BoolVar(&config.CheckoutNo, "no-checkout", false, "do not populate the new worktree")
31+
Cmd.PersistentFlags().BoolVarP(&config.Force, "force", "f", false, "checkout <branch> even if already checked out in other worktree")
32+
Cmd.PersistentFlags().BoolVarP(&config.Quiet, "quiet", "q", false, "suppress progress reporting")
33+
}
34+
35+
// checkConfig scans config for proper use of flags.
36+
func checkConfig(args []string) error {
37+
funcName := "checkConfig"
38+
cmn.Debug("%s: %s: begin\n", command, funcName)
39+
40+
cmn.Debug("%s: %s: check mutually exclusive branch flags\n", command, funcName)
41+
if len(config.Branch) > 0 && len(config.BranchReset) > 0 {
42+
return fmt.Errorf("config: set branch with either -b or -B; don't use both")
43+
}
44+
45+
cmn.Debug("%s: %s: check track has a new branch in flags\n", command, funcName)
46+
if config.Track && !(len(config.Branch) > 0 || len(config.BranchReset) > 0) {
47+
return fmt.Errorf("config: track requires new branch via -b or -B")
48+
}
49+
50+
cmn.Debug("%s: %s: end\n", command, funcName)
51+
return nil
52+
}
53+
54+
// run provides the core execution of the 'mk' command.
2155
func run(cmd *cobra.Command, args []string) error {
2256
funcName := "run"
2357
cmn.Debug("%s: %s: begin\n", command, funcName)
58+
cmn.Debug("%s: %s: config: %#v\n", command, funcName, config)
2459
cmn.Debug("%s: %s: args: %v\n", command, funcName, args)
2560

61+
// Set the worktree name.
62+
wtName := args[0]
63+
cmn.Debug("%s: %s: worktree name: %s\n", command, funcName, wtName)
64+
65+
// Set the commit-ish to be used.
66+
commitish := args[1]
67+
cmn.Debug("%s: %s: commit-ish: %s\n", command, funcName, commitish)
68+
69+
// Check configuration.
70+
err := checkConfig(args)
71+
if err != nil {
72+
return err
73+
}
74+
75+
// Add the worktree.
76+
output, err := git.WorktreeAdd(config, wtName, commitish)
77+
if err != nil {
78+
return err
79+
}
80+
fmt.Print(string(output))
81+
2682
cmn.Debug("%s: %s: end\n", command, funcName)
2783
return nil
2884
}

internal/cobra/mv/command.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Package mv implements the mv subcommand for git-wt.
2+
package mv
3+
4+
import (
5+
"fmt"
6+
7+
"github.com/jason-dour/git-wt/internal/cmn"
8+
"github.com/jason-dour/git-wt/internal/git"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var (
13+
command = "mv" // Command name.
14+
config *cmn.CfgMv = &cmn.CfgMv{} // Configuration for the command.
15+
Cmd = &cobra.Command{
16+
Use: command + " worktree-name new-worktree-name",
17+
Short: "Move a worktree within the project.",
18+
Long: cmn.Basename + " " + command + " - Move a worktree within the project.",
19+
Args: cobra.ExactArgs(2),
20+
Aliases: []string{"move", "ren", "rename"},
21+
RunE: run,
22+
} // Cobra command definition for the 'mv' command.
23+
)
24+
25+
// init performs initialization for the 'mv' command.
26+
func init() {
27+
Cmd.PersistentFlags().BoolVarP(&config.Force, "force", "f", false, "force move even if worktree is dirty or locked")
28+
}
29+
30+
// run provides the core execution of the 'mv' command.
31+
func run(cmd *cobra.Command, args []string) error {
32+
funcName := "run"
33+
cmn.Debug("%s: %s: begin\n", command, funcName)
34+
cmn.Debug("%s: %s: config: %#v\n", command, funcName, config)
35+
cmn.Debug("%s: %s: args: %v\n", command, funcName, args)
36+
37+
// Set the worktree current name.
38+
wtCurr := args[0]
39+
cmn.Debug("%s: %s: worktree name: %s\n", command, funcName, wtCurr)
40+
41+
// Set the worktree current name.
42+
wtNew := args[1]
43+
cmn.Debug("%s: %s: new worktree name: %s\n", command, funcName, wtNew)
44+
45+
// Remove the worktree.
46+
output, err := git.WorktreeMove(config, wtCurr, wtNew)
47+
if err != nil {
48+
return err
49+
}
50+
fmt.Print(string(output))
51+
52+
cmn.Debug("%s: %s: end\n", command, funcName)
53+
return nil
54+
}

internal/cobra/rm/command.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Package rm implements the rm subcommand for git-wt.
2+
package rm
3+
4+
import (
5+
"fmt"
6+
7+
"github.com/jason-dour/git-wt/internal/cmn"
8+
"github.com/jason-dour/git-wt/internal/git"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var (
13+
command = "rm" // Command name.
14+
config *cmn.CfgRm = &cmn.CfgRm{} // Configuration for the command.
15+
Cmd = &cobra.Command{
16+
Use: command,
17+
Short: "Remove a worktree from the project.",
18+
Long: cmn.Basename + " " + command + " - Remove a worktree from the project.",
19+
Args: cobra.ExactArgs(1),
20+
Aliases: []string{"remove", "del", "delete"},
21+
RunE: run,
22+
} // Cobra command definition for the 'rm' command.
23+
)
24+
25+
// init performs initialization for the 'rm' command.
26+
func init() {
27+
Cmd.PersistentFlags().BoolVarP(&config.Force, "force", "f", false, "force removal even if worktree is dirty or locked")
28+
}
29+
30+
// run provides the core execution of the 'rm' command.
31+
func run(cmd *cobra.Command, args []string) error {
32+
funcName := "run"
33+
cmn.Debug("%s: %s: begin\n", command, funcName)
34+
cmn.Debug("%s: %s: config: %#v\n", command, funcName, config)
35+
cmn.Debug("%s: %s: args: %v\n", command, funcName, args)
36+
37+
// Set the worktree name.
38+
wtName := args[0]
39+
cmn.Debug("%s: %s: worktree name: %s\n", command, funcName, wtName)
40+
41+
// Remove the worktree.
42+
output, err := git.WorktreeRemove(config, wtName)
43+
if err != nil {
44+
return err
45+
}
46+
fmt.Print(string(output))
47+
48+
cmn.Debug("%s: %s: end\n", command, funcName)
49+
return nil
50+
}

internal/cobra/root/command.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ package root
44
import (
55
"github.com/jason-dour/git-wt/internal/cmn"
66
"github.com/jason-dour/git-wt/internal/cobra/cl"
7-
"github.com/jason-dour/git-wt/internal/cobra/list"
7+
"github.com/jason-dour/git-wt/internal/cobra/ls"
88
"github.com/jason-dour/git-wt/internal/cobra/mk"
9+
"github.com/jason-dour/git-wt/internal/cobra/mv"
10+
"github.com/jason-dour/git-wt/internal/cobra/rm"
911
"github.com/spf13/cobra"
1012
)
1113

@@ -26,7 +28,9 @@ func init() {
2628
Cmd.PersistentFlags().BoolVarP(&cmn.DebugFlag, "debug", "d", false, "enable debug mode")
2729

2830
// Sub-Commands
29-
Cmd.AddCommand(mk.Cmd)
3031
Cmd.AddCommand(cl.Cmd)
31-
Cmd.AddCommand(list.Cmd)
32+
Cmd.AddCommand(ls.Cmd)
33+
Cmd.AddCommand(mk.Cmd)
34+
Cmd.AddCommand(mv.Cmd)
35+
Cmd.AddCommand(rm.Cmd)
3236
}

0 commit comments

Comments
 (0)