github.com/trevoraustin/hub@v2.2.0-preview1.0.20141105230840-96d8bfc654cc+incompatible/commands/apply.go (about)

     1  package commands
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"regexp"
     7  
     8  	"github.com/github/hub/github"
     9  	"github.com/github/hub/utils"
    10  )
    11  
    12  var cmdApply = &Command{
    13  	Run:          apply,
    14  	GitExtension: true,
    15  	Usage:        "apply GITHUB-URL",
    16  	Short:        "Apply a patch to files and/or to the index",
    17  	Long: `Downloads the patch file for the pull request or commit at the URL and
    18  applies that patch from disk with git am or git apply. Similar to
    19  cherry-pick, but doesn't add new remotes. git am creates commits while
    20  preserving authorship info while <code>apply</code> only applies the
    21  patch to the working copy.
    22  `,
    23  }
    24  
    25  var cmdAm = &Command{
    26  	Run:          apply,
    27  	GitExtension: true,
    28  	Usage:        "am GITHUB-URL",
    29  	Short:        "Apply a patch to files and/or to the index",
    30  	Long: `Downloads the patch file for the pull request or commit at the URL and
    31  applies that patch from disk with git am or git apply. Similar to
    32  cherry-pick, but doesn't add new remotes. git am creates commits while
    33  preserving authorship info while <code>apply</code> only applies the
    34  patch to the working copy.
    35  `,
    36  }
    37  
    38  func init() {
    39  	CmdRunner.Use(cmdApply)
    40  	CmdRunner.Use(cmdAm)
    41  }
    42  
    43  /*
    44    $ gh apply https://github.com/jingweno/gh/pull/55
    45    > curl https://github.com/jingweno/gh/pull/55.patch -o /tmp/55.patch
    46    > git apply /tmp/55.patch
    47  
    48    $ git apply --ignore-whitespace https://github.com/jingweno/gh/commit/fdb9921
    49    > curl https://github.com/jingweno/gh/commit/fdb9921.patch -o /tmp/fdb9921.patch
    50    > git apply --ignore-whitespace /tmp/fdb9921.patch
    51  
    52    $ git apply https://gist.github.com/8da7fb575debd88c54cf
    53    > curl https://gist.github.com/8da7fb575debd88c54cf.txt -o /tmp/gist-8da7fb575debd88c54cf.txt
    54    > git apply /tmp/gist-8da7fb575debd88c54cf.txt
    55  */
    56  func apply(command *Command, args *Args) {
    57  	if !args.IsParamsEmpty() {
    58  		transformApplyArgs(args)
    59  	}
    60  }
    61  
    62  func transformApplyArgs(args *Args) {
    63  	gistRegexp := regexp.MustCompile("^https?://gist\\.github\\.com/([\\w.-]+/)?([a-f0-9]+)")
    64  	pullRegexp := regexp.MustCompile("^(pull|commit)/([0-9a-f]+)")
    65  	for _, arg := range args.Params {
    66  		var (
    67  			patch    io.ReadCloser
    68  			apiError error
    69  		)
    70  		projectURL, err := github.ParseURL(arg)
    71  		if err == nil {
    72  			gh := github.NewClient(projectURL.Project.Host)
    73  			match := pullRegexp.FindStringSubmatch(projectURL.ProjectPath())
    74  			if match != nil {
    75  				if match[1] == "pull" {
    76  					patch, apiError = gh.PullRequestPatch(projectURL.Project, match[2])
    77  				} else {
    78  					patch, apiError = gh.CommitPatch(projectURL.Project, match[2])
    79  				}
    80  			}
    81  		} else {
    82  			match := gistRegexp.FindStringSubmatch(arg)
    83  			if match != nil {
    84  				// TODO: support Enterprise gist
    85  				gh := github.NewClient(github.GitHubHost)
    86  				patch, apiError = gh.GistPatch(match[2])
    87  			}
    88  		}
    89  
    90  		utils.Check(apiError)
    91  		if patch == nil {
    92  			continue
    93  		}
    94  
    95  		idx := args.IndexOfParam(arg)
    96  		patchFile, err := ioutil.TempFile("", "hub")
    97  		utils.Check(err)
    98  
    99  		_, err = io.Copy(patchFile, patch)
   100  		utils.Check(err)
   101  
   102  		patchFile.Close()
   103  		patch.Close()
   104  
   105  		args.Params[idx] = patchFile.Name()
   106  	}
   107  }