diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7c1c7e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.idea \ No newline at end of file diff --git a/README.md b/README.md index eceb64f..39d2279 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,15 @@ By default, the config file is searched for in `[HOME_DIR]./config/grm/config.ya ### Commands -| command | Description | -|---------|-------------| -| sync | Fetches changes from repositories or pulls a repository if one does not exist. -| status | Get repository information - what is the current branch, how many commits are above and behind it for each remote. +| command | Description | +|---------|--------------------------------------------------------------------------------------------------------------------| +| sync | Fetches changes from repositories or pulls a repository if one does not exist. | +| status | Get repository information - what is the current branch, how many commits are above and behind it for each remote. | ## Changelog +- 0.3.2 3rd party security libs update +- 0.3.1 Upgrade to Go 1.19 - 0.3.0 Adding the ability to limit actions to repositories containing a given name or tags - 0.2.0 Add status command - get information about the current status in the repository - 0.1.1 Allow to use env vars in config diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..cb9e044 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,26 @@ +version: '3' + +tasks: + pull: + cmds: + - go mod download + silent: true + + test: + cmds: + - go test $(find './internal' -name "*.go" -exec dirname {} \; | uniq | grep '/') -cover + + build: + dir: "cmd" + deps: + - pull + cmds: + - mkdir -p ../build + - go build -o ../build/grm + + install: + dir: "build" + deps: + - build + cmds: + - cp grm ${GOPATH}/bin/grm diff --git a/main.go b/cmd/main.go similarity index 67% rename from main.go rename to cmd/main.go index 51cd378..e013f5f 100644 --- a/main.go +++ b/cmd/main.go @@ -1,16 +1,13 @@ package main import ( + "gitlab.com/revalus/grm/internal/grm" "os" - - "gitlab.com/revalus/grm/app" ) -const () - func main() { - app := app.GitRepositoryManager{} + app := grm.GitRepositoryManager{} err := app.Parse(os.Args) if err != nil { os.Exit(2) diff --git a/commands/common_utils_test.go b/commands/common_utils_test.go deleted file mode 100644 index 07dfc8b..0000000 --- a/commands/common_utils_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package commands - -import ( - "fmt" - "os" - - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/osfs" - "github.com/go-git/go-git/v5" - gitcfg "github.com/go-git/go-git/v5/config" - "github.com/go-git/go-git/v5/plumbing/cache" - "github.com/go-git/go-git/v5/storage/filesystem" - "gitlab.com/revalus/grm/config" -) - -type TestSetup struct { - rootFS billy.Filesystem - baseRepository struct { - fileSystem billy.Filesystem - repo *git.Repository - } -} - -func checkErrorDuringPreparation(err error) { - if err != nil { - fmt.Printf("Cannot prepare a temporary directory for testing! %v ", err.Error()) - os.Exit(2) - } -} - -func createTmpDir() string { - - baseForTMPDir := fmt.Sprintf("%v/grmTest", os.TempDir()) - if _, ok := os.Stat(baseForTMPDir); ok != nil { - err := os.Mkdir(baseForTMPDir, 0777) - checkErrorDuringPreparation(err) - } - - tempDir, err := os.MkdirTemp(baseForTMPDir, "*") - checkErrorDuringPreparation(err) - - return tempDir -} - -func getTestSetup() TestSetup { - - tmpDir := createTmpDir() - - baseFileSystem := osfs.New(tmpDir) - - initRepositoryFileSystem, err := baseFileSystem.Chroot("worktree") - checkErrorDuringPreparation(err) - - directoryForGitMetadata, err := initRepositoryFileSystem.Chroot(".git") - checkErrorDuringPreparation(err) - - repository, err := git.Init(filesystem.NewStorage(directoryForGitMetadata, cache.NewObjectLRUDefault()), initRepositoryFileSystem) - checkErrorDuringPreparation(err) - - fileForFirstCommit, err := initRepositoryFileSystem.Create("TestFile.txt") - checkErrorDuringPreparation(err) - - _, err = fileForFirstCommit.Write([]byte("foo-conent")) - checkErrorDuringPreparation(err) - - repositoryWorkTree, err := repository.Worktree() - checkErrorDuringPreparation(err) - - repositoryWorkTree.Add(fileForFirstCommit.Name()) - _, err = repositoryWorkTree.Commit("First commit", &git.CommitOptions{}) - - checkErrorDuringPreparation(err) - - return TestSetup{ - baseRepository: struct { - fileSystem billy.Filesystem - repo *git.Repository - }{ - fileSystem: initRepositoryFileSystem, - repo: repository, - }, - rootFS: baseFileSystem, - } - -} - -func makeCommit(wk *git.Worktree, commitMessage string) { - - _, err := wk.Commit(commitMessage, &git.CommitOptions{}) - checkErrorDuringPreparation(err) - -} - -func getFSForLocalRepo(dirName string, baseFileSystem billy.Filesystem) (billy.Filesystem, *filesystem.Storage) { - fsForLocalRepo, err := baseFileSystem.Chroot(dirName) - checkErrorDuringPreparation(err) - fsForMetadata, err := fsForLocalRepo.Chroot(".git") - checkErrorDuringPreparation(err) - storageForTestRepo := filesystem.NewStorage(fsForMetadata, cache.NewObjectLRUDefault()) - return fsForLocalRepo, storageForTestRepo -} - -func getBaseForTestingSyncCommand() (StatusChecker, *git.Repository, config.RepositoryConfig, TestSetup) { - tmpDirWithInitialRepository := getTestSetup() - dirNameForLocalRepository := "testRepo" - fsForLocalRepo, storageForTestRepo := getFSForLocalRepo(dirNameForLocalRepository, tmpDirWithInitialRepository.rootFS) - - fakeLocalRepository, err := git.Clone(storageForTestRepo, fsForLocalRepo, &git.CloneOptions{ - URL: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), - }) - checkErrorDuringPreparation(err) - - sc := StatusChecker{ - workspace: tmpDirWithInitialRepository.rootFS.Root(), - } - - repoCfg := config.RepositoryConfig{ - Name: "test", - Src: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), - Dest: dirNameForLocalRepository, - } - - return sc, fakeLocalRepository, repoCfg, tmpDirWithInitialRepository -} - -func getBaseForTestingSyncMultipleRemote() (StatusChecker, *git.Repository, config.RepositoryConfig) { - sc, fakeLocalRepository, repoCfg, tmpDirWithInitialRepository := getBaseForTestingSyncCommand() - - fakeLocalRepository.CreateRemote(&gitcfg.RemoteConfig{ - Name: "subremote", - URLs: []string{tmpDirWithInitialRepository.baseRepository.fileSystem.Root()}, - }) - - fakeLocalRepository.Fetch(&git.FetchOptions{ - RemoteName: "subremote", - }) - return sc, fakeLocalRepository, repoCfg -} diff --git a/go.mod b/go.mod index 2896766..ddc7f7d 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,33 @@ module gitlab.com/revalus/grm -go 1.17 +go 1.19 require ( - github.com/akamensky/argparse v1.3.1 - github.com/go-git/go-billy/v5 v5.3.1 - github.com/go-git/go-git/v5 v5.4.2 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + github.com/akamensky/argparse v1.4.0 + github.com/go-git/go-billy/v5 v5.5.0 + github.com/go-git/go-git/v5 v5.11.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/Microsoft/go-winio v0.5.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7 // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/google/go-cmp v0.5.6 // indirect - github.com/imdario/mergo v0.3.12 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kevinburke/ssh_config v1.1.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/xanzy/ssh-agent v0.3.1 // indirect - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect - golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 // indirect - golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c // indirect + github.com/skeema/knownhosts v1.2.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 91471eb..edc65bf 100644 --- a/go.sum +++ b/go.sum @@ -1,124 +1,132 @@ -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7 h1:DSqTh6nEes/uO8BlNcGk8PzZsxY2sN9ZL//veWBdTRI= -github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/akamensky/argparse v1.3.1 h1:kP6+OyvR0fuBH6UhbE6yh/nskrDEIQgEA1SUXDPjx4g= -github.com/akamensky/argparse v1.3.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc= +github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= -github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= -github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 h1:VrJZAjbekhoRn7n5FBujY31gboH+iB3pdLxn3gE9FjU= -golang.org/x/net v0.0.0-20211101193420-4a448f8816b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c h1:QOfDMdrf/UwlVR0UBq2Mpr58UzNtvgJRXA4BgPfFACs= -golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/commands/command.go b/internal/commands/command.go similarity index 78% rename from commands/command.go rename to internal/commands/command.go index 88bf1e9..86706b3 100644 --- a/commands/command.go +++ b/internal/commands/command.go @@ -1,6 +1,8 @@ package commands -import "gitlab.com/revalus/grm/config" +import ( + "gitlab.com/revalus/grm/internal/config" +) type Command interface { Command(repoCfg config.RepositoryConfig) CommandStatus diff --git a/internal/commands/common_utils_test.go b/internal/commands/common_utils_test.go new file mode 100644 index 0000000..505f9be --- /dev/null +++ b/internal/commands/common_utils_test.go @@ -0,0 +1,118 @@ +package commands + +import ( + "fmt" + "os" + "path" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/osfs" + "github.com/go-git/go-git/v5" + gitcfg "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing/cache" + "github.com/go-git/go-git/v5/storage/filesystem" +) + +type TestSetupPaths struct { + baseTestDirectory string + baseTestRepository string +} + +func checkErrorDuringPreparation(err error) { + if err != nil { + fmt.Printf("Cannot prepare a temporary directory for testing! %v ", err.Error()) + os.Exit(2) + } +} + +func createRepositoryForTest() string { + systemTMPDirectoryWithTestPath := fmt.Sprintf("%v/grmTest", os.TempDir()) + if _, ok := os.Stat(systemTMPDirectoryWithTestPath); ok != nil { + err := os.Mkdir(systemTMPDirectoryWithTestPath, 0777) + checkErrorDuringPreparation(err) + } + temporaryDirPath, err := os.MkdirTemp(systemTMPDirectoryWithTestPath, "*") + checkErrorDuringPreparation(err) + return temporaryDirPath +} + +// prepareRepositoryDirectories - prepare directories for file (rootRepositoryDirectory) and git metadata (gitMetadataDirectory) +func prepareRepositoryDirectories(dirName string) (billy.Filesystem, billy.Filesystem) { + rootRepositoryDirectory := osfs.New(dirName) + gitMetadataDirectory, err := rootRepositoryDirectory.Chroot(".git") + checkErrorDuringPreparation(err) + + return rootRepositoryDirectory, gitMetadataDirectory +} + +func prepareBasicRepository() TestSetupPaths { + + temporaryDirPath := createRepositoryForTest() + + // Create an interface of abstraction over filesystem to provide tests over multiple systems + // baseTestsDirectory - provides to main directory where new directories might be created + baseTestsDirectory := osfs.New(temporaryDirPath) + rootRepositoryDirectory, gitMetadataDirectory := prepareRepositoryDirectories(baseTestsDirectory.Root() + "/base_repository") + + repository, err := git.Init(filesystem.NewStorage( + gitMetadataDirectory, + cache.NewObjectLRUDefault()), + rootRepositoryDirectory, + ) + checkErrorDuringPreparation(err) + + testFile, err := rootRepositoryDirectory.Create("TestFile.txt") + checkErrorDuringPreparation(err) + + _, err = testFile.Write([]byte("foo-conent")) + checkErrorDuringPreparation(err) + + repositoryWorkTree, err := repository.Worktree() + checkErrorDuringPreparation(err) + + _, err = repositoryWorkTree.Add(testFile.Name()) + checkErrorDuringPreparation(err) + + _, err = repositoryWorkTree.Commit("First commit", &git.CommitOptions{}) + checkErrorDuringPreparation(err) + + return TestSetupPaths{ + baseTestDirectory: baseTestsDirectory.Root(), + baseTestRepository: rootRepositoryDirectory.Root(), + } + +} + +func makeCommit(wk *git.Worktree, commitMessage string) { + _, err := wk.Commit(commitMessage, &git.CommitOptions{}) + checkErrorDuringPreparation(err) +} + +// createAndCloneRepository - create sub-repository with cloned base repository required to verify sync command +func createAndCloneRepository(repositoryName string, paths TestSetupPaths) *git.Repository { + + baseGitRepository, gitMetadataDirectory := prepareRepositoryDirectories( + path.Join(paths.baseTestDirectory, repositoryName), + ) + + storageForSubRepository := filesystem.NewStorage(gitMetadataDirectory, cache.NewObjectLRUDefault()) + fakeLocalRepository, err := git.Clone(storageForSubRepository, baseGitRepository, &git.CloneOptions{ + URL: paths.baseTestRepository, + }) + checkErrorDuringPreparation(err) + return fakeLocalRepository +} + +func addLocalRepositoryAsAFakeRemoteRepository(repository *git.Repository, baseTestRepositoryPath string) error { + + _, err := repository.CreateRemote(&gitcfg.RemoteConfig{ + Name: "subremote", + URLs: []string{baseTestRepositoryPath}, + }) + if err != nil { + return err + } + return repository.Fetch(&git.FetchOptions{ + RemoteName: "subremote", + }) +} diff --git a/commands/status_cmd.go b/internal/commands/status_cmd.go similarity index 78% rename from commands/status_cmd.go rename to internal/commands/status_cmd.go index 3279f5b..db55e69 100644 --- a/commands/status_cmd.go +++ b/internal/commands/status_cmd.go @@ -2,11 +2,12 @@ package commands import ( "fmt" - "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" - "gitlab.com/revalus/grm/config" + "gitlab.com/revalus/grm/internal/config" + "path" + "sort" ) type StatusChecker struct { @@ -20,7 +21,7 @@ func NewStatusChecker(workspace string) StatusChecker { } func findNumberOfCommitDiffs(srcCommit *object.Commit, dstCommit *object.Commit) int { - + // This function is a helper function to get only five latest items, based on given commit getFiveElementsFromHashes := func(commit *object.Commit, hashedSlice *[]string) *object.Commit { var err error @@ -36,6 +37,7 @@ func findNumberOfCommitDiffs(srcCommit *object.Commit, dstCommit *object.Commit) return commit } + // Compare diff between sources by hash list (the same hash list must be present to assume the end of changes) getRangeDiff := func(listFist, listSecond []string) (int, bool) { diffRange := 0 @@ -52,8 +54,10 @@ func findNumberOfCommitDiffs(srcCommit *object.Commit, dstCommit *object.Commit) return diffRange, false } - baseCommitHashes := []string{} - destCommitHashes := []string{} + var baseCommitHashes []string + var destCommitHashes []string + + // Try to find all differences, limit only to five last changes to avoid reading whole repository at once for { if srcCommit != nil { @@ -80,8 +84,8 @@ func (sc StatusChecker) Command(repoCfg config.RepositoryConfig) CommandStatus { Error: false, } - destPath := fmt.Sprintf("%v/%v", sc.workspace, repoCfg.Dest) - repo, err := git.PlainOpen(destPath) + repositoryPath := path.Join(sc.workspace, repoCfg.Dest) + repo, err := git.PlainOpen(repositoryPath) if err != nil { cmdStatus.Error = true @@ -116,14 +120,14 @@ func (sc StatusChecker) Command(repoCfg config.RepositoryConfig) CommandStatus { err error } - remotesStatus := make(map[string]remoteStatus) + var remoteNames []string + remoteStatues := make(map[string]remoteStatus) for _, remote := range remotes { remoteName := remote.Config().Name - remoteRevision, err := repo.ResolveRevision(plumbing.Revision(fmt.Sprintf("%v/%v", remoteName, headReference.Name().Short()))) if err != nil { - remotesStatus[remoteName] = remoteStatus{ + remoteStatues[remoteName] = remoteStatus{ err: err, } continue @@ -131,7 +135,7 @@ func (sc StatusChecker) Command(repoCfg config.RepositoryConfig) CommandStatus { remoteBranchCommit, err := repo.CommitObject(*remoteRevision) if err != nil { - remotesStatus[remoteName] = remoteStatus{ + remoteStatues[remoteName] = remoteStatus{ err: err, } continue @@ -144,11 +148,14 @@ func (sc StatusChecker) Command(repoCfg config.RepositoryConfig) CommandStatus { if status.ahead > 0 || status.behind > 0 { cmdStatus.Changed = true } - remotesStatus[remoteName] = status + remoteNames = append(remoteNames, remoteName) + remoteStatues[remoteName] = status } + sort.Strings(remoteNames) cmdStatus.Message = fmt.Sprintf("branch %v", headReference.Name().Short()) - for remoteName, status := range remotesStatus { + for _, remoteName := range remoteNames { + status := remoteStatues[remoteName] if status.err != nil { cmdStatus.Message = fmt.Sprintf("%v - ( | %v | problem: %v )", cmdStatus.Message, remoteName, status.err.Error()) continue diff --git a/commands/status_cmd_test.go b/internal/commands/status_cmd_test.go similarity index 67% rename from commands/status_cmd_test.go rename to internal/commands/status_cmd_test.go index e8b18a1..9bd3242 100644 --- a/commands/status_cmd_test.go +++ b/internal/commands/status_cmd_test.go @@ -2,20 +2,23 @@ package commands import ( "fmt" + "github.com/go-git/go-git/v5/plumbing/cache" + "github.com/go-git/go-git/v5/storage/filesystem" + "gitlab.com/revalus/grm/internal/config" + "path" "testing" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/storage/memory" - "gitlab.com/revalus/grm/config" ) func TestIfBranchesAreEqual(t *testing.T) { - tmpDirWithInitialRepository := getTestSetup() + pathsToTest := prepareBasicRepository() fakeLocalRepo, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{ - URL: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), + URL: pathsToTest.baseTestRepository, }) checkErrorDuringPreparation(err) @@ -42,9 +45,9 @@ func TestIfBranchesAreEqual(t *testing.T) { func TestIfCurrentBranchIsDifferent(t *testing.T) { - tmpDirWithInitialRepository := getTestSetup() + pathsToTest := prepareBasicRepository() fakeLocalRepo, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{ - URL: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), + URL: pathsToTest.baseTestRepository, }) checkErrorDuringPreparation(err) @@ -85,28 +88,21 @@ func TestIfCurrentBranchIsDifferent(t *testing.T) { result = findNumberOfCommitDiffs(currentBranchCommit, remoteBranchCommit) if result != 15 { - t.Errorf("Expected to get 5 changes, instead of this got %v", result) + t.Errorf("Expected to get 15 changes, instead of this got %v", result) } } func TestCommandRepositoryDoesNotExists(t *testing.T) { - tmpDirWithInitialRepository := getTestSetup() - fsForLocalRepo, storageForTestRepo := getFSForLocalRepo("noMatterValue", tmpDirWithInitialRepository.rootFS) - - _, err := git.Clone(storageForTestRepo, fsForLocalRepo, &git.CloneOptions{ - URL: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), - }) - checkErrorDuringPreparation(err) - + pathsToTest := prepareBasicRepository() sc := StatusChecker{ - workspace: tmpDirWithInitialRepository.rootFS.Root(), + workspace: pathsToTest.baseTestDirectory, } repoCfg := config.RepositoryConfig{ Name: "test", - Src: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), - Dest: tmpDirWithInitialRepository.rootFS.Root(), + Src: pathsToTest.baseTestRepository, + Dest: pathsToTest.baseTestDirectory, } repoStatus := sc.Command(repoCfg) @@ -125,12 +121,15 @@ func TestCommandRepositoryDoesNotExists(t *testing.T) { func TestCommandRepositoryNoRemoteBranch(t *testing.T) { - tmpDirWithInitialRepository := getTestSetup() - dirNameForLocalRepository := "testRepo" - fsForLocalRepo, storageForTestRepo := getFSForLocalRepo(dirNameForLocalRepository, tmpDirWithInitialRepository.rootFS) + pathsToTest := prepareBasicRepository() + dirNameForLocalRepository := "sub-repository" + fsForLocalRepo, gitMetadataDirectory := prepareRepositoryDirectories( + path.Join(pathsToTest.baseTestDirectory, dirNameForLocalRepository), + ) + storageForTestRepo := filesystem.NewStorage(gitMetadataDirectory, cache.NewObjectLRUDefault()) fakeLocalRepository, err := git.Clone(storageForTestRepo, fsForLocalRepo, &git.CloneOptions{ - URL: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), + URL: pathsToTest.baseTestRepository, }) checkErrorDuringPreparation(err) @@ -138,12 +137,12 @@ func TestCommandRepositoryNoRemoteBranch(t *testing.T) { checkErrorDuringPreparation(err) sc := StatusChecker{ - workspace: tmpDirWithInitialRepository.rootFS.Root(), + workspace: pathsToTest.baseTestDirectory, } repoCfg := config.RepositoryConfig{ Name: "test", - Src: tmpDirWithInitialRepository.baseRepository.fileSystem.Root(), + Src: pathsToTest.baseTestRepository, Dest: dirNameForLocalRepository, } @@ -164,7 +163,21 @@ func TestCommandRepositoryNoRemoteBranch(t *testing.T) { func TestCommandAllCorrectWithoutChanges(t *testing.T) { - sc, _, repoCfg, _ := getBaseForTestingSyncCommand() + pathsToTest := prepareBasicRepository() + subRepositoryDirectoryName := "sub-repository" + + // Get new empty repository to compare with base repository + createAndCloneRepository(subRepositoryDirectoryName, pathsToTest) + + sc := StatusChecker{ + workspace: pathsToTest.baseTestDirectory, + } + + repoCfg := config.RepositoryConfig{ + Name: "test", + Src: pathsToTest.baseTestRepository, + Dest: subRepositoryDirectoryName, + } repoStatus := sc.Command(repoCfg) expectedMessage := "branch master - ( | origin | \u21910 \u21930 )" @@ -182,7 +195,19 @@ func TestCommandAllCorrectWithoutChanges(t *testing.T) { } func TestCommandAllCorrectWithOneChange(t *testing.T) { - sc, fakeLocalRepository, repoCfg, _ := getBaseForTestingSyncCommand() + pathsToTest := prepareBasicRepository() + subRepositoryDirectoryName := "sub-repository" + fakeLocalRepository := createAndCloneRepository(subRepositoryDirectoryName, pathsToTest) + + sc := StatusChecker{ + workspace: pathsToTest.baseTestDirectory, + } + + repoCfg := config.RepositoryConfig{ + Name: "test", + Src: pathsToTest.baseTestRepository, + Dest: subRepositoryDirectoryName, + } fakeLocalWorkTree, err := fakeLocalRepository.Worktree() checkErrorDuringPreparation(err) @@ -207,9 +232,26 @@ func TestCommandAllCorrectWithOneChange(t *testing.T) { } } -func TestCommandMultiRemoteNoChanges(t *testing.T) { +func TestCommandMultiRemotesNoChanges(t *testing.T) { + pathsToTest := prepareBasicRepository() + subRepositoryDirectoryName := "sub-repository" + fakeLocalRepository := createAndCloneRepository(subRepositoryDirectoryName, pathsToTest) + + sc := StatusChecker{ + workspace: pathsToTest.baseTestDirectory, + } + + repoCfg := config.RepositoryConfig{ + Name: "test", + Src: pathsToTest.baseTestRepository, + Dest: subRepositoryDirectoryName, + } + + err := addLocalRepositoryAsAFakeRemoteRepository(fakeLocalRepository, pathsToTest.baseTestRepository) + if err != nil { + t.Errorf("Unexpected error %v", err) + } - sc, _, repoCfg := getBaseForTestingSyncMultipleRemote() repoStatus := sc.Command(repoCfg) expectedMessage := "branch master - ( | origin | \u21910 \u21930 ) - ( | subremote | \u21910 \u21930 )" @@ -225,8 +267,25 @@ func TestCommandMultiRemoteNoChanges(t *testing.T) { } } -func TestCommandMultiRemoteWithOneChange(t *testing.T) { - sc, fakeLocalRepository, repoCfg := getBaseForTestingSyncMultipleRemote() +func TestCommandMultiRemotesWithOneChange(t *testing.T) { + pathsToTest := prepareBasicRepository() + subRepositoryDirectoryName := "sub-repository" + fakeLocalRepository := createAndCloneRepository(subRepositoryDirectoryName, pathsToTest) + + sc := StatusChecker{ + workspace: pathsToTest.baseTestDirectory, + } + + repoCfg := config.RepositoryConfig{ + Name: "test", + Src: pathsToTest.baseTestRepository, + Dest: subRepositoryDirectoryName, + } + + err := addLocalRepositoryAsAFakeRemoteRepository(fakeLocalRepository, pathsToTest.baseTestRepository) + if err != nil { + t.Errorf("Unexpected error %v", err) + } fakeLocalWorkTree, err := fakeLocalRepository.Worktree() checkErrorDuringPreparation(err) diff --git a/commands/sync_cmd.go b/internal/commands/sync_cmd.go similarity index 68% rename from commands/sync_cmd.go rename to internal/commands/sync_cmd.go index 36d1be2..b82e6f6 100644 --- a/commands/sync_cmd.go +++ b/internal/commands/sync_cmd.go @@ -1,10 +1,11 @@ package commands import ( + "errors" "fmt" + "gitlab.com/revalus/grm/internal/config" "github.com/go-git/go-git/v5" - "gitlab.com/revalus/grm/config" ) type Synchronizer struct { @@ -26,15 +27,14 @@ const ( func fetchRepository(repo *git.Repository) (bool, error) { err := repo.Fetch(&git.FetchOptions{}) - if err == git.NoErrAlreadyUpToDate { + switch { + case errors.Is(err, git.NoErrAlreadyUpToDate): return false, nil + case errors.Is(err, git.NoErrAlreadyUpToDate): + return false, nil + default: + return true, nil } - - if err != nil && err != git.NoErrAlreadyUpToDate { - return false, err - } - - return true, nil } func cloneRepository(destPath string, repoCfg *config.RepositoryConfig) (bool, error) { @@ -62,22 +62,24 @@ func (s Synchronizer) Command(repoCfg config.RepositoryConfig) CommandStatus { destPath := fmt.Sprintf("%v/%v", s.workspace, repoCfg.Dest) repo, err := git.PlainOpen(destPath) - if err != nil && err == git.ErrRepositoryNotExists { - cmdStatus.Changed, err = cloneRepository(destPath, &repoCfg) - cmdStatus.Message = syncCloned - } else if err == nil { - cmdStatus.Changed, err = fetchRepository(repo) - if cmdStatus.Changed { - cmdStatus.Message = syncFetched + if err != nil { + if errors.Is(err, git.ErrRepositoryNotExists) { + cmdStatus.Changed, err = cloneRepository(destPath, &repoCfg) + cmdStatus.Message = syncCloned } else { - cmdStatus.Message = syncUpToDate + cmdStatus.Error = true + cmdStatus.Message = err.Error() } - } else { - cmdStatus.Error = true - cmdStatus.Message = err.Error() return cmdStatus } + cmdStatus.Changed, err = fetchRepository(repo) + if cmdStatus.Changed { + cmdStatus.Message = syncFetched + } else { + cmdStatus.Message = syncUpToDate + } + if err != nil { cmdStatus.Error = true cmdStatus.Message = err.Error() diff --git a/commands/sync_cmd_test.go b/internal/commands/sync_cmd_test.go similarity index 80% rename from commands/sync_cmd_test.go rename to internal/commands/sync_cmd_test.go index da086d3..758e95d 100644 --- a/commands/sync_cmd_test.go +++ b/internal/commands/sync_cmd_test.go @@ -2,10 +2,9 @@ package commands import ( "fmt" + "gitlab.com/revalus/grm/internal/config" "os" "testing" - - "gitlab.com/revalus/grm/config" ) func TestSyncInit(t *testing.T) { @@ -17,14 +16,14 @@ func TestSyncInit(t *testing.T) { func TestSyncCommand(t *testing.T) { - testSetup := getTestSetup() + pathsToTest := prepareBasicRepository() sync := Synchronizer{ - workspace: testSetup.rootFS.Root(), + workspace: pathsToTest.baseTestDirectory, } cfg := config.RepositoryConfig{ - Src: fmt.Sprintf("file://%v", testSetup.baseRepository.fileSystem.Root()), + Src: fmt.Sprintf("file://%v", pathsToTest.baseTestRepository), Dest: "awesome-go", } @@ -33,10 +32,11 @@ func TestSyncCommand(t *testing.T) { t.Errorf("Unexpected error: %v", cloneStatus.Message) } - info, err := os.Stat(fmt.Sprintf("%v/awesome-go/.git", testSetup.rootFS.Root())) + info, err := os.Stat(fmt.Sprintf("%v/awesome-go/.git", pathsToTest.baseTestDirectory)) if err != nil { t.Errorf("Unexpected error: %v", err.Error()) } + if !info.IsDir() { t.Errorf("Expected that the selected path is dir") } diff --git a/config/cmd.go b/internal/config/cmd.go similarity index 95% rename from config/cmd.go rename to internal/config/cmd.go index 1373bda..797cd8d 100644 --- a/config/cmd.go +++ b/internal/config/cmd.go @@ -61,10 +61,6 @@ func ParseCliArguments(name, description string, arguments []string) (CliArgumen return CliArguments{}, errors.New(parser.Usage("Please follow this help")) } - if !syncCMD.Happened() && !(*version) && !statusCMD.Happened() { - return CliArguments{}, errors.New(errNoCommand) - } - if *limitName != "" && len(*limitTags) != 0 { return CliArguments{}, errors.New(errNameAndTagsTogether) } diff --git a/config/cmd_test.go b/internal/config/cmd_test.go similarity index 91% rename from config/cmd_test.go rename to internal/config/cmd_test.go index 1d90adf..6e0c446 100644 --- a/config/cmd_test.go +++ b/internal/config/cmd_test.go @@ -3,6 +3,7 @@ package config import ( "fmt" "os" + "strings" "testing" ) @@ -47,8 +48,8 @@ func TestParsingWithoutCommand(t *testing.T) { if err == nil { t.Errorf("Expected error, not results: %v", results) } - if err.Error() != errNoCommand { - t.Errorf("Expected to get \"%v\", instead of this got \"%v\"", errNoCommand, err.Error()) + if !strings.Contains(err.Error(), "Please follow this help") { + t.Errorf("Expected the error contains \"Please follow this help\", but as a result received: \"%v\"", err.Error()) } } diff --git a/config/config_file_parse.go b/internal/config/config_file_parse.go similarity index 91% rename from config/config_file_parse.go rename to internal/config/config_file_parse.go index b875bf5..fd385ed 100644 --- a/config/config_file_parse.go +++ b/internal/config/config_file_parse.go @@ -41,9 +41,9 @@ func GetRepositoryConfig(data []byte, fileExtension string) (Configuration, erro return Configuration{}, errors.New(errorMessage) } if repo.Name == "" { - splittedGit := strings.Split(repo.Src, "/") - nameWithExcention := splittedGit[len(splittedGit)-1] - name := strings.Split(nameWithExcention, ".")[0] + splitGit := strings.Split(repo.Src, "/") + nameWithExtension := splitGit[len(splitGit)-1] + name := strings.Split(nameWithExtension, ".")[0] config.Repositories[index].Name = name } if repo.Dest == "" { diff --git a/config/config_file_parse_test.go b/internal/config/config_file_parse_test.go similarity index 95% rename from config/config_file_parse_test.go rename to internal/config/config_file_parse_test.go index e5fe458..3726ec2 100644 --- a/config/config_file_parse_test.go +++ b/internal/config/config_file_parse_test.go @@ -1,6 +1,7 @@ package config import ( + "errors" "fmt" "os" "reflect" @@ -101,9 +102,9 @@ repositories: `) _, err := GetRepositoryConfig(exampleWrongYamlConfig, "yaml") - expectedError := fmt.Sprintf(errMissingSrcField, 0) + expectedError := errors.New(fmt.Sprintf(errMissingSrcField, 0)) - if err.Error() != expectedError { + if errors.Is(err, expectedError) { t.Errorf("Expected to get error with value %v, instead of this got: %v", expectedError, err.Error()) } } @@ -127,7 +128,7 @@ repositories: } expectedError := getDuplicateFieldError("name", "example2", []int{1, 2}) - if err.Error() != expectedError.Error() { + if errors.Is(err, expectedError) { t.Errorf("Expected to get error with value %v, instead of this got: %v", expectedError.Error(), err.Error()) } } @@ -151,7 +152,7 @@ repositories: expectedError := getDuplicateFieldError("dest", "example", []int{1, 2}) - if err.Error() != expectedError.Error() { + if errors.Is(err, expectedError) { t.Errorf("Expected to get error with value \"%v\", instead of this got: \"%v\"", expectedError, err) } } diff --git a/config/errors.go b/internal/config/errors.go similarity index 87% rename from config/errors.go rename to internal/config/errors.go index 4a9dcac..112cbda 100644 --- a/config/errors.go +++ b/internal/config/errors.go @@ -7,7 +7,6 @@ import ( ) const ( - errNoCommand = "at least one command must be specified, use help to get commands" errNotSupportedType = "not supported configuration type" errMissingWorkspaceField = "missing required \"workspace\" field" errMissingSrcField = "missing required field the \"src\" in row %v" diff --git a/config/structures.go b/internal/config/structures.go similarity index 100% rename from config/structures.go rename to internal/config/structures.go diff --git a/echo/echo.go b/internal/echo/echo.go similarity index 100% rename from echo/echo.go rename to internal/echo/echo.go diff --git a/echo/echo_test.go b/internal/echo/echo_test.go similarity index 100% rename from echo/echo_test.go rename to internal/echo/echo_test.go diff --git a/app/app.go b/internal/grm/app.go similarity index 82% rename from app/app.go rename to internal/grm/app.go index 0cffc00..5369e09 100644 --- a/app/app.go +++ b/internal/grm/app.go @@ -1,20 +1,19 @@ -package app +package grm import ( "errors" "fmt" + "gitlab.com/revalus/grm/internal/commands" + "gitlab.com/revalus/grm/internal/config" + "gitlab.com/revalus/grm/internal/echo" "io" "sync" - - "gitlab.com/revalus/grm/commands" - "gitlab.com/revalus/grm/config" - "gitlab.com/revalus/grm/echo" ) const ( - APP_NAME = "Git repository manager" - APP_DESCRIPTION = "Manage your repository with simple app" - VERSION = "0.3.0" + AppName = "Git repository manager" + AppDescription = "Manage your repository with simple grm" + VERSION = "0.3.2" errNotFoundTags = "no repository was found with the specified tags" errNotFoundName = "no repository was found with the specified name" ) @@ -25,7 +24,7 @@ type GitRepositoryManager struct { } func (g *GitRepositoryManager) Parse(args []string) error { - arguments, err := config.ParseCliArguments(APP_NAME, APP_DESCRIPTION, args) + arguments, err := config.ParseCliArguments(AppName, AppDescription, args) if err != nil { fmt.Printf("Error: %v", err.Error()) return err @@ -37,13 +36,13 @@ func (g *GitRepositoryManager) Parse(args []string) error { return err } - fileExcension, err := getFileExcension(arguments.ConfigurationFile) + fileExtension, err := getFileExtension(arguments.ConfigurationFile) if err != nil { fmt.Printf("Error: %v", err.Error()) return err } - configuration, err := config.GetRepositoryConfig(configFileContent, fileExcension) + configuration, err := config.GetRepositoryConfig(configFileContent, fileExtension) if err != nil { fmt.Printf("Error: %v", err.Error()) return err @@ -62,18 +61,18 @@ func (g *GitRepositoryManager) Run(w io.Writer) int { exitCode := 0 if len(g.cliArguments.LimitToTags) != 0 { - err := g.limitTags() + err := g.limitRepositoriesToTags() if err != nil { echo.ErrorfMsg(err.Error()) - exitCode = 1 + return 1 } } if g.cliArguments.LimitToName != "" { - err := g.limitName() + err := g.limitRepositoryToName() if err != nil { echo.ErrorfMsg(err.Error()) - exitCode = 1 + return 1 } } @@ -109,7 +108,7 @@ func describeStatus(status commands.CommandStatus) { } } -func (g *GitRepositoryManager) limitTags() error { +func (g *GitRepositoryManager) limitRepositoriesToTags() error { limitedTagsTmp := []config.RepositoryConfig{} for _, item := range g.configuration.Repositories { @@ -124,7 +123,7 @@ func (g *GitRepositoryManager) limitTags() error { return nil } -func (g *GitRepositoryManager) limitName() error { +func (g *GitRepositoryManager) limitRepositoryToName() error { for _, item := range g.configuration.Repositories { if g.cliArguments.LimitToName == item.Name { g.configuration.Repositories = []config.RepositoryConfig{item} diff --git a/app/app_test.go b/internal/grm/app_test.go similarity index 97% rename from app/app_test.go rename to internal/grm/app_test.go index 18e2952..b7f6c26 100644 --- a/app/app_test.go +++ b/internal/grm/app_test.go @@ -1,14 +1,13 @@ -package app +package grm import ( "fmt" + "gitlab.com/revalus/grm/internal/commands" + "gitlab.com/revalus/grm/internal/config" + "gitlab.com/revalus/grm/internal/echo" "os" "reflect" "testing" - - "gitlab.com/revalus/grm/commands" - "gitlab.com/revalus/grm/config" - "gitlab.com/revalus/grm/echo" ) type FakeCommandToTest struct { @@ -92,7 +91,7 @@ func TestParseApplication(t *testing.T) { os.Remove(workdir) }) - args := []string{"custom-app", "sync", "-c", configFile} + args := []string{"custom-grm", "sync", "-c", configFile} grm := GitRepositoryManager{} grm.Parse(args) @@ -164,7 +163,7 @@ func TestLimitTags(t *testing.T) { } echo.Color(false) echo.Output(emt) - grm.limitTags() + grm.limitRepositoriesToTags() grm.runCommand(fakeCommand) } @@ -193,7 +192,7 @@ func TestLimitName(t *testing.T) { } echo.Color(false) echo.Output(emt) - grm.limitName() + grm.limitRepositoryToName() grm.runCommand(fakeCommand) } func TestRunWithNotExistingNameInLimit(t *testing.T) { diff --git a/app/utils.go b/internal/grm/utils.go similarity index 70% rename from app/utils.go rename to internal/grm/utils.go index bdbdfdc..2bc8a47 100644 --- a/app/utils.go +++ b/internal/grm/utils.go @@ -1,29 +1,28 @@ -package app +package grm import ( "errors" "fmt" - "io/ioutil" + "gitlab.com/revalus/grm/internal/config" + "os" "strings" - - "gitlab.com/revalus/grm/config" ) func getFileContent(pathToFile string) ([]byte, error) { - return ioutil.ReadFile(pathToFile) + return os.ReadFile(pathToFile) } -func getFileExcension(pathToFile string) (string, error) { - splittedFileName := strings.Split(pathToFile, ".") +func getFileExtension(pathToFile string) (string, error) { + splitFileName := strings.Split(pathToFile, ".") - if len(splittedFileName) == 1 { - msg := fmt.Sprintf("excension for file \"%v\", not found", splittedFileName) + if len(splitFileName) == 1 { + msg := fmt.Sprintf("excension for file \"%v\", not found", splitFileName) return "", errors.New(msg) } - fileExcension := splittedFileName[len(splittedFileName)-1] + fileExtension := splitFileName[len(splitFileName)-1] - return fileExcension, nil + return fileExtension, nil } func checkIsItemInSlice(check string, sliceToCheck []string) bool { diff --git a/app/utils_test.go b/internal/grm/utils_test.go similarity index 89% rename from app/utils_test.go rename to internal/grm/utils_test.go index ed4df90..27de73f 100644 --- a/app/utils_test.go +++ b/internal/grm/utils_test.go @@ -1,10 +1,9 @@ -package app +package grm import ( + "gitlab.com/revalus/grm/internal/config" "reflect" "testing" - - "gitlab.com/revalus/grm/config" ) func TestGetFileExtension(t *testing.T) { @@ -16,7 +15,7 @@ func TestGetFileExtension(t *testing.T) { } for key, value := range toTest { - result, err := getFileExcension(key) + result, err := getFileExtension(key) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -30,9 +29,9 @@ func TestGetFileExtension(t *testing.T) { } -func TestErrorInGetExcensionFile(t *testing.T) { +func TestErrorInGetExtensionFile(t *testing.T) { - result, err := getFileExcension("test") + result, err := getFileExtension("test") if err == nil { t.Errorf("Expected to get error, instead of this got result %v", result)