diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index e7f8945..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,198 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:63e35f61c1d659416dc2d27d873689a9aef81701fd077fa4686e3d6edccac3dc" - name = "github.com/DATA-DOG/godog" - packages = [ - ".", - "colors", - "gherkin", - ] - pruneopts = "UT" - revision = "0371765570d36374bef4ab9f62ed0491f0862a3c" - version = "v0.7.6" - -[[projects]] - branch = "master" - digest = "1:98a49d9edf7d250fe280c04f903b4379710f340eda4e48fa6a5a13ab71531b8c" - name = "github.com/antzucaro/matchr" - packages = ["."] - pruneopts = "UT" - revision = "cbc221335f3c9d9eff15d1d9d5983ddf70b906b6" - -[[projects]] - digest = "1:c77e3e35960e9aeda8f3a3ad17c778b9e898cdd5d6eb907e8d7f870baed91105" - name = "github.com/cucumber/cucumber-messages-go" - packages = ["v2"] - pruneopts = "UT" - revision = "0512577f4d68b9c760b05d05f87f22e60c0d53d8" - version = "v2.1.1" - -[[projects]] - digest = "1:e34af935a388775bf3e123102b663740adcefa4935f55881c915c1789292cb22" - name = "github.com/cucumber/gherkin-go" - packages = ["."] - pruneopts = "UT" - revision = "f732235a1dbe09fd6fd5164a59f46f9d8496dbf9" - version = "v6.0.15" - -[[projects]] - digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "UT" - revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" - version = "v1.1.1" - -[[projects]] - branch = "master" - digest = "1:169ce16366c2a4410c50d4efa8efd98fcad96dc0b99025ad8e8022a5aa601119" - name = "github.com/endiangroup/gitest" - packages = ["."] - pruneopts = "UT" - revision = "8bd9873832d276d9f3f6a21532d491037c2ae93b" - -[[projects]] - branch = "master" - digest = "1:b137835cfe0c763e82d581e1d78cb252fede373f77411a6c0200615bc138e3f6" - name = "github.com/endiangroup/pretty-formatter-go" - packages = ["."] - pruneopts = "UT" - revision = "734ba61331dd202f225480f0778d44724cf1e0c3" - -[[projects]] - branch = "master" - digest = "1:9f5edbc39ddd0d1ca8c1f007dd9d7e908924c3d75f6a68b80573a4a9bfcf2cdf" - name = "github.com/endiangroup/snaptest" - packages = ["."] - pruneopts = "UT" - revision = "2524ada5b7284ba268711456cd205482f92011c8" - -[[projects]] - digest = "1:cda5c079f622734322f6e198c53078e768e797104908060a11e1f8837f677e97" - name = "github.com/gogo/protobuf" - packages = [ - "io", - "jsonpb", - "proto", - "sortkeys", - "types", - ] - pruneopts = "UT" - revision = "636bf0302bc95575d69441b25a2603156ffdddf1" - version = "v1.1.1" - -[[projects]] - branch = "master" - digest = "1:e420c2c5eaffc7645bd49f058129bd465ffb3d37a2188bc6d5eb90f9906c57c4" - name = "github.com/heroku/pat" - packages = ["."] - pruneopts = "UT" - revision = "95f5f62e96949c9c3f8cf9337b1282039654c665" - -[[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" - name = "github.com/inconshreveable/mousetrap" - packages = ["."] - pruneopts = "UT" - revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" - version = "v1.0" - -[[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "UT" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:3265b6b251e076aa31b46c3b58cf55670818be301024d29bc5de35f1ca9790c7" - name = "github.com/sanity-io/litter" - packages = ["."] - pruneopts = "UT" - revision = "ae543b7ba8fd6af63e4976198f146e1348ae53c1" - version = "v1.1.0" - -[[projects]] - digest = "1:6a4a11ba764a56d2758899ec6f3848d24698d48442ebce85ee7a3f63284526cd" - name = "github.com/spf13/afero" - packages = [ - ".", - "mem", - ] - pruneopts = "UT" - revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd" - version = "v1.1.2" - -[[projects]] - digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939" - name = "github.com/spf13/cobra" - packages = ["."] - pruneopts = "UT" - revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" - version = "v0.0.3" - -[[projects]] - digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" - name = "github.com/spf13/pflag" - packages = ["."] - pruneopts = "UT" - revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" - version = "v1.0.2" - -[[projects]] - digest = "1:ac83cf90d08b63ad5f7e020ef480d319ae890c208f8524622a2f3136e2686b02" - name = "github.com/stretchr/objx" - packages = ["."] - pruneopts = "UT" - revision = "477a77ecc69700c7cdeb1fa9e129548e1c1c393c" - version = "v0.1.1" - -[[projects]] - digest = "1:cf4fdb98e23a565bd82473027d37512a3d5b186fba3a1895d7e8401d8ce3ffe1" - name = "github.com/stretchr/testify" - packages = [ - "assert", - "mock", - "require", - ] - pruneopts = "UT" - revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" - version = "v1.2.2" - -[[projects]] - digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295" - name = "golang.org/x/text" - packages = [ - "internal/gen", - "internal/triegen", - "internal/ucd", - "transform", - "unicode/cldr", - "unicode/norm", - ] - pruneopts = "UT" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/DATA-DOG/godog", - "github.com/DATA-DOG/godog/gherkin", - "github.com/antzucaro/matchr", - "github.com/cucumber/gherkin-go", - "github.com/endiangroup/gitest", - "github.com/endiangroup/pretty-formatter-go", - "github.com/endiangroup/snaptest", - "github.com/spf13/afero", - "github.com/spf13/cobra", - "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/mock", - "github.com/stretchr/testify/require", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 0f48518..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,42 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[[constraint]] - name = "github.com/DATA-DOG/godog" - version = "0.7.6" - -[prune] - go-tests = true - unused-packages = true - -[[constraint]] - name = "github.com/spf13/afero" - version = "1.1.2" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.2.2" diff --git a/application.go b/application.go index 6719325..9181cbe 100644 --- a/application.go +++ b/application.go @@ -42,6 +42,9 @@ type RepoHooker interface { RepoPrePushHook() error RepoPostMergeHook() error RepoPostCommitHook() error + RepoRemovePrePushHook() error + RepoRemovePostMergeHook() error + RepoRemovePostCommitHook() error } type Application struct { diff --git a/cmd/cobra_commands.go b/cmd/cobra_commands.go index f90ad46..fff0802 100644 --- a/cmd/cobra_commands.go +++ b/cmd/cobra_commands.go @@ -68,12 +68,20 @@ func commandGitHooks(harness *CobraHarness) *cobra.Command { Args: cobra.ExactArgs(1), Example: "$ spec git-hook exec pre-push", } + remove := &cobra.Command{ + Use: "remove ", + Aliases: []string{"rm"}, + Args: cobra.ExactArgs(1), + Example: "$ spec git-hook remove all", + } root.AddCommand( exec, + remove, ) exec.RunE = harness.GitHookExec + remove.RunE = harness.GitHookRemove return root } diff --git a/cmd/cobra_harness.go b/cmd/cobra_harness.go index 048d32c..cc5c9d3 100644 --- a/cmd/cobra_harness.go +++ b/cmd/cobra_harness.go @@ -228,6 +228,29 @@ func (c *CobraHarness) GitHookExec(cmd *cobra.Command, args []string) error { return c.errorWithReturnCode(cmd, 1, fmt.Errorf("invalid hook name : %s", args[0])) } +func (c *CobraHarness) GitHookRemove(cmd *cobra.Command, args []string) error { + switch args[0] { + case "pre-push": + return c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePrePushHook()) + case "post-merge": + return c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePostMergeHook()) + case "post-commit": + return c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePostCommitHook()) + case "all": + if err := c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePrePushHook()); err != nil { + return err + } + + if err := c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePostMergeHook()); err != nil { + return err + } + + return c.errorOrNil(cmd, 1, c.app.RepoHooker.RepoRemovePostCommitHook()) + } + + return c.errorWithReturnCode(cmd, 1, fmt.Errorf("invalid hook name : %s", args[0])) +} + func (c *CobraHarness) Pull(cmd *cobra.Command, args []string) error { return c.errorOrNil(cmd, 1, c.app.PushPuller.Pull()) } diff --git a/cmd/feature_test.go b/cmd/feature_test.go index 1d1ff4d..e418b37 100644 --- a/cmd/feature_test.go +++ b/cmd/feature_test.go @@ -353,7 +353,7 @@ func (t *testHarness) iHaveNotSetAGitRemote() error { func (t *testHarness) overwriteHooks() error { goPath := os.Getenv("GOPATH") - cmd := "go run " + filepath.Join( + cmd := "GO111MODULE=off go run " + filepath.Join( goPath, "src/github.com/endiangroup/specstack/cmd/spec/*.go", ) @@ -457,7 +457,7 @@ func (t *testHarness) iHaveAProperlyConfiguredProjectDirectory() error { return err } - _, f, _, _ := runtime.Caller(1) + _, f, _, _ := runtime.Caller(0) var err error t.gitServer, err = gitest.NewServer(filepath.Join(path.Dir(f), "fixtures/git/starting")) if err != nil { @@ -513,7 +513,7 @@ func (t *testHarness) iShouldSeeAnAppropriateWarningFromGit() error { } func (t *testHarness) thereAreNewMetadataOnTheRemoteGitServer() error { - _, f, _, _ := runtime.Caller(1) + _, f, _, _ := runtime.Caller(0) p := filepath.Join(path.Dir(f), "fixtures/git/with-commits") return t.gitServer.SetTemplate(p) } @@ -647,7 +647,7 @@ func (t *testHarness) iRunAnySpecMetadataCommand() error { func (t *testHarness) thereAreMinorChangesToScenarioOnTheRemoteGitServer(scenario string) error { var err error - _, f, _, _ := runtime.Caller(1) + _, f, _, _ := runtime.Caller(0) t.gitServer, err = gitest.NewServer(filepath.Join(path.Dir(f), "fixtures/git/minor-changes")) if err != nil { return err diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..42a5928 --- /dev/null +++ b/go.mod @@ -0,0 +1,25 @@ +module github.com/endiangroup/specstack + +go 1.13 + +require ( + github.com/DATA-DOG/godog v0.7.13 + github.com/antzucaro/matchr v0.0.0-20180616170659-cbc221335f3c + github.com/cucumber/gherkin-go v0.0.0-20181022222825-04ff9f06a694 + github.com/cucumber/gherkin-go/v8 v8.2.1+incompatible + github.com/davecgh/go-spew v1.1.1 + github.com/endiangroup/gitest v0.0.0-20181129112818-8bd9873832d2 + github.com/endiangroup/pretty-formatter-go v0.0.0-20200412175208-99fc86d6539f + github.com/endiangroup/snaptest v0.0.0-20180313142837-2524ada5b728 + github.com/gogo/protobuf v1.3.1 + github.com/heroku/pat v0.0.0-20141001185247-95f5f62e9694 + github.com/inconshreveable/mousetrap v1.0.0 + github.com/pmezard/go-difflib v1.0.0 + github.com/sanity-io/litter v1.1.0 + github.com/spf13/afero v1.1.2 + github.com/spf13/cobra v0.0.3 + github.com/spf13/pflag v1.0.2 + github.com/stretchr/objx v0.1.1 + github.com/stretchr/testify v1.4.0 + golang.org/x/text v0.3.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..75f1743 --- /dev/null +++ b/go.sum @@ -0,0 +1,68 @@ +github.com/DATA-DOG/godog v0.7.13 h1:JmgpKcra7Vf3yzI9vPsWyoQRx13tyKziHtXWDCUUgok= +github.com/DATA-DOG/godog v0.7.13/go.mod h1:z2OZ6a3X0/YAKVqLfVzYBwFt3j6uSt3Xrqa7XTtcQE0= +github.com/antzucaro/matchr v0.0.0-20180616170659-cbc221335f3c h1:CucViv7orgFBMkehuFFdkCVF5ERovbkRRyhvaYaHu/k= +github.com/antzucaro/matchr v0.0.0-20180616170659-cbc221335f3c/go.mod h1:bV/CkX4+ANGDaBwbHkt9kK287al/i9BsB18PRBvyqYo= +github.com/aslakhellesoy/gox v0.4.0/go.mod h1:eWI5kaukwHdXWzQ7Hhfbb/F2NSO+VCPHIcsovzQd2sY= +github.com/aslakhellesoy/gox v1.0.100/go.mod h1:AJl542QsKKG96COVsv0N74HHzVQgDIQPceVUh1aeU2M= +github.com/cucumber/cucumber-messages-go/v2 v2.0.0 h1:hc6z72JFAOBCvvyarcPkY8mJltpgmlUN4eBTdmOjnqQ= +github.com/cucumber/cucumber-messages-go/v2 v2.0.0/go.mod h1:gcqqQ2QDOn2kUqcrzQ0Py6Tpks0SJTKbBzU2KetX/C8= +github.com/cucumber/cucumber-messages-go/v7 v7.0.0/go.mod h1:6KOqKG8J9I5GWH/hr2ZumTE9FgoMPcJk81GXi3BiDFc= +github.com/cucumber/gherkin-go v0.0.0-20181022222825-04ff9f06a694 h1:EW367w/pmOkc5d9Q/pDY0W/QOGK9laIosSbRkgcM/uo= +github.com/cucumber/gherkin-go v0.0.0-20181022222825-04ff9f06a694/go.mod h1:vZnAEQplhpjcFx1yzDcqmtgkvygC0aclXfO+B9rBJAE= +github.com/cucumber/gherkin-go v5.1.0+incompatible h1:RCvyVI6KQLI2IJkijZBeJcE4K3U7DnhQ1RjD7VV+AIk= +github.com/cucumber/gherkin-go v5.1.0+incompatible/go.mod h1:bYJ65F+CDEAL70FXAu7/ef4ayC/NhRXO8zEW3IB21w0= +github.com/cucumber/gherkin-go/v8 v8.2.1+incompatible/go.mod h1:4JlPa/T6F3/778CBsSLpkhOfxSkJ0pve7UufgLrFzmY= +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/endiangroup/gitest v0.0.0-20181129112818-8bd9873832d2 h1:4uvhYFxOOwowfkRbH+GbkNO5Oi4dZ6gH13g+dagSY74= +github.com/endiangroup/gitest v0.0.0-20181129112818-8bd9873832d2/go.mod h1:duMyF1KOIy66NKiDhA3+m4t4MZB//0fBZVsI+r6cJFQ= +github.com/endiangroup/pretty-formatter-go v0.0.0-20200412175208-99fc86d6539f h1:fV5LOG1DlGc7xsq+w+D5xaORSXRfSAWNYVD24VT8s90= +github.com/endiangroup/pretty-formatter-go v0.0.0-20200412175208-99fc86d6539f/go.mod h1:mUOel2db21VaFISGFwXcdGoyHlwY4UZidcR1m24k2+o= +github.com/endiangroup/snaptest v0.0.0-20180313142837-2524ada5b728 h1:iuxC0U7oE56/TrhPI03MkQVMVZqehmYTPLMcDOw1fhg= +github.com/endiangroup/snaptest v0.0.0-20180313142837-2524ada5b728/go.mod h1:AroReQgLqRx4FpAS2JyrR3qiDHE7UHcRWkm9VE2ixTI= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/heroku/pat v0.0.0-20141001185247-95f5f62e9694 h1:o+Sn+q49hJ4xd4vaq20O+zNMoDS4RzXjNbPVzTgHV/s= +github.com/heroku/pat v0.0.0-20141001185247-95f5f62e9694/go.mod h1:WcNZz/1+5swQ0+U95XdjAVBF4ANKhGBfKRVOqbVYxGM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +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/sanity-io/litter v1.1.0 h1:BllcKWa3VbZmOZbDCoszYLk7zCsKHz5Beossi8SUcTc= +github.com/sanity-io/litter v1.1.0/go.mod h1:CJ0VCw2q4qKU7LaQr3n7UOSHzgEMgcGco7N/SkZQPjw= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/personas/developer.go b/personas/developer.go index af151d0..9083daf 100644 --- a/personas/developer.go +++ b/personas/developer.go @@ -277,3 +277,13 @@ func (d *Developer) RepoPostMergeHook() error { func (d *Developer) RepoPostCommitHook() error { return d.TransferScenarioMetadata() } + +func (d *Developer) RepoRemovePrePushHook() error { + return d.repo.RemoveHook("pre-push") +} +func (d *Developer) RepoRemovePostMergeHook() error { + return d.repo.RemoveHook("post-merge") +} +func (d *Developer) RepoRemovePostCommitHook() error { + return d.repo.RemoveHook("post-commit") +} diff --git a/repository/repository.go b/repository/repository.go index 9f4deda..a234843 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -8,6 +8,7 @@ type Repository interface { Configurer MetadataSyncer ObjectHasher + HookRemover } // Initialiser initialises a repo @@ -34,3 +35,7 @@ type ObjectHasher interface { ObjectHash(io.Reader) (string, error) ObjectString(hash string) (string, error) } + +type HookRemover interface { + RemoveHook(string) error +} diff --git a/repository/repository_git.go b/repository/repository_git.go index 7d373d4..72a1db8 100644 --- a/repository/repository_git.go +++ b/repository/repository_git.go @@ -10,13 +10,16 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "syscall" "time" ) const ( - gitNotesRef = "refs/notes/specstack" + gitNotesRef = "refs/notes/specstack" + gitHookOpeningTag = "### spec {" + gitHookClosingTag = "### }" // Scopes for git config GitConfigScopeLocal = 1 @@ -24,7 +27,10 @@ const ( GitConfigScopeGlobal = 4 ) -var ErrNoConfigFound = errors.New("no config found") +var ( + ErrNoConfigFound = errors.New("no config found") + findHookEntryRegex = regexp.MustCompile("(?s)" + gitHookOpeningTag + ".+" + gitHookClosingTag) +) // NewGitCmdConfigErr creates the appropriate typed error for a Git failure, if // possible. @@ -306,13 +312,41 @@ func (repo *Git) WriteHookFile(name, command string) error { content := fmt.Sprintf( `#!/bin/sh + +%s # Added by spec command on %s %s -`, time.Now().Format(time.RFC3339), command) +%s +`, + gitHookOpeningTag, + time.Now().Format(time.RFC3339), + command, + gitHookClosingTag, + ) return ioutil.WriteFile(path, []byte(content), 0774) } +func (repo *Git) RemoveHook(name string) error { + hooksDir, err := repo.gitHooksDirectory() + if err != nil { + return err + } + + path := filepath.Join(hooksDir, name) + if _, err := os.Stat(path); os.IsNotExist(err) { + return nil + } + + hookBytes, err := ioutil.ReadFile(path) + if err != nil { + return err + } + + removeMsg := fmt.Sprintf("# Removed by spec command on %s", time.Now().Format(time.RFC3339)) + return ioutil.WriteFile(path, findHookEntryRegex.ReplaceAll(hookBytes, []byte(removeMsg)), 0774) +} + func (repo *Git) PullMetadata(from string) error { exists, err := repo.hasRemote(from) if err != nil { diff --git a/repository/repository_git_test.go b/repository/repository_git_test.go index 5cdab94..79b5125 100644 --- a/repository/repository_git_test.go +++ b/repository/repository_git_test.go @@ -220,12 +220,13 @@ func Test_AnInitialisedGitRepoKnowsItsGitDirectories(t *testing.T) { dir, repo, shutdown := initialisedGitRepoDir(t) defer shutdown() - expectedGitDir := filepath.Join(dir, ".git") + expectedGitDir, err := filepath.EvalSymlinks(filepath.Join(dir, ".git")) + require.NoError(t, err) expectedHooksDir := filepath.Join(expectedGitDir, "hooks") topDir, err := repo.topDirectory() require.Nil(t, err) - require.Equal(t, dir, topDir) + require.Contains(t, topDir, dir) gitDir, err := repo.gitDirectory() require.Nil(t, err) @@ -265,6 +266,24 @@ func Test_AnInitialisedGitRepoCanWriteItsHooksWhenAppropriate(t *testing.T) { }) } +func Test_AnInitialisedGitRepoCanRemoveItsHooks(t *testing.T) { + _, repo, shutdown := initialisedGitRepoDir(t) + defer shutdown() + + hooksDir, err := repo.gitHooksDirectory() + require.Nil(t, err) + + pp := filepath.Join(hooksDir, "pre-push") + + require.Nil(t, repo.PrepareMetadataSync()) + require.Nil(t, repo.RemoveHook("pre-push")) + + prePushBytes, err := ioutil.ReadFile(pp) + require.NoError(t, err) + + require.False(t, findHookEntryRegex.Match(prePushBytes)) +} + func Test_AnInitialisedGitRepoCanHashObjectsConsistently(t *testing.T) { _, repo, shutdown := initialisedGitRepoDir(t) diff --git a/repository/repository_mock.go b/repository/repository_mock.go index b1cb9e3..8329b90 100644 --- a/repository/repository_mock.go +++ b/repository/repository_mock.go @@ -2,8 +2,11 @@ package repository -import io "io" -import mock "github.com/stretchr/testify/mock" +import ( + io "io" + + mock "github.com/stretchr/testify/mock" +) // MockRepository is an autogenerated mock type for the Repository type type MockRepository struct { @@ -152,6 +155,20 @@ func (_m *MockRepository) PushMetadata(to string) error { return r0 } +// RemoveHook provides a mock function with given fields: _a0 +func (_m *MockRepository) RemoveHook(_a0 string) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(string) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SetConfig provides a mock function with given fields: _a0, _a1 func (_m *MockRepository) SetConfig(_a0 string, _a1 string) error { ret := _m.Called(_a0, _a1)