From a66afdec302f98b5a963f93c4544694a23bafcf7 Mon Sep 17 00:00:00 2001 From: isindir Date: Sat, 12 Mar 2022 17:43:13 +0000 Subject: [PATCH] Add mockery to try it (#13) * fix: refactor code and add some tests; bump some dependencies * Fix typo * Fix typo --- .github/workflows/go.yaml | 6 +- .tool-versions | 4 +- Makefile | 10 +- exec/exec.go | 38 ++++ exec/mocks/ShellRunnerI.go | 38 ++++ gitget/get.go | 146 +++++++-------- gitget/get_test.go | 328 ++++++++++++++++++++++++++++------ gitlab/gitlab.go | 125 +++++++++---- gitlab/mocks/GitGetGitlabI.go | 170 ++++++++++++++++++ go.mod | 7 +- go.sum | 5 +- 11 files changed, 707 insertions(+), 170 deletions(-) create mode 100644 exec/exec.go create mode 100644 exec/mocks/ShellRunnerI.go create mode 100644 gitlab/mocks/GitGetGitlabI.go diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index 9046162..e195de0 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -14,7 +14,7 @@ jobs: if: github.ref != 'refs/heads/master' steps: - - name: Set up Go 1.17.8 + - name: Set up Go uses: actions/setup-go@v1 with: go-version: 1.17.8 @@ -23,6 +23,7 @@ jobs: - name: Install GoReleaser uses: goreleaser/goreleaser-action@v2 with: + version: v1.6.3 install-only: true - name: Check out code into the Go module directory @@ -43,7 +44,7 @@ jobs: if: github.ref == 'refs/heads/master' steps: - - name: Set up Go 1.17.8 + - name: Set up Go uses: actions/setup-go@v1 with: go-version: 1.17.8 @@ -52,6 +53,7 @@ jobs: - name: Install GoReleaser uses: goreleaser/goreleaser-action@v2 with: + version: v1.6.3 install-only: true - name: Install svu diff --git a/.tool-versions b/.tool-versions index 430cb48..081f257 100644 --- a/.tool-versions +++ b/.tool-versions @@ -2,4 +2,6 @@ # https://golang.org/dl/ golang 1.17.8 # https://github.com/goreleaser/goreleaser/releases -goreleaser 1.6.0 +goreleaser 1.6.3 +# https://github.com/vektra/mockery/releases +mockery 2.10.0 diff --git a/Makefile b/Makefile index 99e2495..e5ba110 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ run: ## Runs main help test: ## Placeholder to run unit tests @echo "Running unit tests" @mkdir -p bin - $(GO) test -cover -coverprofile=bin/c.out ./... + $(GO) test -cover -coverprofile=bin/c.out $$( go list ./... | egrep -v 'mocks|qqq|vendor|exec|cmd' ) $(GO) tool cover -html=bin/c.out -o bin/coverage.html @echo @@ -52,8 +52,14 @@ fmt: ## Run go fmt against code. vet: ## Run go vet against code. $(GO) vet ./... +.PHONY: mockery +mockery: ## Regenerate mock files + for i in exec gitlab; do \ + (cd $$i; rm -fr mocks; mockery --all) ;\ + done + .PHONY: mod -mod: ## Run go mod tidy/vendor +mod: mockery ## Run go mod tidy/vendor $(GO) mod tidy $(GO) mod vendor diff --git a/exec/exec.go b/exec/exec.go new file mode 100644 index 0000000..704818c --- /dev/null +++ b/exec/exec.go @@ -0,0 +1,38 @@ +package exec + +import ( + "bytes" + "os/exec" +) + +const gitCmd = "git" + +type ShellRunnerI interface { + ExecGitCommand(args []string, stdoutb *bytes.Buffer, erroutb *bytes.Buffer, dir string) (cmd *exec.Cmd, err error) +} + +type ShellRunner struct{} + +// ExecGitCommand executes git with flags passed as `args` and can change working directory if `dir` is passed +func (repo *ShellRunner) ExecGitCommand( + args []string, + stdoutb *bytes.Buffer, + erroutb *bytes.Buffer, + dir string, +) (cmd *exec.Cmd, err error) { + cmd = exec.Command(gitCmd, args...) + + if stdoutb != nil { + cmd.Stdout = stdoutb + } + if erroutb != nil { + cmd.Stderr = erroutb + } + + if dir != "" { + cmd.Dir = dir + } + + err = cmd.Run() + return cmd, err +} diff --git a/exec/mocks/ShellRunnerI.go b/exec/mocks/ShellRunnerI.go new file mode 100644 index 0000000..181144e --- /dev/null +++ b/exec/mocks/ShellRunnerI.go @@ -0,0 +1,38 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + bytes "bytes" + exec "os/exec" + + mock "github.com/stretchr/testify/mock" +) + +// ShellRunnerI is an autogenerated mock type for the ShellRunnerI type +type ShellRunnerI struct { + mock.Mock +} + +// ExecGitCommand provides a mock function with given fields: args, stdoutb, erroutb, dir +func (_m *ShellRunnerI) ExecGitCommand(args []string, stdoutb *bytes.Buffer, erroutb *bytes.Buffer, dir string) (*exec.Cmd, error) { + ret := _m.Called(args, stdoutb, erroutb, dir) + + var r0 *exec.Cmd + if rf, ok := ret.Get(0).(func([]string, *bytes.Buffer, *bytes.Buffer, string) *exec.Cmd); ok { + r0 = rf(args, stdoutb, erroutb, dir) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*exec.Cmd) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func([]string, *bytes.Buffer, *bytes.Buffer, string) error); ok { + r1 = rf(args, stdoutb, erroutb, dir) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/gitget/get.go b/gitget/get.go index 47be66c..cc0af39 100644 --- a/gitget/get.go +++ b/gitget/get.go @@ -30,7 +30,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path" "path/filepath" "regexp" @@ -45,12 +44,11 @@ import ( "gopkg.in/yaml.v2" "github.com/isindir/git-get/bitbucket" + "github.com/isindir/git-get/exec" "github.com/isindir/git-get/github" "github.com/isindir/git-get/gitlab" ) -const gitCmd = "git" - var stayOnRef bool var defaultMainBranch = "master" var gitProvider string @@ -58,6 +56,7 @@ var mirrorVisibilityMode = "private" var bitbucketMirrorProject = "" var colorHighlight *color.Color var colorRef *color.Color +var shellRunner = new(exec.ShellRunner) // ConfigGenParamsStruct - data structure to store parameters passed via cli flags type ConfigGenParamsStruct struct { @@ -66,11 +65,11 @@ type ConfigGenParamsStruct struct { GitlabVisibility string GitlabMinAccessLevel string - // Girhub specific vars + // GitHub specific vars GithubVisibility string GithubAffiliation string - // Bitbicket specific vars + // Bitbucket specific vars /* MAYBE: implement for bitbucket to allow subset of repositories BitbucketDivision string @@ -87,7 +86,7 @@ type bitbucketLinks struct { type Repo struct { URL string `yaml:"url"` // git url of the remote repository Path string `yaml:"path,omitempty"` // to clone repository to - AltName string `yaml:"altname,omitempty"` // when clone, repository will have different name from remote + AltName string `yaml:"altname,omitempty"` // when cloned, repository will have different name from remote Ref string `yaml:"ref,omitempty"` // branch to clone (normally trunk branch name, but git sha or git tag can be also specified) Symlinks []string `yaml:"symlinks,omitempty"` // paths where to create symlinks to the repository clone // helper fields, not supposed to be written or read in Gitfile: @@ -95,8 +94,10 @@ type Repo struct { sha string `yaml:"sha,omitempty"` mirrorURL string `yaml:"mirror_url,omitempty"` status RepoStatus // keep track of the repository status after operation to provide summary + executor *exec.ShellRunnerI } +// RepoList is a slice of Repo structs type RepoList []Repo // RepoStatus - data structure to track repository status @@ -114,13 +115,12 @@ type RepoI interface { CreateSymlink(symlink string) ChoosePathPrefix(pathPrefix string) string EnsurePathExists() - ExecGitCommand(args []string, stdoutb *bytes.Buffer, erroutb *bytes.Buffer, dir string) (cmd *exec.Cmd, err error) GetCurrentBranch() string GetRepoLocalName() string GitCheckout(branch string) GitPull() - GitStashPop() - GitStashSave() + GitStashPop() bool + GitStashSave() bool IsClean() bool IsCurrentBranchRef() bool IsRefBranch() bool @@ -192,6 +192,7 @@ func (repo *Repo) EnsurePathExists(pathPrefix string) { } } +// SetRepoLocalName sets struct AltName to short name obtained from repository uri func (repo *Repo) SetRepoLocalName() { repo.AltName = repo.GetRepoLocalName() } @@ -201,15 +202,24 @@ func (repo *Repo) SetSha() { repo.sha = generateSha(fmt.Sprintf("%s (%s) %s", repo.URL, repo.Ref, repo.fullPath)) } +// generateSha returns sha of the string passed in or "unknown" if error occurs func generateSha(input string) string { h := sha1.New() - io.WriteString(h, input) + _, err := io.WriteString(h, input) + if err != nil { + return "unknown" + } return fmt.Sprintf("%x", h.Sum(nil))[0:7] } +func (repo *Repo) SetShellRunner(exe exec.ShellRunnerI) { + repo.executor = &exe +} + // PrepareForGet performs checks for repository as well as constructs // extra information and sets repository data structure values. func (repo *Repo) PrepareForGet() { + repo.SetShellRunner(shellRunner) repo.EnsurePathExists("") repo.SetDefaultRef() repo.SetRepoLocalName() @@ -272,7 +282,7 @@ func (repo *Repo) RepoPathExists() bool { func (repo *Repo) CloneMirror() bool { log.Infof("%s: Clone repository '%s' for mirror", repo.sha, repo.URL) var serr bytes.Buffer - _, err := repo.ExecGitCommand( + _, err := (*repo.executor).ExecGitCommand( []string{"clone", "--mirror", repo.URL, repo.fullPath}, nil, &serr, @@ -289,7 +299,7 @@ func (repo *Repo) CloneMirror() bool { func (repo *Repo) PushMirror() bool { log.Infof("%s: Push repository '%s' as a mirror '%s'", repo.sha, repo.URL, repo.mirrorURL) var serr bytes.Buffer - _, err := repo.ExecGitCommand([]string{"push", "--mirror", repo.mirrorURL}, nil, &serr, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"push", "--mirror", repo.mirrorURL}, nil, &serr, repo.fullPath) if err != nil { log.Errorf("%s: %v %v", repo.sha, err, serr.String()) return false @@ -301,7 +311,7 @@ func (repo *Repo) PushMirror() bool { func (repo *Repo) Clone() bool { log.Infof("%s: Clone repository '%s'", repo.sha, repo.URL) var serr bytes.Buffer - _, err := repo.ExecGitCommand( + _, err := (*repo.executor).ExecGitCommand( []string{"clone", "--branch", repo.Ref, repo.URL, repo.fullPath}, nil, &serr, @@ -319,7 +329,7 @@ func (repo *Repo) Clone() bool { func (repo *Repo) ShallowClone() bool { log.Infof("%s: Clone repository '%s'", repo.sha, repo.URL) var serr bytes.Buffer - _, err := repo.ExecGitCommand( + _, err := (*repo.executor).ExecGitCommand( []string{"clone", "--depth", "1", "--branch", repo.Ref, repo.URL, repo.fullPath}, nil, &serr, @@ -349,11 +359,11 @@ func (repo *Repo) RemoveTargetDir(dotGit bool) { func (repo *Repo) IsClean() bool { res := true - _, err := repo.ExecGitCommand([]string{"diff", "--quiet"}, nil, nil, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"diff", "--quiet"}, nil, nil, repo.fullPath) if err != nil { res = false } - _, err = repo.ExecGitCommand([]string{"diff", "--staged", "--quiet"}, nil, nil, repo.fullPath) + _, err = (*repo.executor).ExecGitCommand([]string{"diff", "--staged", "--quiet"}, nil, nil, repo.fullPath) if err != nil { res = false } @@ -362,94 +372,81 @@ func (repo *Repo) IsClean() bool { func (repo *Repo) IsCurrentBranchRef() bool { var outb, errb bytes.Buffer - repo.ExecGitCommand([]string{"rev-parse", "--abbrev-ref", "HEAD"}, &outb, &errb, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"rev-parse", "--abbrev-ref", "HEAD"}, &outb, &errb, repo.fullPath) + if err != nil { + log.Errorf("%s: Error when checking branch %v", repo.sha, err) + } return (strings.TrimSpace(outb.String()) == repo.Ref) } func (repo *Repo) GetCurrentBranch() string { var outb, errb bytes.Buffer - repo.ExecGitCommand([]string{"rev-parse", "--abbrev-ref", "HEAD"}, &outb, &errb, repo.fullPath) - return strings.TrimSpace(outb.String()) -} - -func (repo *Repo) ExecGitCommand( - args []string, - stdoutb *bytes.Buffer, - erroutb *bytes.Buffer, - dir string, -) (cmd *exec.Cmd, err error) { - cmd = exec.Command(gitCmd, args...) - - if stdoutb != nil { - cmd.Stdout = stdoutb - } - if erroutb != nil { - cmd.Stderr = erroutb - } - - if dir != "" { - cmd.Dir = dir + _, err := (*repo.executor).ExecGitCommand([]string{"rev-parse", "--abbrev-ref", "HEAD"}, &outb, &errb, repo.fullPath) + if err != nil { + log.Errorf("%s: Error when getting branch %v", repo.sha, err) + return "" } - - err = cmd.Run() - return cmd, err + return strings.TrimSpace(outb.String()) } -func (repo *Repo) GitStashSave() { +func (repo *Repo) GitStashSave() bool { log.Infof("%s: Stash unsaved changes", repo.sha) var serr bytes.Buffer - _, err := repo.ExecGitCommand([]string{"stash", "save"}, nil, &serr, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"stash", "save"}, nil, &serr, repo.fullPath) if err != nil { repo.status.Error = true log.Warnf("%s: %v: %v", repo.sha, err, serr.String()) + return false } + return true } -func (repo *Repo) GitStashPop() { +func (repo *Repo) GitStashPop() bool { log.Infof("%s: Restore stashed changes", repo.sha) var serr bytes.Buffer - _, err := repo.ExecGitCommand([]string{"stash", "pop"}, nil, &serr, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"stash", "pop"}, nil, &serr, repo.fullPath) if err != nil { repo.status.Error = true log.Warnf("%s: %v: %v", repo.sha, err, serr.String()) + return false } + return true } +// IsRefBranch returns true if func (repo *Repo) IsRefBranch() bool { - res := true fullRef := fmt.Sprintf("refs/heads/%s", repo.Ref) - _, err := repo.ExecGitCommand( + _, err := (*repo.executor).ExecGitCommand( []string{"show-ref", "--quiet", "--verify", fullRef}, nil, nil, repo.fullPath, ) if err != nil { - res = false + return false } - return res + return true } func (repo *Repo) IsRefTag() bool { - res := true fullRef := fmt.Sprintf("refs/tags/%s", repo.Ref) - _, err := repo.ExecGitCommand( + _, err := (*repo.executor).ExecGitCommand( []string{"show-ref", "--quiet", "--verify", fullRef}, nil, nil, repo.fullPath, ) if err != nil { - res = false + return false } - return res + return true } func (repo *Repo) GitPull() { if repo.IsRefBranch() { log.Infof("%s: Pulling upstream changes", repo.sha) var serr bytes.Buffer - _, err := repo.ExecGitCommand([]string{"pull", "-f"}, nil, &serr, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"pull", "-f"}, nil, &serr, repo.fullPath) if err != nil { repo.status.Error = true log.Errorf("%s: %v: %v", repo.sha, err, serr.String()) @@ -480,7 +477,7 @@ func (repo *Repo) ProcessRepoBasedOnCleaness() { func (repo *Repo) GitCheckout(branch string) { log.Infof("%s: Checkout to '%s' branch in '%s'", repo.sha, colorHighlight.Sprintf(branch), repo.fullPath) var serr bytes.Buffer - _, err := repo.ExecGitCommand([]string{"checkout", branch}, nil, &serr, repo.fullPath) + _, err := (*repo.executor).ExecGitCommand([]string{"checkout", branch}, nil, &serr, repo.fullPath) if err != nil { repo.status.Error = true log.Warnf("%s: %v: %v", repo.sha, err, serr.String()) @@ -569,12 +566,15 @@ func (repo *Repo) EnsureGitlabMirrorExists() { log.Debugf("%s: For Check: BaseURL: %s projectNameFullPath: %s", repo.sha, baseURL, projectNameFullPath) log.Debugf("%s: For Create: BaseURL: %s projectNameShort: %s", repo.sha, baseURL, projectNameShort) // In gitlab Project is both - repository and directory to aggregate repositories - projectFound := gitlab.ProjectExists(repo.sha, baseURL, projectNameFullPath) + gitlabObj := gitlab.GitGetGitlab{} + gitlabObj.Init() + + projectFound := gitlabObj.ProjectExists(repo.sha, baseURL, projectNameFullPath) if !projectFound { log.Debugf("%s: Gitlab project '%s' does not exist", repo.sha, projectNameFullPath) // identify if part `b` is a group ? then need to create project differently - potentially create all subgroups - projectNamespace, namespaceFullPath := gitlab.GetProjectNamespace(repo.sha, baseURL, projectNameFullPath) + projectNamespace, namespaceFullPath := gitlabObj.GetProjectNamespace(repo.sha, baseURL, projectNameFullPath) log.Debugf("%s: '%s' is '%+v'", repo.sha, projectNameFullPath, projectNamespace) // If project namespace exists and is user - create project for user // Otherwise ensure group with subgroups exists and create project in subgroup @@ -583,7 +583,7 @@ func (repo *Repo) EnsureGitlabMirrorExists() { log.Debugf( "%s: Creating new gitlab project '%s' on '%s' for user '%s'", repo.sha, projectNameShort, baseURL, projectNamespace.Path) - gitlab.CreateProject( + gitlabObj.CreateProject( repo.sha, baseURL, projectNameShort, @@ -595,7 +595,7 @@ func (repo *Repo) EnsureGitlabMirrorExists() { log.Debugf(""+ "%s: Creating new gitlab project '%s' on '%s' for namespace '%s'", repo.sha, projectNameShort, baseURL, projectNamespace.Path) - gitlab.CreateProject( + gitlabObj.CreateProject( repo.sha, baseURL, projectNameShort, @@ -626,13 +626,14 @@ func DecomposeGitURL(gitURL string) (string, string, string) { urlParts := strings.SplitN(url, "/", 2) baseURL, fullName := urlParts[0], urlParts[1] - // baseURL and projecName for creating missing repository ( abc.com/b/c/d -> abc.com/b/c , d) + // baseURL and project Name for creating missing repository ( abc.com/b/c/d -> abc.com/b/c , d) _, shortName := filepath.Split(url) // ( abc.com/b/c/d -> abc.com, b/c/d, d ) return baseURL, fullName, shortName } +// EnsureGithubMirrorExists - creates mirror repository if it does not exist func (repo *Repo) EnsureGithubMirrorExists() { _, projectNameFullPath, _ := DecomposeGitURL(repo.mirrorURL) repoNameParts := strings.SplitN(projectNameFullPath, "/", 2) @@ -646,6 +647,7 @@ func (repo *Repo) EnsureGithubMirrorExists() { } } +// EnsureBitbucketMirrorExists - creates mirror repository if it does not exist func (repo *Repo) EnsureBitbucketMirrorExists() { _, fullName, _ := DecomposeGitURL(repo.mirrorURL) repoNameParts := strings.SplitN(fullName, "/", 2) @@ -738,7 +740,7 @@ func mirrorReposFromConfigInParallel( var wait sync.WaitGroup - // make temp directory - preserve it's name + // make temp directory - preserve its name tempDir, err := ioutil.TempDir("", "gitgetmirror") if err != nil { log.Fatalf("Error: %s, while creating temporary directory", err) @@ -774,22 +776,7 @@ func mirrorReposFromConfigInParallel( wait.Wait() } -func processConfig(repoList []Repo) { - for _, repository := range repoList { - repository.PrepareForGet() - if !repository.RepoPathExists() { - // Clone - log.Debugf("%s: path '%s' missing - cloning", repository.sha, repository.fullPath) - repository.Clone() - } else { - // Refresh - log.Debugf("%s: path '%s' exists, will refresh from remote", repository.sha, repository.fullPath) - repository.ProcessRepoBasedOnCurrentBranch() - } - repository.ProcessSymlinks() - } -} - +// GetRepositories - gets the list of repositories func GetRepositories( cfgFiles []string, ignoreFiles []string, @@ -978,7 +965,10 @@ func fetchGitlabRepos( "%s: Fetching repositories for '%s' target: '%s' -> '%s' '%s'", repoSha, gitProvider, gitCloudProviderRootURL, baseURL, groupName) - glRepoList := gitlab.FetchOwnerRepos( + gitlabObj := gitlab.GitGetGitlab{} + gitlabObj.Init() + + glRepoList := gitlabObj.FetchOwnerRepos( repoSha, baseURL, groupName, diff --git a/gitget/get_test.go b/gitget/get_test.go index 10b22df..b262165 100644 --- a/gitget/get_test.go +++ b/gitget/get_test.go @@ -4,8 +4,14 @@ package gitget import ( + "bytes" + "fmt" + "os/exec" "path" "testing" + + "github.com/isindir/git-get/exec/mocks" + "github.com/stretchr/testify/assert" ) var repoUrls = map[string]string{ @@ -15,27 +21,20 @@ var repoUrls = map[string]string{ "https://gitlab.com/devops/deploy/deployment-jobs.git": "deployment-jobs", } -type testGitGetRepo struct { -} - -func TestSetDefaultRef(t *testing.T) { +func Test_SetDefaultRef(t *testing.T) { repo := Repo{} // Test setting to default if not specified repo.SetDefaultRef() - if repo.Ref != "master" { - t.Errorf("Expected 'master', got: '%s'", repo.Ref) - } + assert.Equal(t, "master", repo.Ref) // Test that if already set - setting to default has no effect repo.Ref = "trunk" repo.SetDefaultRef() - if repo.Ref != "trunk" { - t.Errorf("Expected 'trunk', got: '%s'", repo.Ref) - } + assert.Equal(t, "trunk", repo.Ref) } -func TestGetRepoLocalName(t *testing.T) { +func Test_GetRepoLocalName(t *testing.T) { // Test extracting altname from git repo name, if altname is not specified var altname string @@ -43,51 +42,51 @@ func TestGetRepoLocalName(t *testing.T) { repo := Repo{} repo.URL = repoURL altname = repo.GetRepoLocalName() - if altname != expectedAltName { - t.Errorf("Expected '%s', got: '%s'", expectedAltName, altname) - } + assert.Equal(t, expectedAltName, altname) } repo := Repo{} repo.AltName = "abc" altname = repo.GetRepoLocalName() - if altname != "abc" { - t.Errorf("Expected 'abc', got: '%s'", altname) - } + assert.Equal(t, "abc", altname) } -func TestSetRepoLocalName(t *testing.T) { +func Test_SetRepoLocalName(t *testing.T) { for repoURL, expectedAltName := range repoUrls { repo := Repo{} repo.URL = repoURL repo.SetRepoLocalName() - if repo.AltName != expectedAltName { - t.Errorf("Expected '%s', got: '%s'", expectedAltName, repo.AltName) - } + assert.Equal(t, expectedAltName, repo.AltName) } repo := Repo{} repo.AltName = "abc" repo.SetRepoLocalName() - if repo.AltName != "abc" { - t.Errorf("Expected 'abc', got: '%s'", repo.AltName) - } + assert.Equal(t, "abc", repo.AltName) } -func TestSetSha(t *testing.T) { +func Test_SetSha(t *testing.T) { repo := Repo{} - repo.URL = "git@github.com:isindir/git-get.git" + repo.URL = "git@github.com:johndoe/git-get.git" repo.Ref = "master" - repo.fullPath = "/Users/erikszelenka/workspace/eriks/git-get/git-get" + repo.fullPath = "/Users/johndoe/workspace/john/git-get/git-get" repo.SetSha() - if repo.sha != "28f4e2d" { - t.Errorf("Expected '28f4e2d', got: '%s'", repo.sha) - } + assert.Equal(t, "8955354", repo.sha) } -func TestSetRepoFullPath(t *testing.T) { +func Test_PathExists(t *testing.T) { + // Test Happy path + res, _ := PathExists(".") + assert.True(t, res) + + // Test path not found + res, _ = PathExists("NotExpectedToFindMe") + assert.False(t, res) +} + +func Test_SetRepoFullPath(t *testing.T) { repo := Repo{ Path: "qqq", AltName: "abc", @@ -95,40 +94,263 @@ func TestSetRepoFullPath(t *testing.T) { expectedFullPath := path.Join("qqq", "abc") repo.SetRepoFullPath() - if repo.fullPath != expectedFullPath { - t.Errorf("Expected '%s', got: '%s'", expectedFullPath, repo.fullPath) - } + assert.Equal(t, expectedFullPath, repo.fullPath) } -func TestPathExists(t *testing.T) { - // Test Happy path - res, _ := PathExists(".") - if !res { - t.Errorf("Expected '.' path to exist, got: '%v'", res) +func Test_RepoPathExists(t *testing.T) { + // Test path exists + repo := Repo{ + fullPath: ".", } + assert.True(t, repo.RepoPathExists()) + // Test path not found - res, _ = PathExists("NotExpectedToFindMe") - if res { - t.Errorf("Expected 'NotExpectedToFindMe' path to NOT exist, got: '%v'", res) + repo.fullPath = "NotExpectedToFindMe" + assert.False(t, repo.RepoPathExists()) +} + +func Test_generateSha(t *testing.T) { + type testCase struct { + name string + repoInfo string + expectedResult string + } + + testCases := []testCase{ + {name: "test 1", repoInfo: "Some string here", expectedResult: "21e5963"}, + {name: "test 2", repoInfo: "Another string here", expectedResult: "04d5c8f"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := generateSha(tc.repoInfo) + assert.Equal(t, tc.expectedResult, result) + }) } } -func TestRepoPathExists(t *testing.T) { - // Test path exists - repo := Repo{ - fullPath: ".", +func Test_SetMirrorURL(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult string + mirrorRootURL string } - if !repo.RepoPathExists() { - t.Errorf("Expected '.' path to exist") + testCases := []testCase{ + {name: "test repo abc", expectedResult: "abc/abc.git", repo: Repo{AltName: "abc"}, mirrorRootURL: "abc"}, + {name: "test repo qqq", expectedResult: "abc/qqq/cde.git", repo: Repo{AltName: "cde"}, mirrorRootURL: "abc/qqq"}, + {name: "test repo http://qqq", expectedResult: "http://qqq/cde.git", repo: Repo{AltName: "cde"}, mirrorRootURL: "http://qqq"}, + {name: "test repo git@qqq", expectedResult: "git@qqq/cde.git", repo: Repo{AltName: "cde"}, mirrorRootURL: "git@qqq"}, } - // Test path not found - repo.fullPath = "NotExpectedToFindMe" - if repo.RepoPathExists() { - t.Errorf("Expected 'NotExpectedToFindMe' path to NOT exist") + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tc.repo.SetMirrorURL(tc.mirrorRootURL) + assert.Equal(t, tc.expectedResult, tc.repo.mirrorURL) + }) } } -//(t *testing.T) { +func Test_Repo_IsRefTag(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult bool + returnError error + } + + testCases := []testCase{ + {name: "test 1", expectedResult: true, repo: Repo{Ref: "abc", fullPath: "cde_p"}, returnError: nil}, + {name: "test 2", expectedResult: false, repo: Repo{Ref: "cde", fullPath: "cde_a"}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + + mockGitExec.On( + "ExecGitCommand", + []string{"show-ref", "--quiet", "--verify", fmt.Sprintf("refs/tags/%s", tc.repo.Ref)}, + (*bytes.Buffer)(nil), + (*bytes.Buffer)(nil), + tc.repo.fullPath).Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.IsRefTag() + assert.Equal(t, tc.expectedResult, result) + }) + } +} +func Test_Repo_IsRefBranch(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult bool + returnError error + } + + testCases := []testCase{ + {name: "test 1", expectedResult: true, repo: Repo{Ref: "abc", fullPath: "cde_p"}, returnError: nil}, + {name: "test 2", expectedResult: false, repo: Repo{Ref: "cde", fullPath: "cde_a"}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + + mockGitExec.On( + "ExecGitCommand", + []string{"show-ref", "--quiet", "--verify", fmt.Sprintf("refs/heads/%s", tc.repo.Ref)}, + (*bytes.Buffer)(nil), + (*bytes.Buffer)(nil), + tc.repo.fullPath).Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.IsRefBranch() + assert.Equal(t, tc.expectedResult, result) + }) + } +} + +func Test_Repo_GitStashPop(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult bool + returnError error + } + + testCases := []testCase{ + {name: "test 1", expectedResult: true, repo: Repo{}, returnError: nil}, + {name: "test 2", expectedResult: false, repo: Repo{}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + serr := &bytes.Buffer{} + + mockGitExec.On( + "ExecGitCommand", + []string{"stash", "pop"}, + (*bytes.Buffer)(nil), + serr, + tc.repo.fullPath).Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.GitStashPop() + assert.Equal(t, tc.expectedResult, result) + assert.Equal(t, !tc.expectedResult, tc.repo.status.Error) + }) + } +} +func Test_Repo_GitStashSave(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult bool + returnError error + } + + testCases := []testCase{ + {name: "test 1", expectedResult: true, repo: Repo{}, returnError: nil}, + {name: "test 2", expectedResult: false, repo: Repo{}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + serr := &bytes.Buffer{} + + mockGitExec.On( + "ExecGitCommand", + []string{"stash", "save"}, + (*bytes.Buffer)(nil), + serr, + tc.repo.fullPath).Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.GitStashSave() + assert.Equal(t, tc.expectedResult, result) + assert.Equal(t, !tc.expectedResult, tc.repo.status.Error) + }) + } +} + +func Test_Repo_CloneMirror(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult bool + returnError error + } + + testCases := []testCase{ + {name: "test 1", expectedResult: true, repo: Repo{URL: "cde", fullPath: "cde_a"}, returnError: nil}, + {name: "test 2", expectedResult: false, repo: Repo{URL: "cde", fullPath: "cde_a"}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + serr := &bytes.Buffer{} + + mockGitExec.On( + "ExecGitCommand", + []string{"clone", "--mirror", tc.repo.URL, tc.repo.fullPath}, + (*bytes.Buffer)(nil), + serr, + "").Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.CloneMirror() + assert.Equal(t, tc.expectedResult, result) + }) + } +} +func Test_Repo_GetCurrentBranch(t *testing.T) { + type testCase struct { + name string + repo Repo + expectedResult string + returnError error + } + + testCases := []testCase{ + // Have not found a way to mutate `outb` at mock call invocation time to validate against `expectedResult` + {name: "test 1", expectedResult: "", repo: Repo{fullPath: "cde_a"}, returnError: nil}, + {name: "test 2", expectedResult: "", repo: Repo{fullPath: "cde_a"}, returnError: fmt.Errorf("test error")}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockGitExec := new(mocks.ShellRunnerI) + exe := &exec.Cmd{} + var outb, errb bytes.Buffer + + mockGitExec.On( + "ExecGitCommand", + []string{"rev-parse", "--abbrev-ref", "HEAD"}, + &outb, + &errb, + tc.repo.fullPath).Return(exe, tc.returnError) + + tc.repo.SetShellRunner(mockGitExec) + + result := tc.repo.GetCurrentBranch() + assert.Equal(t, tc.expectedResult, result) + }) + } +} diff --git a/gitlab/gitlab.go b/gitlab/gitlab.go index 5c8cdb9..c799cbd 100644 --- a/gitlab/gitlab.go +++ b/gitlab/gitlab.go @@ -33,29 +33,84 @@ import ( gitlab "github.com/xanzy/go-gitlab" ) -func gitlabAuth(repositorySha string, baseUrl string) *gitlab.Client { - token, tokenFound := os.LookupEnv("GITLAB_TOKEN") +type GitGetGitlab struct { + token string + client *gitlab.Client +} + +type GitGetGitlabI interface { + Init() bool + + gitlabAuth(repositorySha string, baseUrl string) bool + ProjectExists(repositorySha string, baseUrl string, projectName string) bool + GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPath string) (*gitlab.Namespace, string) + getGroupID(repoSha string, git *gitlab.Client, groupName string) (int, string, error) + + CreateProject( + repositorySha string, + baseUrl string, + projectName string, + namespaceID int, + mirrorVisibilityMode string, + sourceURL string, + ) *gitlab.Project + + processSubgroups( + repoSha string, + git *gitlab.Client, + groupID int, + groupName string, + glRepoList []*gitlab.Project, + gitlabOwned bool, + gitlabVisibility, gitlabMinAccessLevel string, + ) []*gitlab.Project + + appendGroupsProjects( + repoSha string, + git *gitlab.Client, + groupID int, + groupName string, + glRepoList []*gitlab.Project, + gitlabOwned bool, + gitlabVisibility string, + ) []*gitlab.Project + + FetchOwnerRepos( + repositorySha, baseURL, groupName string, + gitlabOwned bool, + gitlabVisibility, gitlabMinAccessLevel string, + ) []*gitlab.Project +} + +func (gitProvider *GitGetGitlab) Init() bool { + var tokenFound bool + gitProvider.token, tokenFound = os.LookupEnv("GITLAB_TOKEN") if !tokenFound { - log.Fatalf("%s: Error - environment variable GITLAB_TOKEN not found", repositorySha) + log.Fatal("Error - environment variable GITLAB_TOKEN not found") os.Exit(1) } + return tokenFound +} + +func (gitProvider *GitGetGitlab) auth(repositorySha string, baseUrl string) bool { clientOptions := gitlab.WithBaseURL("https://" + baseUrl) - git, err := gitlab.NewClient(token, clientOptions) + var err error + gitProvider.client, err = gitlab.NewClient(gitProvider.token, clientOptions) if err != nil { log.Fatalf("%s: Error - while trying to authenticate to Gitlab: %s", repositorySha, err) os.Exit(1) } - return git + return true } // ProjectExists checks if project exists and returns boolean if API call is successful -func ProjectExists(repositorySha string, baseUrl string, projectName string) bool { +func (gitProvider *GitGetGitlab) ProjectExists(repositorySha string, baseUrl string, projectName string) bool { log.Debugf("%s: Checking repository '%s' '%s' existence", repositorySha, baseUrl, projectName) - git := gitlabAuth(repositorySha, baseUrl) + gitProvider.auth(repositorySha, baseUrl) - prj, _, err := git.Projects.GetProject(projectName, nil, nil) + prj, _, err := gitProvider.client.Projects.GetProject(projectName, nil, nil) log.Debugf("%s: project: '%+v'", repositorySha, prj) @@ -67,9 +122,9 @@ func ProjectExists(repositorySha string, baseUrl string, projectName string) boo } // GetProjectNamespace - return Project Namespace and namespace full path -func GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPath string) (*gitlab.Namespace, string) { +func (gitProvider *GitGetGitlab) GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPath string) (*gitlab.Namespace, string) { log.Debugf("%s: Getting Project FullPath Namespace '%s'", repositorySha, projectNameFullPath) - git := gitlabAuth(repositorySha, baseUrl) + gitProvider.auth(repositorySha, baseUrl) pathElements := strings.Split(projectNameFullPath, "/") // Remove short project name from the path elements list @@ -78,7 +133,7 @@ func GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPa } namespaceFullPath := strings.Join(pathElements, "/") - namespaceObject, _, err := git.Namespaces.GetNamespace(namespaceFullPath, nil, nil) + namespaceObject, _, err := gitProvider.client.Namespaces.GetNamespace(namespaceFullPath, nil, nil) log.Debugf( "%s: Getting namespace '%s': resulting namespace object: '%+v'", @@ -92,7 +147,7 @@ func GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPa } // CreateProject - Create new code repository -func CreateProject( +func (gitProvider *GitGetGitlab) CreateProject( repositorySha string, baseUrl string, projectName string, @@ -100,7 +155,7 @@ func CreateProject( mirrorVisibilityMode string, sourceURL string, ) *gitlab.Project { - git := gitlabAuth(repositorySha, baseUrl) + gitProvider.auth(repositorySha, baseUrl) p := &gitlab.CreateProjectOptions{ Name: gitlab.String(projectName), @@ -112,7 +167,7 @@ func CreateProject( p.NamespaceID = gitlab.Int(namespaceID) } - project, _, err := git.Projects.CreateProject(p) + project, _, err := gitProvider.client.Projects.CreateProject(p) if err != nil { log.Fatalf( "%s: Error - while trying to create gitlab project '%s': '%s'", @@ -123,7 +178,7 @@ func CreateProject( return project } -func getGroupID(repoSha string, git *gitlab.Client, groupName string) (int, string, error) { +func (gitProvider *GitGetGitlab) getGroupID(repoSha string, git *gitlab.Client, groupName string) (int, string, error) { // Fetch group ID needed for other operations _, shortName := filepath.Split(groupName) //escapedGroupName := url.QueryEscape(groupName) @@ -146,7 +201,7 @@ func getGroupID(repoSha string, git *gitlab.Client, groupName string) (int, stri return 0, "", fmt.Errorf("%s: Group with name '%s' not found", repoSha, groupName) } -func processSubgroups( +func (gitProvider *GitGetGitlab) processSubgroups( repoSha string, git *gitlab.Client, groupID int, @@ -228,7 +283,7 @@ func processSubgroups( "%s: Recursive getRepositories call for subgroup '%d:%s'", repoSha, subGroups[currentGroup].ID, subGroups[currentGroup].FullName) - glRepoList = getRepositories( + glRepoList = gitProvider.getRepositories( repoSha, git, subGroups[currentGroup].ID, @@ -243,7 +298,7 @@ func processSubgroups( return glRepoList } -func appendGroupsProjects( +func (gitProvider *GitGetGitlab) appendGroupsProjects( repoSha string, git *gitlab.Client, groupID int, @@ -316,7 +371,7 @@ func appendGroupsProjects( } // Recursive function via processSubgroups -func getRepositories( +func (gitProvider *GitGetGitlab) getRepositories( repoSha string, git *gitlab.Client, groupID int, @@ -326,37 +381,45 @@ func getRepositories( gitlabVisibility, gitlabMinAccessLevel string, ) []*gitlab.Project { log.Debugf("%s: Ready to start processing subgroups for '%d:%s'", repoSha, groupID, groupName) - glRepoList = processSubgroups( + glRepoList = gitProvider.processSubgroups( repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel) log.Debugf("%s: Ready to start processing projects for '%d:%s'", repoSha, groupID, groupName) - glRepoList = appendGroupsProjects(repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility) + glRepoList = gitProvider.appendGroupsProjects( + repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility) return glRepoList } // FetchOwnerRepos - fetches all repositories for the specified gitlab path -func FetchOwnerRepos( - repoSha, baseURL, groupName string, +func (gitProvider *GitGetGitlab) FetchOwnerRepos( + repositorySha, baseURL, groupName string, gitlabOwned bool, gitlabVisibility, gitlabMinAccessLevel string, ) []*gitlab.Project { - git := gitlabAuth(repoSha, baseURL) + gitProvider.auth(repositorySha, baseURL) var glRepoList []*gitlab.Project - log.Debugf("%s: Get groupID for '%s'", repoSha, groupName) - groupID, fullGroupName, err := getGroupID(repoSha, git, groupName) + log.Debugf("%s: Get groupID for '%s'", repositorySha, groupName) + groupID, fullGroupName, err := gitProvider.getGroupID(repositorySha, gitProvider.client, groupName) if err != nil { log.Errorf( "%s: Error while trying to find group '%s': %s", - repoSha, groupName, err, + repositorySha, groupName, err, ) return glRepoList } - log.Debugf("%s: GroupID for '%s' is '%d'", repoSha, fullGroupName, groupID) - - glRepoList = getRepositories( - repoSha, git, groupID, fullGroupName, glRepoList, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel, + log.Debugf("%s: GroupID for '%s' is '%d'", repositorySha, fullGroupName, groupID) + + glRepoList = gitProvider.getRepositories( + repositorySha, + gitProvider.client, + groupID, + fullGroupName, + glRepoList, + gitlabOwned, + gitlabVisibility, + gitlabMinAccessLevel, ) return glRepoList diff --git a/gitlab/mocks/GitGetGitlabI.go b/gitlab/mocks/GitGetGitlabI.go new file mode 100644 index 0000000..589e008 --- /dev/null +++ b/gitlab/mocks/GitGetGitlabI.go @@ -0,0 +1,170 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + gitlab "github.com/xanzy/go-gitlab" +) + +// GitGetGitlabI is an autogenerated mock type for the GitGetGitlabI type +type GitGetGitlabI struct { + mock.Mock +} + +// CreateProject provides a mock function with given fields: repositorySha, baseUrl, projectName, namespaceID, mirrorVisibilityMode, sourceURL +func (_m *GitGetGitlabI) CreateProject(repositorySha string, baseUrl string, projectName string, namespaceID int, mirrorVisibilityMode string, sourceURL string) *gitlab.Project { + ret := _m.Called(repositorySha, baseUrl, projectName, namespaceID, mirrorVisibilityMode, sourceURL) + + var r0 *gitlab.Project + if rf, ok := ret.Get(0).(func(string, string, string, int, string, string) *gitlab.Project); ok { + r0 = rf(repositorySha, baseUrl, projectName, namespaceID, mirrorVisibilityMode, sourceURL) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Project) + } + } + + return r0 +} + +// FetchOwnerRepos provides a mock function with given fields: repositorySha, baseURL, groupName, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel +func (_m *GitGetGitlabI) FetchOwnerRepos(repositorySha string, baseURL string, groupName string, gitlabOwned bool, gitlabVisibility string, gitlabMinAccessLevel string) []*gitlab.Project { + ret := _m.Called(repositorySha, baseURL, groupName, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel) + + var r0 []*gitlab.Project + if rf, ok := ret.Get(0).(func(string, string, string, bool, string, string) []*gitlab.Project); ok { + r0 = rf(repositorySha, baseURL, groupName, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.Project) + } + } + + return r0 +} + +// GetProjectNamespace provides a mock function with given fields: repositorySha, baseUrl, projectNameFullPath +func (_m *GitGetGitlabI) GetProjectNamespace(repositorySha string, baseUrl string, projectNameFullPath string) (*gitlab.Namespace, string) { + ret := _m.Called(repositorySha, baseUrl, projectNameFullPath) + + var r0 *gitlab.Namespace + if rf, ok := ret.Get(0).(func(string, string, string) *gitlab.Namespace); ok { + r0 = rf(repositorySha, baseUrl, projectNameFullPath) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Namespace) + } + } + + var r1 string + if rf, ok := ret.Get(1).(func(string, string, string) string); ok { + r1 = rf(repositorySha, baseUrl, projectNameFullPath) + } else { + r1 = ret.Get(1).(string) + } + + return r0, r1 +} + +// Init provides a mock function with given fields: +func (_m *GitGetGitlabI) Init() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// ProjectExists provides a mock function with given fields: repositorySha, baseUrl, projectName +func (_m *GitGetGitlabI) ProjectExists(repositorySha string, baseUrl string, projectName string) bool { + ret := _m.Called(repositorySha, baseUrl, projectName) + + var r0 bool + if rf, ok := ret.Get(0).(func(string, string, string) bool); ok { + r0 = rf(repositorySha, baseUrl, projectName) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// appendGroupsProjects provides a mock function with given fields: repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility +func (_m *GitGetGitlabI) appendGroupsProjects(repoSha string, git *gitlab.Client, groupID int, groupName string, glRepoList []*gitlab.Project, gitlabOwned bool, gitlabVisibility string) []*gitlab.Project { + ret := _m.Called(repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility) + + var r0 []*gitlab.Project + if rf, ok := ret.Get(0).(func(string, *gitlab.Client, int, string, []*gitlab.Project, bool, string) []*gitlab.Project); ok { + r0 = rf(repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.Project) + } + } + + return r0 +} + +// getGroupID provides a mock function with given fields: repoSha, git, groupName +func (_m *GitGetGitlabI) getGroupID(repoSha string, git *gitlab.Client, groupName string) (int, string, error) { + ret := _m.Called(repoSha, git, groupName) + + var r0 int + if rf, ok := ret.Get(0).(func(string, *gitlab.Client, string) int); ok { + r0 = rf(repoSha, git, groupName) + } else { + r0 = ret.Get(0).(int) + } + + var r1 string + if rf, ok := ret.Get(1).(func(string, *gitlab.Client, string) string); ok { + r1 = rf(repoSha, git, groupName) + } else { + r1 = ret.Get(1).(string) + } + + var r2 error + if rf, ok := ret.Get(2).(func(string, *gitlab.Client, string) error); ok { + r2 = rf(repoSha, git, groupName) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// gitlabAuth provides a mock function with given fields: repositorySha, baseUrl +func (_m *GitGetGitlabI) gitlabAuth(repositorySha string, baseUrl string) bool { + ret := _m.Called(repositorySha, baseUrl) + + var r0 bool + if rf, ok := ret.Get(0).(func(string, string) bool); ok { + r0 = rf(repositorySha, baseUrl) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// processSubgroups provides a mock function with given fields: repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel +func (_m *GitGetGitlabI) processSubgroups(repoSha string, git *gitlab.Client, groupID int, groupName string, glRepoList []*gitlab.Project, gitlabOwned bool, gitlabVisibility string, gitlabMinAccessLevel string) []*gitlab.Project { + ret := _m.Called(repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel) + + var r0 []*gitlab.Project + if rf, ok := ret.Get(0).(func(string, *gitlab.Client, int, string, []*gitlab.Project, bool, string, string) []*gitlab.Project); ok { + r0 = rf(repoSha, git, groupID, groupName, glRepoList, gitlabOwned, gitlabVisibility, gitlabMinAccessLevel) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.Project) + } + } + + return r0 +} diff --git a/go.mod b/go.mod index 5122131..5dffa9e 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,10 @@ go 1.17 require ( github.com/fatih/color v1.13.0 github.com/google/go-github/v43 v43.0.0 - github.com/ktrysmt/go-bitbucket v0.9.36 + github.com/ktrysmt/go-bitbucket v0.9.37 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.3.0 + github.com/stretchr/testify v1.7.0 github.com/xanzy/go-gitlab v0.55.1 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 @@ -16,6 +17,7 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -24,10 +26,13 @@ require ( github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.1.1 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index af80aa2..ee018e6 100644 --- a/go.sum +++ b/go.sum @@ -262,8 +262,8 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/ktrysmt/go-bitbucket v0.9.36 h1:tXuZarVceStMxkmFxkSDMPfbm/Zff6wd8ctmus4d/s4= -github.com/ktrysmt/go-bitbucket v0.9.36/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= +github.com/ktrysmt/go-bitbucket v0.9.37 h1:4R1nDZopDci4e/JGFql7fHffVQPbuWiShMLJ2yi82gs= +github.com/ktrysmt/go-bitbucket v0.9.37/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -340,6 +340,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=