Просмотр исходного кода

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
Bryan Jacobs 12 лет назад
Родитель
Сommit
f609f91b72
4 измененных файлов с 50 добавлено и 20 удалено
  1. 24 12
      docs/manifest-format.txt
  2. 6 1
      manifest_xml.py
  3. 13 5
      project.py
  4. 7 2
      subcmds/upload.py

+ 24 - 12
docs/manifest-format.txt

@@ -37,24 +37,26 @@ following DTD:
     <!ATTLIST remote review       CDATA #IMPLIED>
     <!ATTLIST remote review       CDATA #IMPLIED>
   
   
     <!ELEMENT default (EMPTY)>
     <!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)>
     <!ELEMENT manifest-server (EMPTY)>
     <!ATTLIST url              CDATA #REQUIRED>
     <!ATTLIST url              CDATA #REQUIRED>
   
   
     <!ELEMENT project (annotation?,
     <!ELEMENT project (annotation?,
                        project*)>
                        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 upstream CDATA #IMPLIED>
     <!ATTLIST project clone-depth CDATA #IMPLIED>
     <!ATTLIST project clone-depth CDATA #IMPLIED>
     <!ATTLIST project force-path CDATA #IMPLIED>
     <!ATTLIST project force-path CDATA #IMPLIED>
@@ -125,6 +127,11 @@ Attribute `revision`: Name of a Git branch (e.g. `master` or
 `refs/heads/master`).  Project elements lacking their own
 `refs/heads/master`).  Project elements lacking their own
 revision attribute will use this revision.
 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_j`: Number of parallel jobs to use when synching.
 
 
 Attribute `sync_c`: Set to true to only sync the given Git
 Attribute `sync_c`: Set to true to only sync the given Git
@@ -203,6 +210,11 @@ Tags and/or explicit SHA-1s should work in theory, but have not
 been extensively tested.  If not supplied the revision given by
 been extensively tested.  If not supplied the revision given by
 the default element is used.
 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,
 Attribute `groups`: List of groups to which this project belongs,
 whitespace or comma separated.  All projects belong to the group
 whitespace or comma separated.  All projects belong to the group
 "all", and each project automatically belongs to a group of
 "all", and each project automatically belongs to a group of

+ 6 - 1
manifest_xml.py

@@ -555,6 +555,8 @@ class XmlManifest(object):
     if d.revisionExpr == '':
     if d.revisionExpr == '':
       d.revisionExpr = None
       d.revisionExpr = None
 
 
+    d.destBranchExpr = node.getAttribute('dest-branch') or None
+
     sync_j = node.getAttribute('sync-j')
     sync_j = node.getAttribute('sync-j')
     if sync_j == '' or sync_j is None:
     if sync_j == '' or sync_j is None:
       d.sync_j = 1
       d.sync_j = 1
@@ -676,6 +678,8 @@ class XmlManifest(object):
         raise ManifestParseError('invalid clone-depth %s in %s' %
         raise ManifestParseError('invalid clone-depth %s in %s' %
                                  (clone_depth, self.manifestFile))
                                  (clone_depth, self.manifestFile))
 
 
+    dest_branch = node.getAttribute('dest-branch') or self._default.destBranchExpr
+
     upstream = node.getAttribute('upstream')
     upstream = node.getAttribute('upstream')
 
 
     groups = ''
     groups = ''
@@ -709,7 +713,8 @@ class XmlManifest(object):
                       sync_s = sync_s,
                       sync_s = sync_s,
                       clone_depth = clone_depth,
                       clone_depth = clone_depth,
                       upstream = upstream,
                       upstream = upstream,
-                      parent = parent)
+                      parent = parent,
+                      dest_branch = dest_branch)
 
 
     for n in node.childNodes:
     for n in node.childNodes:
       if n.nodeName == 'copyfile':
       if n.nodeName == 'copyfile':

+ 13 - 5
project.py

@@ -157,11 +157,12 @@ class ReviewableBranch(object):
       R_HEADS + self.name,
       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,
     self.project.UploadForReview(self.name,
                                  people,
                                  people,
                                  auto_topic=auto_topic,
                                  auto_topic=auto_topic,
-                                 draft=draft)
+                                 draft=draft,
+                                 dest_branch=dest_branch)
 
 
   def GetPublishedRefs(self):
   def GetPublishedRefs(self):
     refs = {}
     refs = {}
@@ -497,7 +498,8 @@ class Project(object):
                clone_depth = None,
                clone_depth = None,
                upstream = None,
                upstream = None,
                parent = None,
                parent = None,
-               is_derived = False):
+               is_derived = False,
+               dest_branch = None):
     """Init a Project object.
     """Init a Project object.
 
 
     Args:
     Args:
@@ -517,6 +519,7 @@ class Project(object):
       parent: The parent Project object.
       parent: The parent Project object.
       is_derived: False if the project was explicitly defined in the manifest;
       is_derived: False if the project was explicitly defined in the manifest;
                   True if the project is a discovered submodule.
                   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.manifest = manifest
     self.name = name
     self.name = name
@@ -559,6 +562,7 @@ class Project(object):
       self.work_git = None
       self.work_git = None
     self.bare_git = self._GitGetByExec(self, bare=True)
     self.bare_git = self._GitGetByExec(self, bare=True)
     self.bare_ref = GitRefs(gitdir)
     self.bare_ref = GitRefs(gitdir)
+    self.dest_branch = dest_branch
 
 
     # This will be filled in if a project is later identified to be the
     # This will be filled in if a project is later identified to be the
     # project containing repo hooks.
     # project containing repo hooks.
@@ -908,7 +912,8 @@ class Project(object):
   def UploadForReview(self, branch=None,
   def UploadForReview(self, branch=None,
                       people=([],[]),
                       people=([],[]),
                       auto_topic=False,
                       auto_topic=False,
-                      draft=False):
+                      draft=False,
+                      dest_branch=None):
     """Uploads the named branch for code review.
     """Uploads the named branch for code review.
     """
     """
     if branch is None:
     if branch is None:
@@ -922,7 +927,10 @@ class Project(object):
     if not branch.remote.review:
     if not branch.remote.review:
       raise GitError('remote %s has no review url' % branch.remote.name)
       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):
     if not dest_branch.startswith(R_HEADS):
       dest_branch = R_HEADS + dest_branch
       dest_branch = R_HEADS + dest_branch
 
 

+ 7 - 2
subcmds/upload.py

@@ -146,6 +146,10 @@ Gerrit Code Review:  http://code.google.com/p/gerrit/
     p.add_option('-d', '--draft',
     p.add_option('-d', '--draft',
                  action='store_true', dest='draft', default=False,
                  action='store_true', dest='draft', default=False,
                  help='If specified, upload as a draft.')
                  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
     # 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.
     # opposites of each other, which is why they store to different locations.
@@ -185,7 +189,8 @@ Gerrit Code Review:  http://code.google.com/p/gerrit/
       date = branch.date
       date = branch.date
       commit_list = branch.commits
       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):' % (
       print('  branch %s (%2d commit%s, %s):' % (
                     name,
                     name,
                     len(commit_list),
                     len(commit_list),
@@ -336,7 +341,7 @@ Gerrit Code Review:  http://code.google.com/p/gerrit/
           key = 'review.%s.uploadtopic' % branch.project.remote.review
           key = 'review.%s.uploadtopic' % branch.project.remote.review
           opt.auto_topic = branch.project.config.GetBoolean(key)
           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
         branch.uploaded = True
       except UploadError as e:
       except UploadError as e:
         branch.error = e
         branch.error = e