[patch] Allow jiri patch to specify a rebase revision.
This change adds '-rebase-revision' flag to 'jiri patch' to allow
the patch to be rebased to a specific revision instead of the default
master branch. This feature is required to conduct Infra code purple.
Bugs: VC-163
Test: Local
Change-Id: Id944e72d4aa0621ac0e6339e46e4c7fbe2976679
diff --git a/cmd/jiri/patch.go b/cmd/jiri/patch.go
index fffef0c..a48b688 100644
--- a/cmd/jiri/patch.go
+++ b/cmd/jiri/patch.go
@@ -20,16 +20,17 @@
)
var (
- patchRebaseFlag bool
- patchTopicFlag bool
- patchBranchFlag string
- patchDeleteFlag bool
- patchHostFlag string
- patchForceFlag bool
- cherryPickFlag bool
- detachedHeadFlag bool
- patchProjectFlag string
- rebaseFailures uint32
+ patchRebaseFlag bool
+ patchRebaseRevision string
+ patchTopicFlag bool
+ patchBranchFlag string
+ patchDeleteFlag bool
+ patchHostFlag string
+ patchForceFlag bool
+ cherryPickFlag bool
+ detachedHeadFlag bool
+ patchProjectFlag string
+ rebaseFailures uint32
)
func init() {
@@ -37,6 +38,7 @@
cmdPatch.Flags.BoolVar(&patchDeleteFlag, "delete", false, "Delete the existing branch if already exists")
cmdPatch.Flags.BoolVar(&patchForceFlag, "force", false, "Use force when deleting the existing branch")
cmdPatch.Flags.BoolVar(&patchRebaseFlag, "rebase", false, "Rebase the change after downloading")
+ cmdPatch.Flags.StringVar(&patchRebaseRevision, "rebase-revision", "", "Rebase the change to a specific revision after downloading")
cmdPatch.Flags.StringVar(&patchHostFlag, "host", "", `Gerrit host to use. Defaults to gerrit host specified in manifest.`)
cmdPatch.Flags.StringVar(&patchProjectFlag, "project", "", `Project to apply patch to. This cannot be passed with topic flag.`)
cmdPatch.Flags.BoolVar(&patchTopicFlag, "topic", false, `Patch whole topic.`)
@@ -205,6 +207,33 @@
return nil
}
+// rebaseProjectWRevision rebases the current branch on top of a given revision.
+func rebaseProjectWRevision(jirix *jiri.X, project project.Project, revision string) error {
+ jirix.Logger.Infof("Rebasing project %s(%s)\n", project.Name, project.Path)
+ scm := gitutil.New(jirix, gitutil.RootDirOpt(project.Path))
+ name, email, err := scm.UserInfoForCommit("HEAD")
+ if err != nil {
+ return fmt.Errorf("Rebase: cannot get user info for HEAD: %s", err)
+ }
+ scm = gitutil.New(jirix, gitutil.UserNameOpt(name), gitutil.UserEmailOpt(email), gitutil.RootDirOpt(project.Path))
+ if err := scm.FetchRefspec("origin", revision); err != nil {
+ jirix.Logger.Errorf("Not able to fetch revision %q: %s", revision, err)
+ jirix.IncrementFailures()
+ return nil
+ }
+ if err := scm.Rebase(revision); err != nil {
+ if err2 := scm.RebaseAbort(); err2 != nil {
+ return err2
+ }
+ jirix.Logger.Errorf("Cannot rebase the change: %s", err)
+ jirix.IncrementFailures()
+ atomic.AddUint32(&rebaseFailures, 1)
+ return nil
+ }
+ jirix.Logger.Infof("Project rebased\n")
+ return nil
+}
+
func findProject(jirix *jiri.X, projectName string, projects project.Projects, host string, hostUrl *url.URL, ref string) *project.Project {
var projectToPatch *project.Project
var projectToPatchNoGerritHost *project.Project
@@ -248,6 +277,10 @@
return jirix.UsageErrorf("-topic and -project flags cannot be used together")
}
+ if patchRebaseRevision != "" && (!patchRebaseFlag || patchProjectFlag == "") {
+ return jirix.UsageErrorf("-rebase-revision should only be used with -rebase and -project flag")
+ }
+
var cl int
var ps int
var err error
@@ -328,8 +361,14 @@
}
}
if ok && patchRebaseFlag {
- if err := rebaseProject(jirix, *p, remoteBranch); err != nil {
- return err
+ if patchRebaseRevision != "" {
+ if err := rebaseProjectWRevision(jirix, *p, patchRebaseRevision); err != nil {
+ return err
+ }
+ } else {
+ if err := rebaseProject(jirix, *p, remoteBranch); err != nil {
+ return err
+ }
}
}
} else {