mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-28 20:17:26 +00:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
9830553748 | |||
2bc7f5cb3a | |||
b292b98c3e | |||
2f127de752 | |||
7da1314e38 | |||
435370c6f0 | |||
e8f75fa368 |
@ -32,6 +32,7 @@ following DTD:
|
|||||||
|
|
||||||
<!ELEMENT remote (EMPTY)>
|
<!ELEMENT remote (EMPTY)>
|
||||||
<!ATTLIST remote name ID #REQUIRED>
|
<!ATTLIST remote name ID #REQUIRED>
|
||||||
|
<!ATTLIST remote alias CDATA #IMPLIED>
|
||||||
<!ATTLIST remote fetch CDATA #REQUIRED>
|
<!ATTLIST remote fetch CDATA #REQUIRED>
|
||||||
<!ATTLIST remote review CDATA #IMPLIED>
|
<!ATTLIST remote review CDATA #IMPLIED>
|
||||||
|
|
||||||
@ -89,6 +90,12 @@ name specified here is used as the remote name in each project's
|
|||||||
.git/config, and is therefore automatically available to commands
|
.git/config, and is therefore automatically available to commands
|
||||||
like `git fetch`, `git remote`, `git pull` and `git push`.
|
like `git fetch`, `git remote`, `git pull` and `git push`.
|
||||||
|
|
||||||
|
Attribute `alias`: The alias, if specified, is used to override
|
||||||
|
`name` to be set as the remote name in each project's .git/config.
|
||||||
|
Its value can be duplicated while attribute `name` has to be unique
|
||||||
|
in the manifest file. This helps each project to be able to have
|
||||||
|
same remote name which actually points to different remote url.
|
||||||
|
|
||||||
Attribute `fetch`: The Git URL prefix for all projects which use
|
Attribute `fetch`: The Git URL prefix for all projects which use
|
||||||
this remote. Each project's name is appended to this prefix to
|
this remote. Each project's name is appended to this prefix to
|
||||||
form the actual URL used to clone the project.
|
form the actual URL used to clone the project.
|
||||||
@ -171,7 +178,11 @@ the default element is used.
|
|||||||
|
|
||||||
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
|
||||||
"default".
|
"default", and each project automatically belongs to a group of
|
||||||
|
it's name:`name` and path:`path`. E.g. for
|
||||||
|
<project name="monkeys" path="barrel-of"/>, that project
|
||||||
|
definition is implicitly in the following manifest groups:
|
||||||
|
default, name:monkeys, and path:barrel-of.
|
||||||
|
|
||||||
Element annotation
|
Element annotation
|
||||||
------------------
|
------------------
|
||||||
|
@ -89,7 +89,7 @@ class _GitCall(object):
|
|||||||
if ver_str.startswith('git version '):
|
if ver_str.startswith('git version '):
|
||||||
_git_version = tuple(
|
_git_version = tuple(
|
||||||
map(lambda x: int(x),
|
map(lambda x: int(x),
|
||||||
ver_str[len('git version '):].strip().split('.')[0:3]
|
ver_str[len('git version '):].strip().split('-')[0].split('.')[0:3]
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, 'fatal: "%s" unsupported' % ver_str
|
print >>sys.stderr, 'fatal: "%s" unsupported' % ver_str
|
||||||
|
@ -41,12 +41,14 @@ class _Default(object):
|
|||||||
class _XmlRemote(object):
|
class _XmlRemote(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name,
|
||||||
|
alias=None,
|
||||||
fetch=None,
|
fetch=None,
|
||||||
manifestUrl=None,
|
manifestUrl=None,
|
||||||
review=None):
|
review=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fetchUrl = fetch
|
self.fetchUrl = fetch
|
||||||
self.manifestUrl = manifestUrl
|
self.manifestUrl = manifestUrl
|
||||||
|
self.remoteAlias = alias
|
||||||
self.reviewUrl = review
|
self.reviewUrl = review
|
||||||
self.resolvedFetchUrl = self._resolveFetchUrl()
|
self.resolvedFetchUrl = self._resolveFetchUrl()
|
||||||
|
|
||||||
@ -62,7 +64,10 @@ class _XmlRemote(object):
|
|||||||
|
|
||||||
def ToRemoteSpec(self, projectName):
|
def ToRemoteSpec(self, projectName):
|
||||||
url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName
|
url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName
|
||||||
return RemoteSpec(self.name, url, self.reviewUrl)
|
remoteName = self.name
|
||||||
|
if self.remoteAlias:
|
||||||
|
remoteName = self.remoteAlias
|
||||||
|
return RemoteSpec(remoteName, url, self.reviewUrl)
|
||||||
|
|
||||||
class XmlManifest(object):
|
class XmlManifest(object):
|
||||||
"""manages the repo configuration file"""
|
"""manages the repo configuration file"""
|
||||||
@ -451,12 +456,15 @@ class XmlManifest(object):
|
|||||||
reads a <remote> element from the manifest file
|
reads a <remote> element from the manifest file
|
||||||
"""
|
"""
|
||||||
name = self._reqatt(node, 'name')
|
name = self._reqatt(node, 'name')
|
||||||
|
alias = node.getAttribute('alias')
|
||||||
|
if alias == '':
|
||||||
|
alias = None
|
||||||
fetch = self._reqatt(node, 'fetch')
|
fetch = self._reqatt(node, 'fetch')
|
||||||
review = node.getAttribute('review')
|
review = node.getAttribute('review')
|
||||||
if review == '':
|
if review == '':
|
||||||
review = None
|
review = None
|
||||||
manifestUrl = self.manifestProject.config.GetString('remote.origin.url')
|
manifestUrl = self.manifestProject.config.GetString('remote.origin.url')
|
||||||
return _XmlRemote(name, fetch, manifestUrl, review)
|
return _XmlRemote(name, alias, fetch, manifestUrl, review)
|
||||||
|
|
||||||
def _ParseDefault(self, node):
|
def _ParseDefault(self, node):
|
||||||
"""
|
"""
|
||||||
@ -566,8 +574,9 @@ class XmlManifest(object):
|
|||||||
if node.hasAttribute('groups'):
|
if node.hasAttribute('groups'):
|
||||||
groups = node.getAttribute('groups')
|
groups = node.getAttribute('groups')
|
||||||
groups = [x for x in re.split('[,\s]+', groups) if x]
|
groups = [x for x in re.split('[,\s]+', groups) if x]
|
||||||
if 'default' not in groups:
|
|
||||||
groups.append('default')
|
default_groups = ['default', 'name:%s' % name, 'path:%s' % path]
|
||||||
|
groups.extend(set(default_groups).difference(groups))
|
||||||
|
|
||||||
if self.IsMirror:
|
if self.IsMirror:
|
||||||
relpath = None
|
relpath = None
|
||||||
|
26
project.py
26
project.py
@ -176,10 +176,11 @@ class ReviewableBranch(object):
|
|||||||
R_HEADS + self.name,
|
R_HEADS + self.name,
|
||||||
'--')
|
'--')
|
||||||
|
|
||||||
def UploadForReview(self, people, auto_topic=False):
|
def UploadForReview(self, people, auto_topic=False, draft=False):
|
||||||
self.project.UploadForReview(self.name,
|
self.project.UploadForReview(self.name,
|
||||||
people,
|
people,
|
||||||
auto_topic=auto_topic)
|
auto_topic=auto_topic,
|
||||||
|
draft=draft)
|
||||||
|
|
||||||
def GetPublishedRefs(self):
|
def GetPublishedRefs(self):
|
||||||
refs = {}
|
refs = {}
|
||||||
@ -881,7 +882,8 @@ class Project(object):
|
|||||||
|
|
||||||
def UploadForReview(self, branch=None,
|
def UploadForReview(self, branch=None,
|
||||||
people=([],[]),
|
people=([],[]),
|
||||||
auto_topic=False):
|
auto_topic=False,
|
||||||
|
draft=False):
|
||||||
"""Uploads the named branch for code review.
|
"""Uploads the named branch for code review.
|
||||||
"""
|
"""
|
||||||
if branch is None:
|
if branch is None:
|
||||||
@ -920,7 +922,13 @@ class Project(object):
|
|||||||
|
|
||||||
if dest_branch.startswith(R_HEADS):
|
if dest_branch.startswith(R_HEADS):
|
||||||
dest_branch = dest_branch[len(R_HEADS):]
|
dest_branch = dest_branch[len(R_HEADS):]
|
||||||
ref_spec = '%s:refs/for/%s' % (R_HEADS + branch.name, dest_branch)
|
|
||||||
|
upload_type = 'for'
|
||||||
|
if draft:
|
||||||
|
upload_type = 'drafts'
|
||||||
|
|
||||||
|
ref_spec = '%s:refs/%s/%s' % (R_HEADS + branch.name, upload_type,
|
||||||
|
dest_branch)
|
||||||
if auto_topic:
|
if auto_topic:
|
||||||
ref_spec = ref_spec + '/' + branch.name
|
ref_spec = ref_spec + '/' + branch.name
|
||||||
cmd.append(ref_spec)
|
cmd.append(ref_spec)
|
||||||
@ -1556,7 +1564,7 @@ class Project(object):
|
|||||||
try:
|
try:
|
||||||
req = urllib2.Request(srcUrl)
|
req = urllib2.Request(srcUrl)
|
||||||
if pos > 0:
|
if pos > 0:
|
||||||
req.add_header('Range', 'bytes=%d-' % pos)
|
req.add_header('Range', 'bytes=%d-' % (pos,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = urllib2.urlopen(req)
|
r = urllib2.urlopen(req)
|
||||||
@ -1575,7 +1583,7 @@ class Project(object):
|
|||||||
msg = e.read()
|
msg = e.read()
|
||||||
if len(msg) > 0 and msg[-1] == '\n':
|
if len(msg) > 0 and msg[-1] == '\n':
|
||||||
msg = msg[0:-1]
|
msg = msg[0:-1]
|
||||||
msg = ' (%s)' % msg
|
msg = ' (%s)' % (msg,)
|
||||||
except:
|
except:
|
||||||
msg = ''
|
msg = ''
|
||||||
else:
|
else:
|
||||||
@ -1593,7 +1601,7 @@ class Project(object):
|
|||||||
|
|
||||||
p = None
|
p = None
|
||||||
try:
|
try:
|
||||||
size = r.headers.get('content-length', 0)
|
size = pos + r.headers.get('content-length', 0)
|
||||||
unit = 1 << 10
|
unit = 1 << 10
|
||||||
|
|
||||||
if size and not quiet:
|
if size and not quiet:
|
||||||
@ -1603,7 +1611,7 @@ class Project(object):
|
|||||||
else:
|
else:
|
||||||
desc = 'KB'
|
desc = 'KB'
|
||||||
p = Progress(
|
p = Progress(
|
||||||
'Downloading %s' % self.relpath,
|
'Downloading %s' % (self.relpath,),
|
||||||
int(size) / unit,
|
int(size) / unit,
|
||||||
units=desc)
|
units=desc)
|
||||||
if pos > 0:
|
if pos > 0:
|
||||||
@ -2181,7 +2189,7 @@ class MetaProject(Project):
|
|||||||
syncbuf.Finish()
|
syncbuf.Finish()
|
||||||
|
|
||||||
return GitCommand(self,
|
return GitCommand(self,
|
||||||
['branch', '-D', 'default'],
|
['update-ref', '-d', 'refs/heads/default'],
|
||||||
capture_stdout = True,
|
capture_stdout = True,
|
||||||
capture_stderr = True).Wait() == 0
|
capture_stderr = True).Wait() == 0
|
||||||
|
|
||||||
|
80
subcmds/overview.py
Normal file
80
subcmds/overview.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2012 The Android Open Source Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from color import Coloring
|
||||||
|
from command import PagedCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Overview(PagedCommand):
|
||||||
|
common = True
|
||||||
|
helpSummary = "Display overview of unmerged project branches"
|
||||||
|
helpUsage = """
|
||||||
|
%prog [--current-branch] [<project>...]
|
||||||
|
"""
|
||||||
|
helpDescription = """
|
||||||
|
The '%prog' command is used to display an overview of the projects branches,
|
||||||
|
and list any local commits that have not yet been merged into the project.
|
||||||
|
|
||||||
|
The -b/--current-branch option can be used to restrict the output to only
|
||||||
|
branches currently checked out in each project. By default, all branches
|
||||||
|
are displayed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _Options(self, p):
|
||||||
|
p.add_option('-b', '--current-branch',
|
||||||
|
dest="current_branch", action="store_true",
|
||||||
|
help="Consider only checked out branches")
|
||||||
|
|
||||||
|
def Execute(self, opt, args):
|
||||||
|
all = []
|
||||||
|
for project in self.GetProjects(args):
|
||||||
|
br = [project.GetUploadableBranch(x)
|
||||||
|
for x in project.GetBranches().keys()]
|
||||||
|
br = [x for x in br if x]
|
||||||
|
if opt.current_branch:
|
||||||
|
br = [x for x in br if x.name == project.CurrentBranch]
|
||||||
|
all.extend(br)
|
||||||
|
|
||||||
|
if not all:
|
||||||
|
return
|
||||||
|
|
||||||
|
class Report(Coloring):
|
||||||
|
def __init__(self, config):
|
||||||
|
Coloring.__init__(self, config, 'status')
|
||||||
|
self.project = self.printer('header', attr='bold')
|
||||||
|
|
||||||
|
out = Report(all[0].project.config)
|
||||||
|
out.project('Projects Overview')
|
||||||
|
out.nl()
|
||||||
|
|
||||||
|
project = None
|
||||||
|
|
||||||
|
for branch in all:
|
||||||
|
if project != branch.project:
|
||||||
|
project = branch.project
|
||||||
|
out.nl()
|
||||||
|
out.project('project %s/' % project.relpath)
|
||||||
|
out.nl()
|
||||||
|
|
||||||
|
commits = branch.commits
|
||||||
|
date = branch.date
|
||||||
|
print '%s %-33s (%2d commit%s, %s)' % (
|
||||||
|
branch.name == project.CurrentBranch and '*' or ' ',
|
||||||
|
branch.name,
|
||||||
|
len(commits),
|
||||||
|
len(commits) != 1 and 's' or ' ',
|
||||||
|
date)
|
||||||
|
for commit in commits:
|
||||||
|
print '%-35s - %s' % ('', commit)
|
@ -134,6 +134,9 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
p.add_option('--cbr', '--current-branch',
|
p.add_option('--cbr', '--current-branch',
|
||||||
dest='current_branch', action='store_true',
|
dest='current_branch', action='store_true',
|
||||||
help='Upload current git branch.')
|
help='Upload current git branch.')
|
||||||
|
p.add_option('-d', '--draft',
|
||||||
|
action='store_true', dest='draft', default=False,
|
||||||
|
help='If specified, upload as a draft.')
|
||||||
|
|
||||||
# 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.
|
||||||
@ -324,7 +327,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)
|
branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft)
|
||||||
branch.uploaded = True
|
branch.uploaded = True
|
||||||
except UploadError, e:
|
except UploadError, e:
|
||||||
branch.error = e
|
branch.error = e
|
||||||
|
Reference in New Issue
Block a user