From f774e31cc1146639ead2aadc8b7720d3e9983ea8 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Wed, 20 May 2020 17:57:58 -0400 Subject: [PATCH] see-pr: to add the github PR pull refspec Signed-off-by: Vincent Batts --- README.md | 27 +++++++++++++ cmd/see-pr/README.md | 27 +++++++++++++ cmd/see-pr/go.mod | 8 ++++ cmd/see-pr/go.sum | 68 ++++++++++++++++++++++++++++++++ cmd/see-pr/main.go | 92 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+) create mode 100644 cmd/see-pr/README.md create mode 100644 cmd/see-pr/go.mod create mode 100644 cmd/see-pr/go.sum create mode 100644 cmd/see-pr/main.go diff --git a/README.md b/README.md index bf4f319..3297fab 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,33 @@ Random utilities of vbatts' being cleaned up, and published # Commands +## see-pr + +Add the github PR refspec to a local git repo. + +### Install + + go get github.com/vbatts/utils/cmd/see-pr + +### Usage + + $ see-pr -h + Usage of see-pr: + -config string + path to the git config (default ".git/config") + -path string + local path of the git repo (default ".") + -remote string + upstream remote name (default "origin") + +Then to let it update your `.git/config`: + + $ see-pr + INFO[0000] reading from ".git/config" + INFO[0000] origin/origin URL: git@github.com:vbatts/utils.git + INFO[0000] appending fetch = +refs/pull/*/head:refs/remotes/pr/* + INFO[0000] SUCCESS! `git fetch` and then you can `git checkout pr/$NUM` of your PRs + ## dups building a document of file checksum info, for a directory tree. Optionally diff --git a/cmd/see-pr/README.md b/cmd/see-pr/README.md new file mode 100644 index 0000000..e8706f9 --- /dev/null +++ b/cmd/see-pr/README.md @@ -0,0 +1,27 @@ +# see-pr + +Add the github PR refspec to a local git repo. + +## Install + + go get github.com/vbatts/utils/cmd/see-pr + +## Usage + + $ see-pr -h + Usage of see-pr: + -config string + path to the git config (default ".git/config") + -path string + local path of the git repo (default ".") + -remote string + upstream remote name (default "origin") + +Then to let it update your `.git/config`: + + $ see-pr + INFO[0000] reading from ".git/config" + INFO[0000] origin/origin URL: git@github.com:vbatts/utils.git + INFO[0000] appending fetch = +refs/pull/*/head:refs/remotes/pr/* + INFO[0000] SUCCESS! `git fetch` and then you can `git checkout pr/$NUM` of your PRs + diff --git a/cmd/see-pr/go.mod b/cmd/see-pr/go.mod new file mode 100644 index 0000000..e5a5a7a --- /dev/null +++ b/cmd/see-pr/go.mod @@ -0,0 +1,8 @@ +module github.com/vbatts/utils/cmd/see-pr + +go 1.13 + +require ( + github.com/go-git/go-git/v5 v5.0.0 + github.com/sirupsen/logrus v1.6.0 +) diff --git a/cmd/see-pr/go.sum b/cmd/see-pr/go.sum new file mode 100644 index 0000000..92eccff --- /dev/null +++ b/cmd/see-pr/go.sum @@ -0,0 +1,68 @@ +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +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/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/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/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.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= +github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg= +github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +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/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.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/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/stretchr/objx v0.1.0/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= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/cmd/see-pr/main.go b/cmd/see-pr/main.go new file mode 100644 index 0000000..8a45c60 --- /dev/null +++ b/cmd/see-pr/main.go @@ -0,0 +1,92 @@ +package main + +import ( + "flag" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/go-git/go-git/v5/config" + "github.com/sirupsen/logrus" +) + +var ( + DefaultConfigPath = ".git/config" + DefaultRepoPath = "." + DefaultUpstreamName = "origin" + + PullRequestRefSpec = "+refs/pull/*/head:refs/remotes/pr/*" +) + +func init() { + flag.StringVar(&DefaultConfigPath, "config", DefaultConfigPath, "path to the git config") + flag.StringVar(&DefaultRepoPath, "path", DefaultRepoPath, "local path of the git repo") + flag.StringVar(&DefaultUpstreamName, "remote", DefaultUpstreamName, "upstream remote name") +} + +func main() { + flag.Parse() + + path := filepath.Join(DefaultRepoPath, DefaultConfigPath) + logrus.Infof("reading from %q", path) + origBuf, err := ioutil.ReadFile(path) + if err != nil { + logrus.Fatal(err) + } + + cfg := config.NewConfig() + err = cfg.Unmarshal(origBuf) + if err != nil { + logrus.Fatal(err) + } + + changesMade := false + foundRemote := false +outer: + for origin, remote := range cfg.Remotes { + if origin != DefaultUpstreamName { + logrus.Infof("skipping %s", origin) + continue + } + foundRemote = true + + foundGithub := false + for _, url := range remote.URLs { + logrus.Infof("%s/%s URL: %s", origin, remote.Name, url) + if strings.Contains(url, "github.com") { + foundGithub = true + } + } + if !foundGithub { + logrus.Warn("no github remote URL found. PR RefSpec doesn't make sense here") + break outer + } + for _, fetch := range remote.Fetch { + if fetch.String() == PullRequestRefSpec { + logrus.Infof("PR Fetch RefSpec is already here!") + break outer + } + logrus.Debugf("%s/%s = %s", origin, remote.Name, fetch) + } + logrus.Infof("appending fetch = %s", PullRequestRefSpec) + remote.Fetch = append(remote.Fetch, config.RefSpec(PullRequestRefSpec)) + changesMade = true + } + if !foundRemote { + logrus.Fatalf("failed to find %q remote", DefaultUpstreamName) + } + + // write back the Marshalled config + if changesMade { + newBuf, err := cfg.Marshal() + if err != nil { + logrus.Fatalf("failed to marshal back: %s", err) + } + //fmt.Println(string(newBuf)) + if err := ioutil.WriteFile(path, newBuf, os.FileMode(0644)); err != nil { + logrus.Fatalf("failed to rewrite %q: %s", path, err) + } + logrus.Infof("SUCCESS! `git fetch` and then you can `git checkout pr/$NUM` of your PRs") + } +}