2013-07-11 22:23:59 +04:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
2014-09-21 10:44:20 +04:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2013-07-19 02:08:32 +04:00
|
|
|
"regexp"
|
2014-07-26 01:52:24 +04:00
|
|
|
|
|
|
|
"github.com/github/hub/github"
|
2014-09-21 10:44:20 +04:00
|
|
|
"github.com/github/hub/utils"
|
2013-07-11 22:23:59 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
var cmdApply = &Command{
|
|
|
|
Run: apply,
|
|
|
|
GitExtension: true,
|
|
|
|
Usage: "apply GITHUB-URL",
|
|
|
|
Short: "Apply a patch to files and/or to the index",
|
|
|
|
Long: `Downloads the patch file for the pull request or commit at the URL and
|
|
|
|
applies that patch from disk with git am or git apply. Similar to
|
|
|
|
cherry-pick, but doesn't add new remotes. git am creates commits while
|
|
|
|
preserving authorship info while <code>apply</code> only applies the
|
|
|
|
patch to the working copy.
|
|
|
|
`,
|
|
|
|
}
|
|
|
|
|
2014-07-26 01:55:12 +04:00
|
|
|
var cmdAm = &Command{
|
|
|
|
Run: apply,
|
|
|
|
GitExtension: true,
|
|
|
|
Usage: "am GITHUB-URL",
|
|
|
|
Short: "Apply a patch to files and/or to the index",
|
|
|
|
Long: `Downloads the patch file for the pull request or commit at the URL and
|
|
|
|
applies that patch from disk with git am or git apply. Similar to
|
|
|
|
cherry-pick, but doesn't add new remotes. git am creates commits while
|
|
|
|
preserving authorship info while <code>apply</code> only applies the
|
|
|
|
patch to the working copy.
|
|
|
|
`,
|
|
|
|
}
|
|
|
|
|
2013-12-30 02:18:14 +04:00
|
|
|
func init() {
|
|
|
|
CmdRunner.Use(cmdApply)
|
2014-07-26 01:55:12 +04:00
|
|
|
CmdRunner.Use(cmdAm)
|
2013-12-30 02:18:14 +04:00
|
|
|
}
|
|
|
|
|
2013-07-19 02:08:32 +04:00
|
|
|
/*
|
2016-01-19 21:31:47 +03:00
|
|
|
$ hub apply https://github.com/jingweno/gh/pull/55
|
2013-07-19 02:08:32 +04:00
|
|
|
> curl https://github.com/jingweno/gh/pull/55.patch -o /tmp/55.patch
|
|
|
|
> git apply /tmp/55.patch
|
|
|
|
|
|
|
|
$ git apply --ignore-whitespace https://github.com/jingweno/gh/commit/fdb9921
|
|
|
|
> curl https://github.com/jingweno/gh/commit/fdb9921.patch -o /tmp/fdb9921.patch
|
|
|
|
> git apply --ignore-whitespace /tmp/fdb9921.patch
|
|
|
|
|
|
|
|
$ git apply https://gist.github.com/8da7fb575debd88c54cf
|
|
|
|
> curl https://gist.github.com/8da7fb575debd88c54cf.txt -o /tmp/gist-8da7fb575debd88c54cf.txt
|
|
|
|
> git apply /tmp/gist-8da7fb575debd88c54cf.txt
|
|
|
|
*/
|
2013-07-11 22:23:59 +04:00
|
|
|
func apply(command *Command, args *Args) {
|
2013-07-19 02:08:32 +04:00
|
|
|
if !args.IsParamsEmpty() {
|
|
|
|
transformApplyArgs(args)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func transformApplyArgs(args *Args) {
|
2014-09-21 10:44:20 +04:00
|
|
|
gistRegexp := regexp.MustCompile("^https?://gist\\.github\\.com/([\\w.-]+/)?([a-f0-9]+)")
|
2014-07-28 10:21:33 +04:00
|
|
|
pullRegexp := regexp.MustCompile("^(pull|commit)/([0-9a-f]+)")
|
2014-07-26 01:52:24 +04:00
|
|
|
for _, arg := range args.Params {
|
|
|
|
var (
|
2014-09-21 10:44:20 +04:00
|
|
|
patch io.ReadCloser
|
|
|
|
apiError error
|
2014-07-26 01:52:24 +04:00
|
|
|
)
|
|
|
|
projectURL, err := github.ParseURL(arg)
|
|
|
|
if err == nil {
|
2014-09-21 10:44:20 +04:00
|
|
|
gh := github.NewClient(projectURL.Project.Host)
|
2014-07-28 10:21:33 +04:00
|
|
|
match := pullRegexp.FindStringSubmatch(projectURL.ProjectPath())
|
2014-07-26 01:52:24 +04:00
|
|
|
if match != nil {
|
2014-09-21 10:44:20 +04:00
|
|
|
if match[1] == "pull" {
|
|
|
|
patch, apiError = gh.PullRequestPatch(projectURL.Project, match[2])
|
|
|
|
} else {
|
|
|
|
patch, apiError = gh.CommitPatch(projectURL.Project, match[2])
|
|
|
|
}
|
2013-07-19 02:08:32 +04:00
|
|
|
}
|
2014-07-26 01:52:24 +04:00
|
|
|
} else {
|
2014-09-21 10:44:20 +04:00
|
|
|
match := gistRegexp.FindStringSubmatch(arg)
|
|
|
|
if match != nil {
|
|
|
|
// TODO: support Enterprise gist
|
|
|
|
gh := github.NewClient(github.GitHubHost)
|
|
|
|
patch, apiError = gh.GistPatch(match[2])
|
2013-07-19 02:08:32 +04:00
|
|
|
}
|
2014-07-26 01:52:24 +04:00
|
|
|
}
|
2013-07-19 02:08:32 +04:00
|
|
|
|
2014-09-21 10:44:20 +04:00
|
|
|
utils.Check(apiError)
|
|
|
|
if patch == nil {
|
2014-07-26 01:52:24 +04:00
|
|
|
continue
|
|
|
|
}
|
2013-07-19 02:08:32 +04:00
|
|
|
|
2014-07-26 01:52:24 +04:00
|
|
|
idx := args.IndexOfParam(arg)
|
2014-09-21 20:37:55 +04:00
|
|
|
patchFile, err := ioutil.TempFile("", "hub")
|
2014-09-21 10:44:20 +04:00
|
|
|
utils.Check(err)
|
2013-07-19 02:08:32 +04:00
|
|
|
|
2014-09-21 20:38:30 +04:00
|
|
|
_, err = io.Copy(patchFile, patch)
|
2014-09-21 10:44:20 +04:00
|
|
|
utils.Check(err)
|
2014-07-26 01:52:24 +04:00
|
|
|
|
2014-09-21 10:44:20 +04:00
|
|
|
patchFile.Close()
|
|
|
|
patch.Close()
|
2014-07-26 01:52:24 +04:00
|
|
|
|
2014-09-21 10:44:20 +04:00
|
|
|
args.Params[idx] = patchFile.Name()
|
2013-07-19 02:08:32 +04:00
|
|
|
}
|
2013-07-11 22:23:59 +04:00
|
|
|
}
|