Send reviews to a different branch from fetch
This adds the ability to have reviews pushed to a different branch
from the one on which changes are based. This is useful for "gateway"
systems without smartsync.
Change-Id: I3a8a0fabcaf6055e62d3fb55f89c944e2f81569f
diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt
index 59f6a2f..dcc90d0 100644
--- a/docs/manifest-format.txt
+++ b/docs/manifest-format.txt
@@ -37,24 +37,26 @@
<!ATTLIST remote review CDATA #IMPLIED>
<!ELEMENT default (EMPTY)>
- <!ATTLIST default remote IDREF #IMPLIED>
- <!ATTLIST default revision CDATA #IMPLIED>
- <!ATTLIST default sync-j CDATA #IMPLIED>
- <!ATTLIST default sync-c CDATA #IMPLIED>
- <!ATTLIST default sync-s CDATA #IMPLIED>
+ <!ATTLIST default remote IDREF #IMPLIED>
+ <!ATTLIST default revision CDATA #IMPLIED>
+ <!ATTLIST default dest-branch CDATA #IMPLIED>
+ <!ATTLIST default sync-j CDATA #IMPLIED>
+ <!ATTLIST default sync-c CDATA #IMPLIED>
+ <!ATTLIST default sync-s CDATA #IMPLIED>
<!ELEMENT manifest-server (EMPTY)>
<!ATTLIST url CDATA #REQUIRED>
<!ELEMENT project (annotation?,
project*)>
- <!ATTLIST project name CDATA #REQUIRED>
- <!ATTLIST project path CDATA #IMPLIED>
- <!ATTLIST project remote IDREF #IMPLIED>
- <!ATTLIST project revision CDATA #IMPLIED>
- <!ATTLIST project groups CDATA #IMPLIED>
- <!ATTLIST project sync-c CDATA #IMPLIED>
- <!ATTLIST project sync-s CDATA #IMPLIED>
+ <!ATTLIST project name CDATA #REQUIRED>
+ <!ATTLIST project path CDATA #IMPLIED>
+ <!ATTLIST project remote IDREF #IMPLIED>
+ <!ATTLIST project revision CDATA #IMPLIED>
+ <!ATTLIST project dest-branch CDATA #IMPLIED>
+ <!ATTLIST project groups CDATA #IMPLIED>
+ <!ATTLIST project sync-c CDATA #IMPLIED>
+ <!ATTLIST project sync-s CDATA #IMPLIED>
<!ATTLIST project upstream CDATA #IMPLIED>
<!ATTLIST project clone-depth CDATA #IMPLIED>
<!ATTLIST project force-path CDATA #IMPLIED>
@@ -125,6 +127,11 @@
`refs/heads/master`). Project elements lacking their own
revision attribute will use this revision.
+Attribute `dest-branch`: Name of a Git branch (e.g. `master`).
+Project elements not setting their own `dest-branch` will inherit
+this value. If this value is not set, projects will use `revision`
+by default instead.
+
Attribute `sync_j`: Number of parallel jobs to use when synching.
Attribute `sync_c`: Set to true to only sync the given Git
@@ -203,6 +210,11 @@
been extensively tested. If not supplied the revision given by
the default element is used.
+Attribute `dest-branch`: Name of a Git branch (e.g. `master`).
+When using `repo upload`, changes will be submitted for code
+review on this branch. If unspecified both here and in the
+default element, `revision` is used instead.
+
Attribute `groups`: List of groups to which this project belongs,
whitespace or comma separated. All projects belong to the group
"all", and each project automatically belongs to a group of
diff --git a/manifest_xml.py b/manifest_xml.py
index 16476aa..817a1c8 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -555,6 +555,8 @@
if d.revisionExpr == '':
d.revisionExpr = None
+ d.destBranchExpr = node.getAttribute('dest-branch') or None
+
sync_j = node.getAttribute('sync-j')
if sync_j == '' or sync_j is None:
d.sync_j = 1
@@ -676,6 +678,8 @@
raise ManifestParseError('invalid clone-depth %s in %s' %
(clone_depth, self.manifestFile))
+ dest_branch = node.getAttribute('dest-branch') or self._default.destBranchExpr
+
upstream = node.getAttribute('upstream')
groups = ''
@@ -709,7 +713,8 @@
sync_s = sync_s,
clone_depth = clone_depth,
upstream = upstream,
- parent = parent)
+ parent = parent,
+ dest_branch = dest_branch)
for n in node.childNodes:
if n.nodeName == 'copyfile':
diff --git a/project.py b/project.py
index f299297..5a7a6ca 100644
--- a/project.py
+++ b/project.py
@@ -157,11 +157,12 @@
R_HEADS + self.name,
'--')
- def UploadForReview(self, people, auto_topic=False, draft=False):
+ def UploadForReview(self, people, auto_topic=False, draft=False, dest_branch=None):
self.project.UploadForReview(self.name,
people,
auto_topic=auto_topic,
- draft=draft)
+ draft=draft,
+ dest_branch=dest_branch)
def GetPublishedRefs(self):
refs = {}
@@ -497,7 +498,8 @@
clone_depth = None,
upstream = None,
parent = None,
- is_derived = False):
+ is_derived = False,
+ dest_branch = None):
"""Init a Project object.
Args:
@@ -517,6 +519,7 @@
parent: The parent Project object.
is_derived: False if the project was explicitly defined in the manifest;
True if the project is a discovered submodule.
+ dest_branch: The branch to which to push changes for review by default.
"""
self.manifest = manifest
self.name = name
@@ -559,6 +562,7 @@
self.work_git = None
self.bare_git = self._GitGetByExec(self, bare=True)
self.bare_ref = GitRefs(gitdir)
+ self.dest_branch = dest_branch
# This will be filled in if a project is later identified to be the
# project containing repo hooks.
@@ -908,7 +912,8 @@
def UploadForReview(self, branch=None,
people=([],[]),
auto_topic=False,
- draft=False):
+ draft=False,
+ dest_branch=None):
"""Uploads the named branch for code review.
"""
if branch is None:
@@ -922,7 +927,10 @@
if not branch.remote.review:
raise GitError('remote %s has no review url' % branch.remote.name)
- dest_branch = branch.merge
+ if dest_branch is None:
+ dest_branch = self.dest_branch
+ if dest_branch is None:
+ dest_branch = branch.merge
if not dest_branch.startswith(R_HEADS):
dest_branch = R_HEADS + dest_branch
diff --git a/subcmds/upload.py b/subcmds/upload.py
index 13b8778..4a22e26 100644
--- a/subcmds/upload.py
+++ b/subcmds/upload.py
@@ -146,6 +146,10 @@
p.add_option('-d', '--draft',
action='store_true', dest='draft', default=False,
help='If specified, upload as a draft.')
+ p.add_option('-D', '--destination', '--dest',
+ type='string', action='store', dest='dest_branch',
+ metavar='BRANCH',
+ help='Submit for review on this target branch.')
# Options relating to upload hook. Note that verify and no-verify are NOT
# opposites of each other, which is why they store to different locations.
@@ -185,7 +189,8 @@
date = branch.date
commit_list = branch.commits
- print('Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr))
+ destination = project.dest_branch or project.revisionExpr
+ print('Upload project %s/ to remote branch %s:' % (project.relpath, destination))
print(' branch %s (%2d commit%s, %s):' % (
name,
len(commit_list),
@@ -336,7 +341,7 @@
key = 'review.%s.uploadtopic' % branch.project.remote.review
opt.auto_topic = branch.project.config.GetBoolean(key)
- branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft)
+ branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft, dest_branch=opt.dest_branch)
branch.uploaded = True
except UploadError as e:
branch.error = e