diff --git a/src/checker/check.go b/src/checker/check.go index 83213986..c57ad12a 100644 --- a/src/checker/check.go +++ b/src/checker/check.go @@ -32,6 +32,7 @@ import ( "github.com/murex/tcr/status" "github.com/murex/tcr/toolchain" "github.com/murex/tcr/vcs" + "github.com/murex/tcr/vcs/git" "os" ) @@ -130,7 +131,7 @@ func initCheckEnv(p params.Params) { checkEnv.workDir = toolchain.GetWorkDir() if checkEnv.sourceTreeErr == nil { - checkEnv.git, checkEnv.gitErr = vcs.New(checkEnv.sourceTree.GetBaseDir()) + checkEnv.git, checkEnv.gitErr = git.New(checkEnv.sourceTree.GetBaseDir()) } } diff --git a/src/checker/check_git.go b/src/checker/check_git.go index 39185aba..63cd0a63 100644 --- a/src/checker/check_git.go +++ b/src/checker/check_git.go @@ -25,6 +25,7 @@ package checker import ( "github.com/murex/tcr/params" "github.com/murex/tcr/vcs" + "github.com/murex/tcr/vcs/git" ) func checkGitEnvironment(_ params.Params) (cr *CheckResults) { @@ -37,18 +38,18 @@ func checkGitEnvironment(_ params.Params) (cr *CheckResults) { } func checkGitCommand() (cp []CheckPoint) { - if !vcs.IsGitCommandAvailable() { + if !git.IsGitCommandAvailable() { cp = append(cp, errorCheckPoint("git command was not found on path")) return cp } - cp = append(cp, okCheckPoint("git command path is ", vcs.GetGitCommandPath())) - cp = append(cp, okCheckPoint("git version is ", vcs.GetGitCommandVersion())) + cp = append(cp, okCheckPoint("git command path is ", git.GetGitCommandPath())) + cp = append(cp, okCheckPoint("git version is ", git.GetGitCommandVersion())) // We could add here a check on git minimum version. No specific need for now. return cp } func checkGitConfig() (cp []CheckPoint) { - cp = append(cp, okCheckPoint("git username is ", vcs.GetGitUserName())) + cp = append(cp, okCheckPoint("git username is ", git.GetGitUserName())) return cp } diff --git a/src/checker/check_test.go b/src/checker/check_test.go index df81dedd..cfa829ca 100644 --- a/src/checker/check_test.go +++ b/src/checker/check_test.go @@ -25,7 +25,7 @@ package checker import ( "github.com/murex/tcr/params" "github.com/murex/tcr/status" - "github.com/murex/tcr/vcs" + "github.com/murex/tcr/vcs/git" "github.com/stretchr/testify/assert" "os" "path/filepath" @@ -46,7 +46,7 @@ var ( func initTestCheckEnv(params params.Params) { initCheckEnv(params) // We replace git implementation with a fake so that we bypass real git access - checkEnv.git, checkEnv.gitErr = vcs.NewGitFake(vcs.GitFakeSettings{}) + checkEnv.git, checkEnv.gitErr = git.NewGitFake(git.GitFakeSettings{}) } func assertStatus(t *testing.T, expected CheckStatus, checker func(params params.Params) (cr *CheckResults), params params.Params) { diff --git a/src/engine/tcr.go b/src/engine/tcr.go index ec4d0462..d2f63e7f 100644 --- a/src/engine/tcr.go +++ b/src/engine/tcr.go @@ -38,6 +38,7 @@ import ( "github.com/murex/tcr/toolchain" "github.com/murex/tcr/ui" "github.com/murex/tcr/vcs" + "github.com/murex/tcr/vcs/git" "gopkg.in/tomb.v2" "os" "strings" @@ -245,7 +246,7 @@ func parseCommitMessage(message string) (event events.TcrEvent) { func (tcr *TcrEngine) initVcs() { if tcr.vcs == nil { var err error - tcr.vcs, err = vcs.New(tcr.sourceTree.GetBaseDir()) + tcr.vcs, err = git.New(tcr.sourceTree.GetBaseDir()) tcr.handleError(err, true, status.GitError) } } diff --git a/src/engine/tcr_test.go b/src/engine/tcr_test.go index eac9cd53..4c006517 100644 --- a/src/engine/tcr_test.go +++ b/src/engine/tcr_test.go @@ -35,6 +35,7 @@ import ( "github.com/murex/tcr/toolchain" "github.com/murex/tcr/ui" "github.com/murex/tcr/vcs" + "github.com/murex/tcr/vcs/git" "github.com/stretchr/testify/assert" "os" "strings" @@ -180,7 +181,7 @@ func Test_tcr_operation_end_state(t *testing.T) { { "commit with git commit failure", func() { - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.CommitCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.CommitCommand}, nil) tcr.commit(events.TcrEvent{}) }, status.GitError, @@ -188,7 +189,7 @@ func Test_tcr_operation_end_state(t *testing.T) { { "commit with git push failure", func() { - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.PushCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.PushCommand}, nil) tcr.commit(events.TcrEvent{}) }, status.GitError, @@ -204,7 +205,7 @@ func Test_tcr_operation_end_state(t *testing.T) { { "revert with git diff failure", func() { - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.DiffCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.DiffCommand}, nil) tcr.revert(events.TcrEvent{}) }, status.GitError, @@ -212,7 +213,7 @@ func Test_tcr_operation_end_state(t *testing.T) { { "revert with git restore failure", func() { - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.RestoreCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.RestoreCommand}, nil) tcr.revert(events.TcrEvent{}) }, status.GitError, @@ -231,7 +232,7 @@ func Test_tcr_operation_end_state(t *testing.T) { func Test_tcr_revert_end_state_with_commit_on_fail_enabled(t *testing.T) { testFlags := []struct { desc string - gitFailures vcs.GitCommands + gitFailures git.GitCommands expectedStatus status.Status }{ { @@ -241,27 +242,27 @@ func Test_tcr_revert_end_state_with_commit_on_fail_enabled(t *testing.T) { }, { "git stash failure", - vcs.GitCommands{vcs.StashCommand}, + git.GitCommands{git.StashCommand}, status.GitError, }, { "git un-stash failure", - vcs.GitCommands{vcs.UnStashCommand}, + git.GitCommands{git.UnStashCommand}, status.GitError, }, { "git add failure", - vcs.GitCommands{vcs.AddCommand}, + git.GitCommands{git.AddCommand}, status.GitError, }, { "git commit failure", - vcs.GitCommands{vcs.CommitCommand}, + git.GitCommands{git.CommitCommand}, status.GitError, }, { "git revert failure", - vcs.GitCommands{vcs.RevertCommand}, + git.GitCommands{git.RevertCommand}, status.GitError, }, } @@ -281,7 +282,7 @@ func Test_tcr_cycle_end_state(t *testing.T) { testFlags := []struct { desc string toolchainFailures toolchain.Operations - gitFailures vcs.GitCommands + gitFailures git.GitCommands expectedStatus status.Status }{ { @@ -301,27 +302,27 @@ func Test_tcr_cycle_end_state(t *testing.T) { }, { "with git add failure", - nil, vcs.GitCommands{vcs.AddCommand}, + nil, git.GitCommands{git.AddCommand}, status.GitError, }, { "with git commit failure", - nil, vcs.GitCommands{vcs.CommitCommand}, + nil, git.GitCommands{git.CommitCommand}, status.GitError, }, { "with git push failure", - nil, vcs.GitCommands{vcs.PushCommand}, + nil, git.GitCommands{git.PushCommand}, status.GitError, }, { "with test and git diff failure", - toolchain.Operations{toolchain.TestOperation}, vcs.GitCommands{vcs.DiffCommand}, + toolchain.Operations{toolchain.TestOperation}, git.GitCommands{git.DiffCommand}, status.GitError, }, { "with test and git restore failure", - toolchain.Operations{toolchain.TestOperation}, vcs.GitCommands{vcs.RestoreCommand}, + toolchain.Operations{toolchain.TestOperation}, git.GitCommands{git.RestoreCommand}, status.GitError, }, } @@ -336,7 +337,7 @@ func Test_tcr_cycle_end_state(t *testing.T) { } } -func initTcrEngineWithFakes(p *params.Params, toolchainFailures toolchain.Operations, gitFailures vcs.GitCommands, gitLogItems vcs.GitLogItems) (TcrInterface, *vcs.GitFake) { +func initTcrEngineWithFakes(p *params.Params, toolchainFailures toolchain.Operations, gitFailures git.GitCommands, gitLogItems vcs.GitLogItems) (TcrInterface, *git.GitFake) { tchn := registerFakeToolchain(toolchainFailures) lang := registerFakeLanguage(tchn) @@ -384,13 +385,13 @@ func registerFakeLanguage(toolchainName string) string { return fake.GetName() } -func replaceGitImplWithFake(tcr TcrInterface, failures vcs.GitCommands, gitLogItems vcs.GitLogItems) *vcs.GitFake { - fakeSettings := vcs.GitFakeSettings{ +func replaceGitImplWithFake(tcr TcrInterface, failures git.GitCommands, gitLogItems vcs.GitLogItems) *git.GitFake { + fakeSettings := git.GitFakeSettings{ FailingCommands: failures, ChangedFiles: vcs.FileDiffs{vcs.NewFileDiff("fake-src", 1, 1)}, Logs: gitLogItems, } - fake, _ := vcs.NewGitFake(fakeSettings) + fake, _ := git.NewGitFake(fakeSettings) tcr.setVcs(fake) return fake } @@ -453,7 +454,7 @@ func Test_set_commit_on_fail(t *testing.T) { func Test_git_pull_calls_git_command(t *testing.T) { tcr, gitFake := initTcrEngineWithFakes(nil, nil, nil, nil) tcr.GitPull() - assert.Equal(t, vcs.PullCommand, gitFake.GetLastCommand()) + assert.Equal(t, git.PullCommand, gitFake.GetLastCommand()) } func Test_git_pull_highlights_errors(t *testing.T) { @@ -462,7 +463,7 @@ func Test_git_pull_highlights_errors(t *testing.T) { return msg.Type.Severity == report.Error && msg.Text == "git pull command failed!" }, ) - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.PullCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.PullCommand}, nil) tcr.GitPull() time.Sleep(1 * time.Millisecond) sniffer.Stop() @@ -475,7 +476,7 @@ func Test_git_push_highlights_errors(t *testing.T) { return msg.Type.Severity == report.Error && msg.Text == "git push command failed!" }, ) - tcr, _ := initTcrEngineWithFakes(nil, nil, vcs.GitCommands{vcs.PushCommand}, nil) + tcr, _ := initTcrEngineWithFakes(nil, nil, git.GitCommands{git.PushCommand}, nil) tcr.GitPush() time.Sleep(1 * time.Millisecond) sniffer.Stop() diff --git a/src/vcs/git_command.go b/src/vcs/git/git_command.go similarity index 95% rename from src/vcs/git_command.go rename to src/vcs/git/git_command.go index f70d6e24..a16b7f2a 100644 --- a/src/vcs/git_command.go +++ b/src/vcs/git/git_command.go @@ -20,24 +20,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package vcs +package git import ( "bufio" "bytes" "github.com/codeskyblue/go-sh" "github.com/murex/tcr/report" + "github.com/murex/tcr/vcs" "strings" ) // IsGitCommandAvailable indicates if git command is available on local machine func IsGitCommandAvailable() bool { - return IsCommandAvailable("git") + return vcs.IsCommandAvailable("git") } // GetGitCommandPath returns the path to git command on this machine func GetGitCommandPath() string { - return GetCommandPath("git") + return vcs.GetCommandPath("git") } // GetGitCommandVersion returns the version of git command on this machine diff --git a/src/vcs/git_impl.go b/src/vcs/git/git_impl.go similarity index 95% rename from src/vcs/git_impl.go rename to src/vcs/git/git_impl.go index f8accc82..2a6fffdf 100644 --- a/src/vcs/git_impl.go +++ b/src/vcs/git/git_impl.go @@ -20,7 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package vcs +package git import ( "bufio" @@ -34,6 +34,7 @@ import ( "github.com/go-git/go-git/v5/plumbing/storer" "github.com/go-git/go-git/v5/storage/filesystem" "github.com/murex/tcr/report" + "github.com/murex/tcr/vcs" "path/filepath" "strconv" "strings" @@ -55,15 +56,14 @@ type gitImpl struct { } // New initializes the git implementation based on the provided directory from local clone -func New(dir string) (GitInterface, error) { +func New(dir string) (vcs.GitInterface, error) { return newGitImpl(plainOpen, dir) } -// newGitImpl initializes a gitImpl instance func newGitImpl(initRepo func(string) (*git.Repository, billy.Filesystem, error), dir string) (*gitImpl, error) { var g = gitImpl{ baseDir: dir, - pushEnabled: DefaultPushEnabled, + pushEnabled: vcs.DefaultPushEnabled, runGitFunction: runGitCommand, traceGitFunction: traceGitCommand, } @@ -81,9 +81,9 @@ func newGitImpl(initRepo func(string) (*git.Repository, billy.Filesystem, error) return nil, err } - if isRemoteDefined(DefaultRemoteName, g.repository) { + if isRemoteDefined(vcs.DefaultRemoteName, g.repository) { g.remoteEnabled = true - g.remoteName = DefaultRemoteName + g.remoteName = vcs.DefaultRemoteName g.workingBranchExistsOnRemote, err = g.isWorkingBranchOnRemote() } @@ -286,7 +286,7 @@ func (g *gitImpl) UnStash(keep bool) error { // Diff returns the list of files modified since last commit with diff info for each file // Current implementation uses a direct call to git -func (g *gitImpl) Diff() (diffs FileDiffs, err error) { +func (g *gitImpl) Diff() (diffs vcs.FileDiffs, err error) { var gitOutput []byte gitOutput, err = g.runGit("diff", "--numstat", "--ignore-cr-at-eol", "--ignore-all-space", "--ignore-blank-lines", "HEAD") @@ -301,7 +301,7 @@ func (g *gitImpl) Diff() (diffs FileDiffs, err error) { added, _ := strconv.Atoi(fields[0]) removed, _ := strconv.Atoi(fields[1]) filename := filepath.Join(g.rootDir, fields[2]) - diffs = append(diffs, NewFileDiff(filename, added, removed)) + diffs = append(diffs, vcs.NewFileDiff(filename, added, removed)) } } return diffs, nil @@ -310,7 +310,7 @@ func (g *gitImpl) Diff() (diffs FileDiffs, err error) { // Log returns the list of git log items compliant with the provided msgFilter. // When no msgFilter is provided, returns all git log items unfiltered. // Current implementation uses go-git's Log() function -func (g *gitImpl) Log(msgFilter func(msg string) bool) (logs GitLogItems, err error) { +func (g *gitImpl) Log(msgFilter func(msg string) bool) (logs vcs.GitLogItems, err error) { plainOpenOptions := git.PlainOpenOptions{ DetectDotGit: true, EnableDotGitCommonDir: false, @@ -333,7 +333,7 @@ func (g *gitImpl) Log(msgFilter func(msg string) bool) (logs GitLogItems, err er } _ = cIter.ForEach(func(c *object.Commit) error { if msgFilter == nil || msgFilter(c.Message) { - logs.Add(NewGitLogItem(c.Hash.String(), c.Committer.When.UTC(), c.Message)) + logs.Add(vcs.NewGitLogItem(c.Hash.String(), c.Committer.When.UTC(), c.Message)) } return nil }) diff --git a/src/vcs/git_impl_test.go b/src/vcs/git/git_impl_test.go similarity index 96% rename from src/vcs/git_impl_test.go rename to src/vcs/git/git_impl_test.go index 62cc9da9..8d0ba288 100644 --- a/src/vcs/git_impl_test.go +++ b/src/vcs/git/git_impl_test.go @@ -20,12 +20,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package vcs +package git import ( "errors" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" + "github.com/murex/tcr/vcs" "github.com/stretchr/testify/assert" "os" "path/filepath" @@ -88,7 +89,7 @@ func Test_git_diff_command(t *testing.T) { gitDiffError error expectError bool expectedArgs []string - expectedDiff FileDiffs + expectedDiff vcs.FileDiffs }{ {"git command arguments", "", @@ -117,7 +118,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "some-file.txt"), 1, 1}, }, }, @@ -126,7 +127,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "file1.txt"), 1, 1}, {filepath.Join("/", "file2.txt"), 1, 1}, }, @@ -136,7 +137,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "some-dir", "some-file.txt"), 1, 1}, }, }, @@ -145,7 +146,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "some-file.txt"), 15, 0}, }, }, @@ -154,7 +155,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "some-file.txt"), 0, 7}, }, }, @@ -165,7 +166,7 @@ func Test_git_diff_command(t *testing.T) { nil, false, nil, - FileDiffs{ + vcs.FileDiffs{ {filepath.Join("/", "some-file.txt"), 1, 1}, }, }, @@ -237,7 +238,7 @@ func Test_git_push_command(t *testing.T) { } g.pushEnabled = tt.pushEnabled g.remoteEnabled = true - g.remoteName = DefaultRemoteName + g.remoteName = vcs.DefaultRemoteName err := g.Push() if tt.expectError { @@ -289,7 +290,7 @@ func Test_git_pull_command(t *testing.T) { return tt.gitError } g.remoteEnabled = true - g.remoteName = DefaultRemoteName + g.remoteName = vcs.DefaultRemoteName g.workingBranchExistsOnRemote = tt.branchOnRemote err := g.Pull() @@ -599,7 +600,7 @@ func Test_git_unstash_command(t *testing.T) { func Test_git_log_command(t *testing.T) { // Note: this test may break if for any reason the TCR repository initial commit is altered - tcrInitialCommit := GitLogItem{ + tcrInitialCommit := vcs.GitLogItem{ Hash: "a823c098187455bade90ee44874d2b41c7ef96d9", Timestamp: time.Date(2021, time.June, 16, 15, 29, 41, 0, time.UTC), Message: "Initial commit", @@ -608,27 +609,27 @@ func Test_git_log_command(t *testing.T) { testFlags := []struct { desc string filter func(msg string) bool - asserter func(t *testing.T, items GitLogItems) + asserter func(t *testing.T, items vcs.GitLogItems) }{ { "filter matching no item", func(_ string) bool { return false }, - func(t *testing.T, items GitLogItems) { - assert.Equal(t, 0, items.len()) + func(t *testing.T, items vcs.GitLogItems) { + assert.Equal(t, 0, items.Len()) }, }, { "filter matching all items", nil, - func(t *testing.T, items GitLogItems) { - assert.Greater(t, items.len(), 100) + func(t *testing.T, items vcs.GitLogItems) { + assert.Greater(t, items.Len(), 100) }, }, { "filter matching one single item", func(msg string) bool { return tcrInitialCommit.Message == msg }, - func(t *testing.T, items GitLogItems) { - assert.Equal(t, 1, items.len()) + func(t *testing.T, items vcs.GitLogItems) { + assert.Equal(t, 1, items.Len()) assert.Equal(t, tcrInitialCommit, items[0]) }, }, diff --git a/src/vcs/git_test_fake.go b/src/vcs/git/git_test_fake.go similarity index 95% rename from src/vcs/git_test_fake.go rename to src/vcs/git/git_test_fake.go index 014c5730..f93faa80 100644 --- a/src/vcs/git_test_fake.go +++ b/src/vcs/git/git_test_fake.go @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package vcs +package git import ( "errors" @@ -30,6 +30,7 @@ import ( "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/storage/memory" + "github.com/murex/tcr/vcs" ) type ( @@ -67,13 +68,13 @@ type ( // GitFakeSettings provide a few ways to tune GitFake behaviour GitFakeSettings struct { FailingCommands GitCommands - ChangedFiles FileDiffs - Logs GitLogItems + ChangedFiles vcs.FileDiffs + Logs vcs.GitLogItems } // GitFake provides a fake implementation of the git interface GitFake struct { - impl GitInterface + impl vcs.GitInterface settings GitFakeSettings lastCommand GitCommand } @@ -132,12 +133,12 @@ func (g *GitFake) Pull() error { } // Diff returns the list of files modified configured at fake initialization -func (g *GitFake) Diff() (_ FileDiffs, err error) { +func (g *GitFake) Diff() (_ vcs.FileDiffs, err error) { return g.settings.ChangedFiles, g.fakeGitCommand(DiffCommand) } // Log returns the list of git logs configured at fake initialization -func (g *GitFake) Log(msgFilter func(msg string) bool) (logs GitLogItems, err error) { +func (g *GitFake) Log(msgFilter func(msg string) bool) (logs vcs.GitLogItems, err error) { err = g.fakeGitCommand(LogCommand) if msgFilter == nil { diff --git a/src/vcs/git_file_diff.go b/src/vcs/git_file_diff.go index 4e4a897c..49dc6ce1 100644 --- a/src/vcs/git_file_diff.go +++ b/src/vcs/git_file_diff.go @@ -26,8 +26,8 @@ type ( // FileDiff is a structure containing diff information for a file FileDiff struct { Path string - addedLines int - removedLines int + AddedLines int + RemovedLines int } // FileDiffs contains a set of FileDiff data in a slice @@ -36,12 +36,12 @@ type ( // NewFileDiff creates a new instance of FileDiff func NewFileDiff(filename string, added int, removed int) FileDiff { - return FileDiff{Path: filename, addedLines: added, removedLines: removed} + return FileDiff{Path: filename, AddedLines: added, RemovedLines: removed} } // ChangedLines returns the number of changed lines for this file func (fd FileDiff) ChangedLines() int { - return fd.addedLines + fd.removedLines + return fd.AddedLines + fd.RemovedLines } // ChangedLines returns the total number of changed lines for this set of files diff --git a/src/vcs/git_log_item.go b/src/vcs/git_log_item.go index 7ed4f14f..6f283149 100644 --- a/src/vcs/git_log_item.go +++ b/src/vcs/git_log_item.go @@ -55,6 +55,7 @@ func (items *GitLogItems) Add(d GitLogItem) { *items = append(*items, d) } -func (items *GitLogItems) len() int { +// Len returns the length of the items array +func (items *GitLogItems) Len() int { return len(*items) }