Compare commits

...

4 Commits

Author SHA1 Message Date
e6a0eeb80d sync: Fix syntax error on Python 2.4
Change-Id: I371d032d5a1ddde137721cbe2b24bfa38f20aaaa
Signed-off-by: Shawn O. Pearce <sop@google.com>
2011-03-22 19:04:47 -07:00
0960b5b53d Creating rr-cache
If git-rerere is enabled, it uses the rr-cache directory that
repo currently creates a symlink from, but doesn't create the
destination directory (inside the project's directory). Git
will then complain during merges and rebases.

This commit creates the rr-cache directory inside the project.

Change-Id: If8b57a04f022fc6ed6a7007d05aa2e876e6611ee
2011-03-17 09:19:51 -07:00
fc06ced9f9 Make 'repo sync -jN' exit with an error code in the case of sync errors.
The bug that this is fixing is described here:

http://code.google.com/p/chromium-os/issues/detail?id=6813

This fix allows the helper threads to signal the main thread that they
saw an error.  When the main thread sees the error, it will let all
existing threads finish, then exit with an error.

Change-Id: If3019bc6b0b3ab9304d49ed2eea53e9d57f3095a
2011-03-17 09:17:42 -07:00
fce89f218a Add 'list' command to repo.
This isn't a required command, but might be more discoverable for
repo newbies?

Change-Id: If357346f234774d42e04e024e65acdaf6dca6c62
2011-03-16 12:55:44 -07:00
3 changed files with 124 additions and 14 deletions

View File

@ -1547,6 +1547,11 @@ class Project(object):
cmd.append(HEAD) cmd.append(HEAD)
if GitCommand(self, cmd).Wait() != 0: if GitCommand(self, cmd).Wait() != 0:
raise GitError("cannot initialize work tree") raise GitError("cannot initialize work tree")
rr_cache = os.path.join(self.gitdir, 'rr-cache')
if not os.path.exists(rr_cache):
os.makedirs(rr_cache)
self._CopyFiles() self._CopyFiles()
def _gitdir_path(self, path): def _gitdir_path(self, path):

48
subcmds/list.py Normal file
View File

@ -0,0 +1,48 @@
#
# Copyright (C) 2011 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 command import Command, MirrorSafeCommand
class List(Command, MirrorSafeCommand):
common = True
helpSummary = "List projects and their associated directories"
helpUsage = """
%prog [<project>...]
"""
helpDescription = """
List all projects; pass '.' to list the project for the cwd.
This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
"""
def Execute(self, opt, args):
"""List all projects and the associated directories.
This may be possible to do with 'repo forall', but repo newbies have
trouble figuring that out. The idea here is that it should be more
discoverable.
Args:
opt: The options. We don't take any.
args: Positional args. Can be a list of projects to list, or empty.
"""
projects = self.GetProjects(args)
lines = []
for project in projects:
lines.append("%s : %s" % (project.relpath, project.name))
lines.sort()
print '\n'.join(lines)

View File

@ -39,6 +39,10 @@ from project import R_HEADS
from project import SyncBuffer from project import SyncBuffer
from progress import Progress from progress import Progress
class _FetchError(Exception):
"""Internal error thrown in _FetchHelper() when we don't want stack trace."""
pass
class Sync(Command, MirrorSafeCommand): class Sync(Command, MirrorSafeCommand):
jobs = 1 jobs = 1
common = True common = True
@ -135,18 +139,59 @@ later is required to fix a server side protocol bug.
dest='repo_upgraded', action='store_true', dest='repo_upgraded', action='store_true',
help=SUPPRESS_HELP) help=SUPPRESS_HELP)
def _FetchHelper(self, opt, project, lock, fetched, pm, sem): def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event):
if not project.Sync_NetworkHalf(quiet=opt.quiet): """Main function of the fetch threads when jobs are > 1.
Args:
opt: Program options returned from optparse. See _Options().
project: Project object for the project to fetch.
lock: Lock for accessing objects that are shared amongst multiple
_FetchHelper() threads.
fetched: set object that we will add project.gitdir to when we're done
(with our lock held).
pm: Instance of a Project object. We will call pm.update() (with our
lock held).
sem: We'll release() this semaphore when we exit so that another thread
can be started up.
err_event: We'll set this event in the case of an error (after printing
out info about the error).
"""
# We'll set to true once we've locked the lock.
did_lock = False
# Encapsulate everything in a try/except/finally so that:
# - We always set err_event in the case of an exception.
# - We always make sure we call sem.release().
# - We always make sure we unlock the lock if we locked it.
try:
try:
success = project.Sync_NetworkHalf(quiet=opt.quiet)
# Lock around all the rest of the code, since printing, updating a set
# and Progress.update() are not thread safe.
lock.acquire()
did_lock = True
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:
sem.release() raise _FetchError()
sys.exit(1)
lock.acquire()
fetched.add(project.gitdir) fetched.add(project.gitdir)
pm.update() pm.update()
except BaseException, e:
# Notify the _Fetch() function about all errors.
err_event.set()
# If we got our own _FetchError, we don't want a stack trace.
# However, if we got something else (something in Sync_NetworkHalf?),
# we'd like one (so re-raise after we've set err_event).
if not isinstance(e, _FetchError):
raise
finally:
if did_lock:
lock.release() lock.release()
sem.release() sem.release()
@ -169,7 +214,13 @@ later is required to fix a server side protocol bug.
threads = set() threads = set()
lock = _threading.Lock() lock = _threading.Lock()
sem = _threading.Semaphore(self.jobs) sem = _threading.Semaphore(self.jobs)
err_event = _threading.Event()
for project in projects: for project in projects:
# Check for any errors before starting any new threads.
# ...we'll let existing threads finish, though.
if err_event.is_set():
break
sem.acquire() sem.acquire()
t = _threading.Thread(target = self._FetchHelper, t = _threading.Thread(target = self._FetchHelper,
args = (opt, args = (opt,
@ -177,13 +228,19 @@ later is required to fix a server side protocol bug.
lock, lock,
fetched, fetched,
pm, pm,
sem)) sem,
err_event))
threads.add(t) threads.add(t)
t.start() t.start()
for t in threads: for t in threads:
t.join() t.join()
# If we saw an error, exit with code 1 so that other scripts can check.
if err_event.is_set():
print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
sys.exit(1)
pm.end() pm.end()
for project in projects: for project in projects:
project.bare_git.gc('--auto') project.bare_git.gc('--auto')