Skip to content

Commit 16ce100

Browse files
committed
wip: add a git-mergetool sub command
Partial implementation of #523. Signed-off-by: Brian McGee <brian@bmcgee.ie>
1 parent 3ba936c commit 16ce100

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

cmd/git_mergetool.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
8+
"github.com/numtide/treefmt/v2/cmd/format"
9+
"github.com/numtide/treefmt/v2/stats"
10+
"github.com/spf13/cobra"
11+
"github.com/spf13/viper"
12+
)
13+
14+
func gitMergetool(
15+
v *viper.Viper,
16+
statz *stats.Stats,
17+
cmd *cobra.Command,
18+
args []string,
19+
) error {
20+
if len(args) != 4 {
21+
return fmt.Errorf("expected 4 arguments, got %d", len(args))
22+
}
23+
24+
//nolint:wrapcheck
25+
// run treefmt on the first three arguments: current, base and other
26+
if err := format.Run(v, statz, cmd, args[:3]); err != nil {
27+
return err
28+
}
29+
30+
// run `git merge-file` and redirect it's output to the fourth argument: merged
31+
merged, err := os.CreateTemp("", "treefmt-git-mergetool-*")
32+
if err != nil {
33+
return fmt.Errorf("failed to create temporary merge file: %w", err)
34+
}
35+
36+
// remove when we're done
37+
defer os.Remove(merged.Name())
38+
39+
//nolint:gosec
40+
merge := exec.Command("git", "merge-file", "--stdout", args[0], args[1], args[2])
41+
// redirect stdout to the temporary merge file
42+
merge.Stdout = merged
43+
// capture stderr
44+
merge.Stderr = os.Stderr
45+
46+
if err = merge.Run(); err != nil {
47+
return fmt.Errorf("failed to run git merge-file: %w", err)
48+
}
49+
50+
// close the merged file
51+
if err = merged.Close(); err != nil {
52+
return fmt.Errorf("failed to close temporary merge file: %w", err)
53+
}
54+
55+
// format the merged file
56+
if err = format.Run(v, statz, cmd, []string{merged.Name()}); err != nil {
57+
return fmt.Errorf("failed to format merged file: %w", err)
58+
}
59+
60+
// rename temp merge file
61+
if err = os.Rename(merged.Name(), args[3]); err != nil {
62+
return fmt.Errorf("failed to rename temporary merge file: %w", err)
63+
}
64+
65+
return nil
66+
}

cmd/root.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ func NewRoot() (*cobra.Command, *stats.Stats) {
7070
"[bash|zsh|fish] Generate shell completion scripts for the specified shell.",
7171
)
7272

73+
// add a flag for git merge tool sub command
74+
fs.Bool("git-mergetool", false, "Use treefmt as a git merge tool.")
75+
7376
// bind our command's flags to viper
7477
if err := v.BindPFlags(fs); err != nil {
7578
cobra.CheckErr(fmt.Errorf("failed to bind global config to viper: %w", err))
@@ -175,6 +178,13 @@ func runE(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, args []string)
175178
}
176179
}
177180

181+
// git mergetool
182+
if merge, err := flags.GetBool("git-mergetool"); err != nil {
183+
cobra.CheckErr(fmt.Errorf("failed to read git-mergetool flag: %w", err))
184+
} else if merge {
185+
return gitMergetool(v, statz, cmd, args)
186+
}
187+
178188
// format
179189
return format.Run(v, statz, cmd, args) //nolint:wrapcheck
180190
}

0 commit comments

Comments
 (0)