Skip to content

Commit a9a96c3

Browse files
authored
Merge pull request #1499 from merico-dev/new-dtm
Feat: Add `dtm commit -m` Command Implementation
2 parents f494c0a + 22081de commit a9a96c3

File tree

7 files changed

+173
-26
lines changed

7 files changed

+173
-26
lines changed

cmd/commit.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/spf13/cobra"
7+
"github.com/spf13/viper"
8+
9+
"github.com/devstream-io/devstream/internal/log"
10+
"github.com/devstream-io/devstream/internal/pkg/commit"
11+
"github.com/devstream-io/devstream/internal/response"
12+
)
13+
14+
// commitCmd represents the commit command
15+
var commitCmd = &cobra.Command{
16+
Use: "commit",
17+
Short: "commit is used to execute git commit operations",
18+
Long: `commit is used to execute git commit operations
19+
20+
e.g.
21+
22+
1. dtm commit -m "commit message"
23+
`,
24+
Run: func(cmd *cobra.Command, args []string) {
25+
message := viper.GetString("message")
26+
if message == "" {
27+
log.Error("message is required")
28+
os.Exit(1)
29+
}
30+
err := commit.Commit(message)
31+
if err != nil {
32+
log.Errorf("commit error: %v", err)
33+
r := response.New(response.StatusError, response.MessageError, err.Error())
34+
r.Print(OutputFormat)
35+
} else {
36+
r := response.New(response.StatusOK, response.MessageOK, "")
37+
r.Print(OutputFormat)
38+
}
39+
},
40+
}
41+
42+
func init() {
43+
rootCmd.AddCommand(commitCmd)
44+
commitCmd.Flags().StringP("message", "m", "", "commit message")
45+
}

cmd/patch.go

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
/*
2-
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
3-
*/
41
package cmd
52

63
import (
@@ -32,15 +29,15 @@ e.g.
3229
log.Error("Incorrect number of arguments")
3330
os.Exit(1)
3431
}
35-
err := patch.Patch(".", args[0])
32+
err := patch.Patch(args[0])
3633
if err != nil {
37-
log.Error(err)
34+
log.Errorf("patch error: %v", err)
3835
r := response.New(response.StatusError, response.MessageError, err.Error())
3936
r.Print(OutputFormat)
40-
os.Exit(1)
37+
} else {
38+
r := response.New(response.StatusOK, response.MessageOK, "")
39+
r.Print(OutputFormat)
4140
}
42-
r := response.New(response.StatusOK, response.MessageOK, "")
43-
r.Print(OutputFormat)
4441
},
4542
}
4643

cmd/scaffold.go

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
/*
2-
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
3-
*/
41
package cmd
52

63
import (

internal/pkg/commit/commit.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package commit
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
"strings"
7+
8+
"github.com/devstream-io/devstream/internal/log"
9+
)
10+
11+
// Commit is used to execute git commit operations
12+
func Commit(message string) error {
13+
// Check if the git command exists
14+
gitPath, err := exec.LookPath("git")
15+
if err != nil {
16+
return fmt.Errorf("git command not found: %w", err)
17+
}
18+
19+
cmd := exec.Command(gitPath, "commit", "-m", message)
20+
output, err := cmd.CombinedOutput()
21+
outputStr := strings.TrimSpace(string(output))
22+
23+
if err != nil {
24+
return fmt.Errorf("git commit failed: %w\nOutput: %s", err, outputStr)
25+
}
26+
27+
log.Infof("Successfully committed the file")
28+
return nil
29+
}

internal/pkg/commit/commit_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package commit_test
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"path/filepath"
7+
8+
. "github.com/onsi/ginkgo"
9+
. "github.com/onsi/gomega"
10+
11+
. "github.com/devstream-io/devstream/internal/pkg/commit"
12+
)
13+
14+
var _ = Describe("Commit", func() {
15+
var testRepoDir string
16+
17+
BeforeEach(func() {
18+
// 1. Create a temporary directory
19+
var err error
20+
testRepoDir, err = os.MkdirTemp("", "test-repo-*")
21+
Expect(err).NotTo(HaveOccurred())
22+
23+
// 2. Change the working directory to the temporary directory
24+
err = os.Chdir(testRepoDir)
25+
Expect(err).NotTo(HaveOccurred())
26+
27+
// 3. Initialize a git repository
28+
cmd := exec.Command("git", "init")
29+
err = cmd.Run()
30+
Expect(err).NotTo(HaveOccurred())
31+
32+
// 4. Create a file and write some content to it
33+
file, err := os.Create(filepath.Join(testRepoDir, "test.txt"))
34+
Expect(err).NotTo(HaveOccurred())
35+
36+
_, err = file.WriteString("Test content")
37+
Expect(err).NotTo(HaveOccurred())
38+
file.Close()
39+
40+
// 5. Add the file to the git index
41+
cmd = exec.Command("git", "add", "test.txt")
42+
err = cmd.Run()
43+
Expect(err).NotTo(HaveOccurred())
44+
})
45+
46+
AfterEach(func() {
47+
err := os.RemoveAll(testRepoDir)
48+
Expect(err).NotTo(HaveOccurred())
49+
})
50+
51+
It("should create a new commit with the given message", func() {
52+
message := "Test commit"
53+
err := Commit(message)
54+
Expect(err).NotTo(HaveOccurred())
55+
56+
cmd := exec.Command("git", "log", "--oneline")
57+
output, err := cmd.CombinedOutput()
58+
Expect(err).NotTo(HaveOccurred())
59+
60+
Expect(string(output)).To(ContainSubstring(message))
61+
})
62+
63+
It("should return an error when git is not installed", func() {
64+
origGitPath, err := exec.LookPath("git")
65+
Expect(err).NotTo(HaveOccurred())
66+
67+
err = os.Setenv("PATH", "")
68+
Expect(err).NotTo(HaveOccurred())
69+
defer func() {
70+
err = os.Setenv("PATH", origGitPath)
71+
Expect(err).NotTo(HaveOccurred())
72+
}()
73+
74+
err = Commit("Test commit")
75+
Expect(err).To(HaveOccurred())
76+
})
77+
})

internal/pkg/patch/patch.go

+7-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"os"
77
"os/exec"
8-
"path/filepath"
98
"regexp"
109
"strings"
1110

@@ -20,24 +19,23 @@ const (
2019
type ProcessOption string
2120

2221
// Patch calls the patch command to apply a diff file to an original
23-
func Patch(workDir, patchFile string) error {
22+
func Patch(patchFile string) error {
2423
log.Infof("Patching file: %s", patchFile)
2524

2625
// Fix patch file if it mixed tab and space indentation
27-
err := fixPatchFile(workDir, patchFile)
26+
err := fixPatchFile(patchFile)
2827
if err != nil {
2928
return fmt.Errorf("patch file fix failed: %w", err)
3029
}
3130

32-
// Check if the patch command exists and is executable
33-
err = checkPatchCommand()
31+
// Check if the patch command exists
32+
patchPath, err := exec.LookPath("patch")
3433
if err != nil {
35-
return fmt.Errorf("patch command check failed: %w", err)
34+
return fmt.Errorf("patch command not found: %w", err)
3635
}
3736

3837
// Use the patch tool to apply the patch
39-
cmd := exec.Command("patch", "-i", patchFile, "-t", "-p0")
40-
cmd.Dir = workDir
38+
cmd := exec.Command(patchPath, "-i", patchFile, "-t", "-p0")
4139
output, err := cmd.CombinedOutput()
4240
if err != nil {
4341
return fmt.Errorf("patch command failed: %w\nOutput: %s", err, string(output))
@@ -73,10 +71,9 @@ func checkPatchCommand() error {
7371
// The original file path is contained in the patch file, so we can use the fix the patch file by using the original file.
7472
// If the original file uses tab indentation, we replace all spaces with tabs in the patch file.
7573
// If the original file uses space indentation, we replace all tabs with spaces in the patch file.
76-
func fixPatchFile(workDir, patchFile string) error {
74+
func fixPatchFile(patchFile string) error {
7775
// Read the original file path from the patch file
7876
originalFilePath, err := extractOriginalFilePathFromPatchFile(patchFile)
79-
originalFilePath = filepath.Join(workDir, originalFilePath)
8077

8178
if err != nil {
8279
return fmt.Errorf("failed to extract original file path from patch string: %w", err)
@@ -118,7 +115,6 @@ func fixPatchFile(workDir, patchFile string) error {
118115
}
119116

120117
return nil
121-
122118
}
123119

124120
// ExtractOriginalFilePathFromPatchString extracts the original file path from a patch string

internal/pkg/patch/patch_test.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ var _ = Describe("Patcher", func() {
2626
)
2727

2828
BeforeEach(func() {
29+
// 1. Create a temporary directory
2930
var err error
3031
tempDir, err = os.MkdirTemp("", "patcher-tests")
3132
Expect(err).NotTo(HaveOccurred())
3233

34+
// 2. Change the working directory to the temporary directory
35+
err = os.Chdir(tempDir)
36+
Expect(err).NotTo(HaveOccurred())
37+
38+
// 3. Create the original file and the patch file
3339
originalFile, err = os.CreateTemp(tempDir, "original-*")
3440
Expect(err).NotTo(HaveOccurred())
3541

@@ -63,7 +69,7 @@ This is the original file.
6369
err = os.WriteFile(patchFile.Name(), []byte(patchContent), 0644)
6470
Expect(err).NotTo(HaveOccurred())
6571

66-
err = Patch(tempDir, patchFile.Name())
72+
err = Patch(patchFile.Name())
6773
Expect(err).NotTo(HaveOccurred())
6874

6975
patchedContent, err := os.ReadFile(originalFile.Name())
@@ -93,7 +99,7 @@ This is the original file.
9399
err = os.WriteFile(patchFile.Name(), []byte(invalidPatchContent), 0644)
94100
Expect(err).NotTo(HaveOccurred())
95101

96-
err = Patch(tempDir, patchFile.Name())
102+
err = Patch(patchFile.Name())
97103
Expect(err).To(HaveOccurred())
98104
Expect(strings.Contains(err.Error(), "patch command failed")).To(BeTrue())
99105
})
@@ -118,7 +124,7 @@ This is the original file.
118124
err = os.WriteFile(patchFile.Name(), []byte(patchContent), 0644)
119125
Expect(err).NotTo(HaveOccurred())
120126

121-
err = Patch(tempDir, patchFile.Name())
127+
err = Patch(patchFile.Name())
122128
Expect(err).NotTo(HaveOccurred())
123129

124130
patchedContent, err := os.ReadFile(originalFile.Name())
@@ -146,7 +152,7 @@ This is the original file.
146152
err = os.WriteFile(patchFile.Name(), []byte(patchContent), 0644)
147153
Expect(err).NotTo(HaveOccurred())
148154

149-
err = Patch(tempDir, patchFile.Name())
155+
err = Patch(patchFile.Name())
150156
Expect(err).NotTo(HaveOccurred())
151157

152158
patchedContent, err := os.ReadFile(originalFile.Name())

0 commit comments

Comments
 (0)