mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-28 20:17:26 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
30d452905f | |||
d6c93a28ca | |||
d572a13021 | |||
3ba5f95b46 | |||
2630dd9787 | |||
dafb1d68d3 | |||
4655e81a75 | |||
723c5dc3d6 | |||
e6a0eeb80d |
48
project.py
48
project.py
@ -650,13 +650,18 @@ class Project(object):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def PrintWorkTreeStatus(self):
|
def PrintWorkTreeStatus(self, output_redir=None):
|
||||||
"""Prints the status of the repository to stdout.
|
"""Prints the status of the repository to stdout.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
output: If specified, redirect the output to this object.
|
||||||
"""
|
"""
|
||||||
if not os.path.isdir(self.worktree):
|
if not os.path.isdir(self.worktree):
|
||||||
print ''
|
if output_redir == None:
|
||||||
print 'project %s/' % self.relpath
|
output_redir = sys.stdout
|
||||||
print ' missing (run "repo sync")'
|
print >>output_redir, ''
|
||||||
|
print >>output_redir, 'project %s/' % self.relpath
|
||||||
|
print >>output_redir, ' missing (run "repo sync")'
|
||||||
return
|
return
|
||||||
|
|
||||||
self.work_git.update_index('-q',
|
self.work_git.update_index('-q',
|
||||||
@ -671,6 +676,8 @@ class Project(object):
|
|||||||
return 'CLEAN'
|
return 'CLEAN'
|
||||||
|
|
||||||
out = StatusColoring(self.config)
|
out = StatusColoring(self.config)
|
||||||
|
if not output_redir == None:
|
||||||
|
out.redirect(output_redir)
|
||||||
out.project('project %-40s', self.relpath + '/')
|
out.project('project %-40s', self.relpath + '/')
|
||||||
|
|
||||||
branch = self.CurrentBranch
|
branch = self.CurrentBranch
|
||||||
@ -720,6 +727,7 @@ class Project(object):
|
|||||||
else:
|
else:
|
||||||
out.write('%s', line)
|
out.write('%s', line)
|
||||||
out.nl()
|
out.nl()
|
||||||
|
|
||||||
return 'DIRTY'
|
return 'DIRTY'
|
||||||
|
|
||||||
def PrintWorkTreeDiff(self):
|
def PrintWorkTreeDiff(self):
|
||||||
@ -783,7 +791,7 @@ class Project(object):
|
|||||||
if R_HEADS + n not in heads:
|
if R_HEADS + n not in heads:
|
||||||
self.bare_git.DeleteRef(name, id)
|
self.bare_git.DeleteRef(name, id)
|
||||||
|
|
||||||
def GetUploadableBranches(self):
|
def GetUploadableBranches(self, selected_branch=None):
|
||||||
"""List any branches which can be uploaded for review.
|
"""List any branches which can be uploaded for review.
|
||||||
"""
|
"""
|
||||||
heads = {}
|
heads = {}
|
||||||
@ -799,6 +807,8 @@ class Project(object):
|
|||||||
for branch, id in heads.iteritems():
|
for branch, id in heads.iteritems():
|
||||||
if branch in pubed and pubed[branch] == id:
|
if branch in pubed and pubed[branch] == id:
|
||||||
continue
|
continue
|
||||||
|
if selected_branch and branch != selected_branch:
|
||||||
|
continue
|
||||||
|
|
||||||
rb = self.GetUploadableBranch(branch)
|
rb = self.GetUploadableBranch(branch)
|
||||||
if rb:
|
if rb:
|
||||||
@ -1159,6 +1169,13 @@ class Project(object):
|
|||||||
|
|
||||||
def CheckoutBranch(self, name):
|
def CheckoutBranch(self, name):
|
||||||
"""Checkout a local topic branch.
|
"""Checkout a local topic branch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The name of the branch to checkout.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the checkout succeeded; False if it didn't; None if the branch
|
||||||
|
didn't exist.
|
||||||
"""
|
"""
|
||||||
rev = R_HEADS + name
|
rev = R_HEADS + name
|
||||||
head = self.work_git.GetHead()
|
head = self.work_git.GetHead()
|
||||||
@ -1173,7 +1190,7 @@ class Project(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
# Branch does not exist in this project
|
# Branch does not exist in this project
|
||||||
#
|
#
|
||||||
return False
|
return None
|
||||||
|
|
||||||
if head.startswith(R_HEADS):
|
if head.startswith(R_HEADS):
|
||||||
try:
|
try:
|
||||||
@ -1196,13 +1213,19 @@ class Project(object):
|
|||||||
|
|
||||||
def AbandonBranch(self, name):
|
def AbandonBranch(self, name):
|
||||||
"""Destroy a local topic branch.
|
"""Destroy a local topic branch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The name of the branch to abandon.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the abandon succeeded; False if it didn't; None if the branch
|
||||||
|
didn't exist.
|
||||||
"""
|
"""
|
||||||
rev = R_HEADS + name
|
rev = R_HEADS + name
|
||||||
all = self.bare_ref.all
|
all = self.bare_ref.all
|
||||||
if rev not in all:
|
if rev not in all:
|
||||||
# Doesn't exist; assume already abandoned.
|
# Doesn't exist
|
||||||
#
|
return None
|
||||||
return True
|
|
||||||
|
|
||||||
head = self.work_git.GetHead()
|
head = self.work_git.GetHead()
|
||||||
if head == rev:
|
if head == rev:
|
||||||
@ -1347,6 +1370,13 @@ class Project(object):
|
|||||||
ref_dir = None
|
ref_dir = None
|
||||||
|
|
||||||
cmd = ['fetch']
|
cmd = ['fetch']
|
||||||
|
|
||||||
|
# The --depth option only affects the initial fetch; after that we'll do
|
||||||
|
# full fetches of changes.
|
||||||
|
depth = self.manifest.manifestProject.config.GetString('repo.depth')
|
||||||
|
if depth and initial:
|
||||||
|
cmd.append('--depth=%s' % depth)
|
||||||
|
|
||||||
if quiet:
|
if quiet:
|
||||||
cmd.append('--quiet')
|
cmd.append('--quiet')
|
||||||
if not self.worktree:
|
if not self.worktree:
|
||||||
|
@ -41,21 +41,30 @@ It is equivalent to "git branch -D <branchname>".
|
|||||||
|
|
||||||
nb = args[0]
|
nb = args[0]
|
||||||
err = []
|
err = []
|
||||||
|
success = []
|
||||||
all = self.GetProjects(args[1:])
|
all = self.GetProjects(args[1:])
|
||||||
|
|
||||||
pm = Progress('Abandon %s' % nb, len(all))
|
pm = Progress('Abandon %s' % nb, len(all))
|
||||||
for project in all:
|
for project in all:
|
||||||
pm.update()
|
pm.update()
|
||||||
if not project.AbandonBranch(nb):
|
|
||||||
err.append(project)
|
status = project.AbandonBranch(nb)
|
||||||
|
if status is not None:
|
||||||
|
if status:
|
||||||
|
success.append(project)
|
||||||
|
else:
|
||||||
|
err.append(project)
|
||||||
pm.end()
|
pm.end()
|
||||||
|
|
||||||
if err:
|
if err:
|
||||||
if len(err) == len(all):
|
for p in err:
|
||||||
print >>sys.stderr, 'error: no project has branch %s' % nb
|
print >>sys.stderr,\
|
||||||
else:
|
"error: %s/: cannot abandon %s" \
|
||||||
for p in err:
|
% (p.relpath, nb)
|
||||||
print >>sys.stderr,\
|
|
||||||
"error: %s/: cannot abandon %s" \
|
|
||||||
% (p.relpath, nb)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
elif not success:
|
||||||
|
print >>sys.stderr, 'error: no project has branch %s' % nb
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print >>sys.stderr, 'Abandoned in %d project(s):\n %s' % (
|
||||||
|
len(success), '\n '.join(p.relpath for p in success))
|
||||||
|
@ -38,21 +38,27 @@ The command is equivalent to:
|
|||||||
|
|
||||||
nb = args[0]
|
nb = args[0]
|
||||||
err = []
|
err = []
|
||||||
|
success = []
|
||||||
all = self.GetProjects(args[1:])
|
all = self.GetProjects(args[1:])
|
||||||
|
|
||||||
pm = Progress('Checkout %s' % nb, len(all))
|
pm = Progress('Checkout %s' % nb, len(all))
|
||||||
for project in all:
|
for project in all:
|
||||||
pm.update()
|
pm.update()
|
||||||
if not project.CheckoutBranch(nb):
|
|
||||||
err.append(project)
|
status = project.CheckoutBranch(nb)
|
||||||
|
if status is not None:
|
||||||
|
if status:
|
||||||
|
success.append(project)
|
||||||
|
else:
|
||||||
|
err.append(project)
|
||||||
pm.end()
|
pm.end()
|
||||||
|
|
||||||
if err:
|
if err:
|
||||||
if len(err) == len(all):
|
for p in err:
|
||||||
print >>sys.stderr, 'error: no project has branch %s' % nb
|
print >>sys.stderr,\
|
||||||
else:
|
"error: %s/: cannot checkout %s" \
|
||||||
for p in err:
|
% (p.relpath, nb)
|
||||||
print >>sys.stderr,\
|
sys.exit(1)
|
||||||
"error: %s/: cannot checkout %s" \
|
elif not success:
|
||||||
% (p.relpath, nb)
|
print >>sys.stderr, 'error: no project has branch %s' % nb
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
114
subcmds/cherry_pick.py
Normal file
114
subcmds/cherry_pick.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2010 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.
|
||||||
|
|
||||||
|
import sys, re, string, random, os
|
||||||
|
from command import Command
|
||||||
|
from git_command import GitCommand
|
||||||
|
|
||||||
|
CHANGE_ID_RE = re.compile(r'^\s*Change-Id: I([0-9a-f]{40})\s*$')
|
||||||
|
|
||||||
|
class CherryPick(Command):
|
||||||
|
common = True
|
||||||
|
helpSummary = "Cherry-pick a change."
|
||||||
|
helpUsage = """
|
||||||
|
%prog <sha1>
|
||||||
|
"""
|
||||||
|
helpDescription = """
|
||||||
|
'%prog' cherry-picks a change from one branch to another.
|
||||||
|
The change id will be updated, and a reference to the old
|
||||||
|
change id will be added.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _Options(self, p):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Execute(self, opt, args):
|
||||||
|
if len(args) != 1:
|
||||||
|
self.Usage()
|
||||||
|
|
||||||
|
reference = args[0]
|
||||||
|
|
||||||
|
p = GitCommand(None,
|
||||||
|
['rev-parse', '--verify', reference],
|
||||||
|
capture_stdout = True,
|
||||||
|
capture_stderr = True)
|
||||||
|
if p.Wait() != 0:
|
||||||
|
print >>sys.stderr, p.stderr
|
||||||
|
sys.exit(1)
|
||||||
|
sha1 = p.stdout.strip()
|
||||||
|
|
||||||
|
p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True)
|
||||||
|
if p.Wait() != 0:
|
||||||
|
print >>sys.stderr, "error: Failed to retrieve old commit message"
|
||||||
|
sys.exit(1)
|
||||||
|
old_msg = self._StripHeader(p.stdout)
|
||||||
|
|
||||||
|
p = GitCommand(None,
|
||||||
|
['cherry-pick', sha1],
|
||||||
|
capture_stdout = True,
|
||||||
|
capture_stderr = True)
|
||||||
|
status = p.Wait()
|
||||||
|
|
||||||
|
print >>sys.stdout, p.stdout
|
||||||
|
print >>sys.stderr, p.stderr
|
||||||
|
|
||||||
|
if status == 0:
|
||||||
|
# The cherry-pick was applied correctly. We just need to edit the
|
||||||
|
# commit message.
|
||||||
|
new_msg = self._Reformat(old_msg, sha1)
|
||||||
|
|
||||||
|
p = GitCommand(None, ['commit', '--amend', '-F', '-'],
|
||||||
|
provide_stdin = True,
|
||||||
|
capture_stdout = True,
|
||||||
|
capture_stderr = True)
|
||||||
|
p.stdin.write(new_msg)
|
||||||
|
if p.Wait() != 0:
|
||||||
|
print >>sys.stderr, "error: Failed to update commit message"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print >>sys.stderr, """\
|
||||||
|
NOTE: When committing (please see above) and editing the commit message,
|
||||||
|
please remove the old Change-Id-line and add:
|
||||||
|
"""
|
||||||
|
print >>sys.stderr, self._GetReference(sha1)
|
||||||
|
print >>sys.stderr
|
||||||
|
|
||||||
|
def _IsChangeId(self, line):
|
||||||
|
return CHANGE_ID_RE.match(line)
|
||||||
|
|
||||||
|
def _GetReference(self, sha1):
|
||||||
|
return "(cherry picked from commit %s)" % sha1
|
||||||
|
|
||||||
|
def _StripHeader(self, commit_msg):
|
||||||
|
lines = commit_msg.splitlines()
|
||||||
|
return "\n".join(lines[lines.index("")+1:])
|
||||||
|
|
||||||
|
def _Reformat(self, old_msg, sha1):
|
||||||
|
new_msg = []
|
||||||
|
|
||||||
|
for line in old_msg.splitlines():
|
||||||
|
if not self._IsChangeId(line):
|
||||||
|
new_msg.append(line)
|
||||||
|
|
||||||
|
# Add a blank line between the message and the change id/reference
|
||||||
|
try:
|
||||||
|
if new_msg[-1].strip() != "":
|
||||||
|
new_msg.append("")
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
new_msg.append(self._GetReference(sha1))
|
||||||
|
return "\n".join(new_msg)
|
@ -14,6 +14,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from color import Coloring
|
from color import Coloring
|
||||||
@ -81,6 +82,9 @@ to update the working directory files.
|
|||||||
g.add_option('--reference',
|
g.add_option('--reference',
|
||||||
dest='reference',
|
dest='reference',
|
||||||
help='location of mirror directory', metavar='DIR')
|
help='location of mirror directory', metavar='DIR')
|
||||||
|
g.add_option('--depth', type='int', default=None,
|
||||||
|
dest='depth',
|
||||||
|
help='create a shallow clone with given depth; see git clone')
|
||||||
|
|
||||||
# Tool
|
# Tool
|
||||||
g = p.add_option_group('repo Version options')
|
g = p.add_option_group('repo Version options')
|
||||||
@ -137,6 +141,11 @@ to update the working directory files.
|
|||||||
if not m.Sync_NetworkHalf():
|
if not m.Sync_NetworkHalf():
|
||||||
r = m.GetRemote(m.remote.name)
|
r = m.GetRemote(m.remote.name)
|
||||||
print >>sys.stderr, 'fatal: cannot obtain manifest %s' % r.url
|
print >>sys.stderr, 'fatal: cannot obtain manifest %s' % r.url
|
||||||
|
|
||||||
|
# Better delete the manifest git dir if we created it; otherwise next
|
||||||
|
# time (when user fixes problems) we won't go through the "is_new" logic.
|
||||||
|
if is_new:
|
||||||
|
shutil.rmtree(m.gitdir)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
syncbuf = SyncBuffer(m.config)
|
syncbuf = SyncBuffer(m.config)
|
||||||
@ -226,6 +235,25 @@ to update the working directory files.
|
|||||||
if a in ('y', 'yes', 't', 'true', 'on'):
|
if a in ('y', 'yes', 't', 'true', 'on'):
|
||||||
gc.SetString('color.ui', 'auto')
|
gc.SetString('color.ui', 'auto')
|
||||||
|
|
||||||
|
def _ConfigureDepth(self, opt):
|
||||||
|
"""Configure the depth we'll sync down.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Options from optparse. We care about opt.depth.
|
||||||
|
"""
|
||||||
|
# Opt.depth will be non-None if user actually passed --depth to repo init.
|
||||||
|
if opt.depth is not None:
|
||||||
|
if opt.depth > 0:
|
||||||
|
# Positive values will set the depth.
|
||||||
|
depth = str(opt.depth)
|
||||||
|
else:
|
||||||
|
# Negative numbers will clear the depth; passing None to SetString
|
||||||
|
# will do that.
|
||||||
|
depth = None
|
||||||
|
|
||||||
|
# We store the depth in the main manifest project.
|
||||||
|
self.manifest.manifestProject.config.SetString('repo.depth', depth)
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
git_require(MIN_GIT_VERSION, fail=True)
|
git_require(MIN_GIT_VERSION, fail=True)
|
||||||
self._SyncManifest(opt)
|
self._SyncManifest(opt)
|
||||||
@ -235,6 +263,8 @@ to update the working directory files.
|
|||||||
self._ConfigureUser()
|
self._ConfigureUser()
|
||||||
self._ConfigureColor()
|
self._ConfigureColor()
|
||||||
|
|
||||||
|
self._ConfigureDepth(opt)
|
||||||
|
|
||||||
if self.manifest.IsMirror:
|
if self.manifest.IsMirror:
|
||||||
type = 'mirror '
|
type = 'mirror '
|
||||||
else:
|
else:
|
||||||
|
@ -15,6 +15,15 @@
|
|||||||
|
|
||||||
from command import PagedCommand
|
from command import PagedCommand
|
||||||
|
|
||||||
|
try:
|
||||||
|
import threading as _threading
|
||||||
|
except ImportError:
|
||||||
|
import dummy_threading as _threading
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
import StringIO
|
||||||
|
|
||||||
class Status(PagedCommand):
|
class Status(PagedCommand):
|
||||||
common = True
|
common = True
|
||||||
helpSummary = "Show the working tree status"
|
helpSummary = "Show the working tree status"
|
||||||
@ -27,6 +36,9 @@ and the most recent commit on this branch (HEAD), in each project
|
|||||||
specified. A summary is displayed, one line per file where there
|
specified. A summary is displayed, one line per file where there
|
||||||
is a difference between these three states.
|
is a difference between these three states.
|
||||||
|
|
||||||
|
The -j/--jobs option can be used to run multiple status queries
|
||||||
|
in parallel.
|
||||||
|
|
||||||
Status Display
|
Status Display
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -60,9 +72,34 @@ the following meanings:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def _Options(self, p):
|
||||||
|
p.add_option('-j', '--jobs',
|
||||||
|
dest='jobs', action='store', type='int', default=2,
|
||||||
|
help="number of projects to check simultaneously")
|
||||||
|
|
||||||
|
def _StatusHelper(self, project, clean_counter, sem, output):
|
||||||
|
"""Obtains the status for a specific project.
|
||||||
|
|
||||||
|
Obtains the status for a project, redirecting the output to
|
||||||
|
the specified object. It will release the semaphore
|
||||||
|
when done.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project: Project to get status of.
|
||||||
|
clean_counter: Counter for clean projects.
|
||||||
|
sem: Semaphore, will call release() when complete.
|
||||||
|
output: Where to output the status.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
state = project.PrintWorkTreeStatus(output)
|
||||||
|
if state == 'CLEAN':
|
||||||
|
clean_counter.next()
|
||||||
|
finally:
|
||||||
|
sem.release()
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
all = self.GetProjects(args)
|
all = self.GetProjects(args)
|
||||||
clean = 0
|
counter = itertools.count()
|
||||||
|
|
||||||
on = {}
|
on = {}
|
||||||
for project in all:
|
for project in all:
|
||||||
@ -77,9 +114,24 @@ the following meanings:
|
|||||||
for cb in branch_names:
|
for cb in branch_names:
|
||||||
print '# on branch %s' % cb
|
print '# on branch %s' % cb
|
||||||
|
|
||||||
for project in all:
|
if opt.jobs == 1:
|
||||||
state = project.PrintWorkTreeStatus()
|
for project in all:
|
||||||
if state == 'CLEAN':
|
state = project.PrintWorkTreeStatus()
|
||||||
clean += 1
|
if state == 'CLEAN':
|
||||||
if len(all) == clean:
|
counter.next()
|
||||||
|
else:
|
||||||
|
sem = _threading.Semaphore(opt.jobs)
|
||||||
|
threads_and_output = []
|
||||||
|
for project in all:
|
||||||
|
sem.acquire()
|
||||||
|
output = StringIO.StringIO()
|
||||||
|
t = _threading.Thread(target=self._StatusHelper,
|
||||||
|
args=(project, counter, sem, output))
|
||||||
|
threads_and_output.append((t, output))
|
||||||
|
t.start()
|
||||||
|
for (t, output) in threads_and_output:
|
||||||
|
t.join()
|
||||||
|
sys.stdout.write(output.getvalue())
|
||||||
|
output.close()
|
||||||
|
if len(all) == counter.next():
|
||||||
print 'nothing to commit (working directory clean)'
|
print 'nothing to commit (working directory clean)'
|
||||||
|
@ -164,31 +164,32 @@ later is required to fix a server side protocol bug.
|
|||||||
# - We always make sure we call sem.release().
|
# - We always make sure we call sem.release().
|
||||||
# - We always make sure we unlock the lock if we locked it.
|
# - We always make sure we unlock the lock if we locked it.
|
||||||
try:
|
try:
|
||||||
success = project.Sync_NetworkHalf(quiet=opt.quiet)
|
try:
|
||||||
|
success = project.Sync_NetworkHalf(quiet=opt.quiet)
|
||||||
|
|
||||||
# Lock around all the rest of the code, since printing, updating a set
|
# Lock around all the rest of the code, since printing, updating a set
|
||||||
# and Progress.update() are not thread safe.
|
# and Progress.update() are not thread safe.
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
did_lock = True
|
did_lock = True
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
print >>sys.stderr, 'error: Cannot fetch %s' % project.name
|
print >>sys.stderr, 'error: Cannot fetch %s' % project.name
|
||||||
if opt.force_broken:
|
if opt.force_broken:
|
||||||
print >>sys.stderr, 'warn: --force-broken, continuing to sync'
|
print >>sys.stderr, 'warn: --force-broken, continuing to sync'
|
||||||
else:
|
else:
|
||||||
raise _FetchError()
|
raise _FetchError()
|
||||||
|
|
||||||
fetched.add(project.gitdir)
|
fetched.add(project.gitdir)
|
||||||
pm.update()
|
pm.update()
|
||||||
except BaseException, e:
|
except BaseException, e:
|
||||||
# Notify the _Fetch() function about all errors.
|
# Notify the _Fetch() function about all errors.
|
||||||
err_event.set()
|
err_event.set()
|
||||||
|
|
||||||
# If we got our own _FetchError, we don't want a stack trace.
|
# If we got our own _FetchError, we don't want a stack trace.
|
||||||
# However, if we got something else (something in Sync_NetworkHalf?),
|
# However, if we got something else (something in Sync_NetworkHalf?),
|
||||||
# we'd like one (so re-raise after we've set err_event).
|
# we'd like one (so re-raise after we've set err_event).
|
||||||
if not isinstance(e, _FetchError):
|
if not isinstance(e, _FetchError):
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
if did_lock:
|
if did_lock:
|
||||||
lock.release()
|
lock.release()
|
||||||
@ -217,7 +218,7 @@ later is required to fix a server side protocol bug.
|
|||||||
for project in projects:
|
for project in projects:
|
||||||
# Check for any errors before starting any new threads.
|
# Check for any errors before starting any new threads.
|
||||||
# ...we'll let existing threads finish, though.
|
# ...we'll let existing threads finish, though.
|
||||||
if err_event.is_set():
|
if err_event.isSet():
|
||||||
break
|
break
|
||||||
|
|
||||||
sem.acquire()
|
sem.acquire()
|
||||||
@ -236,7 +237,7 @@ later is required to fix a server side protocol bug.
|
|||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
# If we saw an error, exit with code 1 so that other scripts can check.
|
# If we saw an error, exit with code 1 so that other scripts can check.
|
||||||
if err_event.is_set():
|
if err_event.isSet():
|
||||||
print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
|
print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -120,6 +120,9 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
p.add_option('--cc',
|
p.add_option('--cc',
|
||||||
type='string', action='append', dest='cc',
|
type='string', action='append', dest='cc',
|
||||||
help='Also send email to these email addresses.')
|
help='Also send email to these email addresses.')
|
||||||
|
p.add_option('--br',
|
||||||
|
type='string', action='store', dest='branch',
|
||||||
|
help='Branch to upload.')
|
||||||
|
|
||||||
# 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.
|
||||||
@ -336,9 +339,13 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
|||||||
pending = []
|
pending = []
|
||||||
reviewers = []
|
reviewers = []
|
||||||
cc = []
|
cc = []
|
||||||
|
branch = None
|
||||||
|
|
||||||
|
if opt.branch:
|
||||||
|
branch = opt.branch
|
||||||
|
|
||||||
for project in project_list:
|
for project in project_list:
|
||||||
avail = project.GetUploadableBranches()
|
avail = project.GetUploadableBranches(branch)
|
||||||
if avail:
|
if avail:
|
||||||
pending.append((project, avail))
|
pending.append((project, avail))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user