2013-07-20 01:26:00 +04:00
|
|
|
package commands
|
|
|
|
|
2013-07-20 09:46:47 +04:00
|
|
|
import (
|
2016-09-08 16:26:30 +03:00
|
|
|
"fmt"
|
2014-04-02 00:40:02 +04:00
|
|
|
"regexp"
|
|
|
|
|
2014-02-10 20:22:36 +04:00
|
|
|
"github.com/github/hub/github"
|
|
|
|
"github.com/github/hub/utils"
|
2013-07-20 09:46:47 +04:00
|
|
|
)
|
|
|
|
|
2013-07-20 01:26:00 +04:00
|
|
|
var cmdCherryPick = &Command{
|
|
|
|
Run: cherryPick,
|
|
|
|
GitExtension: true,
|
2016-01-24 11:56:18 +03:00
|
|
|
Usage: `
|
|
|
|
cherry-pick <COMMIT-URL>
|
|
|
|
cherry-pick <USER>@<SHA>
|
|
|
|
`,
|
|
|
|
Long: `Cherry-pick a commit from a fork on GitHub.
|
|
|
|
|
2016-01-24 18:50:01 +03:00
|
|
|
## See also:
|
|
|
|
|
|
|
|
hub-am(1), hub(1), git-cherry-pick(1)
|
2013-07-20 01:26:00 +04:00
|
|
|
`,
|
|
|
|
}
|
|
|
|
|
2013-12-30 02:18:14 +04:00
|
|
|
func init() {
|
|
|
|
CmdRunner.Use(cmdCherryPick)
|
|
|
|
}
|
|
|
|
|
2013-07-20 01:26:00 +04:00
|
|
|
func cherryPick(command *Command, args *Args) {
|
2013-07-20 09:46:47 +04:00
|
|
|
if args.IndexOfParam("-m") == -1 && args.IndexOfParam("--mainline") == -1 {
|
|
|
|
transformCherryPickArgs(args)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func transformCherryPickArgs(args *Args) {
|
2014-10-16 22:55:08 +04:00
|
|
|
if args.IsParamsEmpty() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-28 05:01:30 +03:00
|
|
|
var project *github.Project
|
|
|
|
var sha, refspec string
|
2016-09-08 16:26:30 +03:00
|
|
|
shaRe := "[a-f0-9]{7,40}"
|
|
|
|
|
|
|
|
var mainProject *github.Project
|
|
|
|
localRepo, mainProjectErr := github.LocalRepo()
|
|
|
|
if mainProjectErr == nil {
|
|
|
|
mainProject, mainProjectErr = localRepo.MainProject()
|
|
|
|
}
|
|
|
|
|
2018-12-28 05:01:30 +03:00
|
|
|
ref := args.LastParam()
|
|
|
|
if url, err := github.ParseURL(ref); err == nil {
|
2013-07-20 09:46:47 +04:00
|
|
|
projectPath := url.ProjectPath()
|
2016-09-08 16:26:30 +03:00
|
|
|
commitRegex := regexp.MustCompile(fmt.Sprintf("^commit/(%s)", shaRe))
|
2018-12-28 05:01:30 +03:00
|
|
|
pullRegex := regexp.MustCompile(fmt.Sprintf(`^pull/(\d+)/commits/(%s)`, shaRe))
|
2016-09-08 16:26:30 +03:00
|
|
|
if matches := commitRegex.FindStringSubmatch(projectPath); len(matches) > 0 {
|
|
|
|
sha = matches[1]
|
|
|
|
project = url.Project
|
2018-12-28 05:01:30 +03:00
|
|
|
} else if matches := pullRegex.FindStringSubmatch(projectPath); len(matches) > 0 {
|
2016-09-08 19:23:55 +03:00
|
|
|
pullId := matches[1]
|
|
|
|
sha = matches[2]
|
|
|
|
utils.Check(mainProjectErr)
|
2018-06-14 15:47:27 +03:00
|
|
|
project = mainProject
|
|
|
|
refspec = fmt.Sprintf("refs/pull/%s/head", pullId)
|
2018-12-28 05:01:30 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ownerWithShaRegexp := regexp.MustCompile(fmt.Sprintf("^(%s)@(%s)$", OwnerRe, shaRe))
|
|
|
|
if matches := ownerWithShaRegexp.FindStringSubmatch(ref); len(matches) > 0 {
|
|
|
|
utils.Check(mainProjectErr)
|
|
|
|
project = mainProject
|
|
|
|
project.Owner = matches[1]
|
|
|
|
sha = matches[2]
|
2016-09-08 19:23:55 +03:00
|
|
|
}
|
2013-07-20 09:46:47 +04:00
|
|
|
}
|
|
|
|
|
2018-12-28 05:01:30 +03:00
|
|
|
if project != nil {
|
|
|
|
args.ReplaceParam(args.IndexOfParam(ref), sha)
|
|
|
|
|
|
|
|
tmpName := "_hub-cherry-pick"
|
|
|
|
remoteName := tmpName
|
|
|
|
|
|
|
|
if remote, err := localRepo.RemoteForProject(project); err == nil {
|
|
|
|
remoteName = remote.Name
|
|
|
|
} else {
|
|
|
|
args.Before("git", "remote", "add", remoteName, project.GitURL("", "", false))
|
|
|
|
}
|
2013-07-20 09:46:47 +04:00
|
|
|
|
2018-12-28 05:01:30 +03:00
|
|
|
fetchArgs := []string{"git", "fetch", "-q", "--no-tags", remoteName}
|
|
|
|
if refspec != "" {
|
|
|
|
fetchArgs = append(fetchArgs, refspec)
|
|
|
|
}
|
|
|
|
args.Before(fetchArgs...)
|
|
|
|
|
|
|
|
if remoteName == tmpName {
|
|
|
|
args.Before("git", "remote", "rm", remoteName)
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 09:46:47 +04:00
|
|
|
}
|