• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

numtide / treefmt / 13989843597

21 Mar 2025 10:35AM UTC coverage: 33.547% (-0.7%) from 34.211%
13989843597

Pull #561

github

brianmcgee
wip: add a git-mergetool sub command

Partial implementation of #523.

Signed-off-by: Brian McGee <brian@bmcgee.ie>
Pull Request #561: wip: add a git-mergetool sub command

7 of 52 new or added lines in 3 files covered. (13.46%)

577 of 1720 relevant lines covered (33.55%)

13.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cmd/git_mergetool.go
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
// gitMergetool handles a 3-way merge using `git merge-file` and formats the resulting merged file.
15
// It expects 4 arguments: current, base, other, and merged filenames.
16
// Returns an error if the process fails or if arguments are invalid.
17
func gitMergetool(
18
        v *viper.Viper,
19
        statz *stats.Stats,
20
        cmd *cobra.Command,
21
        args []string,
NEW
22
) error {
×
NEW
23
        if len(args) != 4 {
×
NEW
24
                return fmt.Errorf("expected 4 arguments, got %d", len(args))
×
NEW
25
        }
×
26

NEW
27
        current := args[0]
×
NEW
28
        base := args[1]
×
NEW
29
        other := args[2]
×
NEW
30
        merged := args[3]
×
NEW
31

×
NEW
32
        // run treefmt on the first three arguments: current, base and other
×
NEW
33
        _, _ = fmt.Fprintf(os.Stderr, "formatting: %s, %s, %s\n\n", current, base, other)
×
NEW
34

×
NEW
35
        //nolint:wrapcheck
×
NEW
36
        if err := format.Run(v, statz, cmd, args[:3]); err != nil {
×
NEW
37
                return err
×
NEW
38
        }
×
39

40
        // open merge file
NEW
41
        mergeFile, err := os.OpenFile(merged, os.O_WRONLY|os.O_CREATE, 0o600)
×
NEW
42
        if err != nil {
×
NEW
43
                return fmt.Errorf("failed to open merge file: %w", err)
×
NEW
44
        }
×
45

46
        // merge current base and other
NEW
47
        merge := exec.Command("git", "merge-file", "--stdout", current, base, other)
×
NEW
48
        _, _ = fmt.Fprintf(os.Stderr, "\n%s\n", merge.String())
×
NEW
49

×
NEW
50
        // redirect stdout to the merge file
×
NEW
51
        merge.Stdout = mergeFile
×
NEW
52
        // capture stderr
×
NEW
53
        merge.Stderr = os.Stderr
×
NEW
54

×
NEW
55
        if err = merge.Run(); err != nil {
×
NEW
56
                return fmt.Errorf("failed to run git merge-file: %w", err)
×
NEW
57
        }
×
58

59
        // close the merge file
NEW
60
        if err = mergeFile.Close(); err != nil {
×
NEW
61
                return fmt.Errorf("failed to close temporary merge file: %w", err)
×
NEW
62
        }
×
63

64
        // format the merge file
NEW
65
        _, _ = fmt.Fprintf(os.Stderr, "formatting: %s\n\n", mergeFile.Name())
×
NEW
66

×
NEW
67
        if err = format.Run(v, stats.New(), cmd, []string{mergeFile.Name()}); err != nil {
×
NEW
68
                return fmt.Errorf("failed to format merged file: %w", err)
×
NEW
69
        }
×
70

NEW
71
        return nil
×
72
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc