/commands/apply.go

https://github.com/ap0ught/hub · Go · 114 lines · 101 code · 12 blank · 1 comment · 14 complexity · 9dccd3d018e0eeb5bc65a762e6c67d0d MD5 · raw file

  1. package commands
  2. import (
  3. "io"
  4. "io/ioutil"
  5. "os"
  6. "regexp"
  7. "github.com/github/hub/v2/github"
  8. "github.com/github/hub/v2/utils"
  9. )
  10. var cmdApply = &Command{
  11. Run: apply,
  12. GitExtension: true,
  13. Usage: "apply <GITHUB-URL>",
  14. Long: `Download a patch from GitHub and apply it locally.
  15. ## Options:
  16. <GITHUB-URL>
  17. A URL to a pull request or commit on GitHub.
  18. ## Examples:
  19. $ hub apply https://github.com/jingweno/gh/pull/55
  20. > curl https://github.com/jingweno/gh/pull/55.patch -o /tmp/55.patch
  21. > git apply /tmp/55.patch
  22. ## See also:
  23. hub-am(1), hub(1), git-apply(1)
  24. `,
  25. }
  26. var cmdAm = &Command{
  27. Run: apply,
  28. GitExtension: true,
  29. Usage: "am [-3] <GITHUB-URL>",
  30. Long: `Replicate commits from a GitHub pull request locally.
  31. ## Options:
  32. -3
  33. (Recommended) See git-am(1).
  34. <GITHUB-URL>
  35. A URL to a pull request or commit on GitHub.
  36. ## Examples:
  37. $ hub am -3 https://github.com/jingweno/gh/pull/55
  38. > curl https://github.com/jingweno/gh/pull/55.patch -o /tmp/55.patch
  39. > git am -3 /tmp/55.patch
  40. ## See also:
  41. hub-apply(1), hub-cherry-pick(1), hub(1), git-am(1)
  42. `,
  43. }
  44. func init() {
  45. CmdRunner.Use(cmdApply)
  46. CmdRunner.Use(cmdAm)
  47. }
  48. func apply(command *Command, args *Args) {
  49. if !args.IsParamsEmpty() {
  50. transformApplyArgs(args)
  51. }
  52. }
  53. func transformApplyArgs(args *Args) {
  54. gistRegexp := regexp.MustCompile("^https?://gist\\.github\\.com/([\\w.-]+/)?([a-f0-9]+)")
  55. commitRegexp := regexp.MustCompile("^(commit|pull/[0-9]+/commits)/([0-9a-f]+)")
  56. pullRegexp := regexp.MustCompile("^pull/([0-9]+)")
  57. for idx, arg := range args.Params {
  58. var (
  59. patch io.ReadCloser
  60. apiError error
  61. )
  62. projectURL, err := github.ParseURL(arg)
  63. if err == nil {
  64. gh := github.NewClient(projectURL.Project.Host)
  65. if match := commitRegexp.FindStringSubmatch(projectURL.ProjectPath()); match != nil {
  66. patch, apiError = gh.CommitPatch(projectURL.Project, match[2])
  67. } else if match := pullRegexp.FindStringSubmatch(projectURL.ProjectPath()); match != nil {
  68. patch, apiError = gh.PullRequestPatch(projectURL.Project, match[1])
  69. }
  70. } else {
  71. match := gistRegexp.FindStringSubmatch(arg)
  72. if match != nil {
  73. // TODO: support Enterprise gist
  74. gh := github.NewClient(github.GitHubHost)
  75. patch, apiError = gh.GistPatch(match[2])
  76. }
  77. }
  78. utils.Check(apiError)
  79. if patch == nil {
  80. continue
  81. }
  82. tempDir := os.TempDir()
  83. err = os.MkdirAll(tempDir, 0775)
  84. utils.Check(err)
  85. patchFile, err := ioutil.TempFile(tempDir, "hub")
  86. utils.Check(err)
  87. _, err = io.Copy(patchFile, patch)
  88. utils.Check(err)
  89. patchFile.Close()
  90. patch.Close()
  91. args.ReplaceParam(idx, patchFile.Name())
  92. }
  93. }