diff --git a/commands/apply.go b/commands/apply.go
index 2e60c0319f5ce59f011e4f06ed4d7c1ec89da522..8e3305ace7011720ce5a0ebfa484588e173e9426 100644
--- a/commands/apply.go
+++ b/commands/apply.go
@@ -5,6 +5,8 @@ import (
"os"
"path/filepath"
"regexp"
+
+ "github.com/github/hub/github"
)
var cmdApply = &Command{
@@ -20,8 +22,22 @@ patch to the working copy.
`,
}
+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 apply
only applies the
+patch to the working copy.
+`,
+}
+
func init() {
CmdRunner.Use(cmdApply)
+ CmdRunner.Use(cmdAm)
}
/*
@@ -44,44 +60,50 @@ func apply(command *Command, args *Args) {
}
func transformApplyArgs(args *Args) {
- urlRegexp := regexp.MustCompile("^https?://(gist\\.)?github\\.com/")
- for _, url := range args.Params {
- if urlRegexp.MatchString(url) {
- idx := args.IndexOfParam(url)
- gist := urlRegexp.FindStringSubmatch(url)[1] == "gist."
-
- fragmentRegexp := regexp.MustCompile("#.+")
- url = fragmentRegexp.ReplaceAllString(url, "")
- pullRegexp := regexp.MustCompile("(/pull/\\d+)/\\w*$")
- if !gist {
- if pullRegexp.MatchString(url) {
- pull := pullRegexp.FindStringSubmatch(url)[1]
- url = pullRegexp.ReplaceAllString(url, pull)
- }
+ urlRegexp := regexp.MustCompile("^https?://(gist\\.)github\\.com/")
+ for _, arg := range args.Params {
+ var (
+ url string
+ gist bool
+ )
+ projectURL, err := github.ParseURL(arg)
+ if err == nil {
+ pullRegexp := regexp.MustCompile("/(pull|commit)/([0-9a-f]+)")
+ match := pullRegexp.FindStringSubmatch(projectURL.Path)
+ if match != nil {
+ url = projectURL.Project.WebURL("", "", match[1]+"/"+match[2])
}
-
- var ext string
+ } else {
+ gist = urlRegexp.MatchString(arg)
if gist {
- ext = ".txt"
- } else {
- ext = ".patch"
- }
-
- if filepath.Ext(url) != ext {
- url += ext
+ url = arg
}
+ }
- var prefix string
- if gist {
- prefix = "gist-"
- }
+ if url == "" {
+ continue
+ }
- patchFile := filepath.Join(os.TempDir(), prefix+filepath.Base(url))
+ var ext string
+ if gist {
+ ext = ".txt"
+ } else {
+ ext = ".patch"
+ }
- args.Before("curl", "-#LA", fmt.Sprintf("gh %s", Version), url, "-o", patchFile)
- args.Params[idx] = patchFile
+ idx := args.IndexOfParam(arg)
+ if filepath.Ext(url) != ext {
+ url += ext
+ }
- break
+ var prefix string
+ if gist {
+ prefix = "gist-"
}
+
+ patchFile := filepath.Join(os.TempDir(), prefix+filepath.Base(url))
+
+ args.Before("curl", "-#LA", fmt.Sprintf("gh %s", Version), url, "-o", patchFile)
+ args.Params[idx] = patchFile
}
}
diff --git a/features/support/fakebin/curl b/features/support/fakebin/curl
new file mode 100755
index 0000000000000000000000000000000000000000..b12906f171233a60c590d5559a6818071a2d2dbe
--- /dev/null
+++ b/features/support/fakebin/curl
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e
+
+url="$3"
+file="$5"
+
+if [ "${url%.patch}" = "$url" ]; then
+ echo "invalid pull request URL: $url" >&2
+ exit 1
+fi
+
+cat > "$file" <
+Date: Tue, 24 Jun 2014 11:07:05 -0700
+Subject: [PATCH] Create a README
+---
+diff --git a/README.md b/README.md
+new file mode 100644
+index 0000000..ce01362
+--- /dev/null
++++ b/README.md
++hello
+--
+1.9.3
+OUT