mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 18:51:29 +00:00
Allow blocking git-cache update with a timeout.
I guess I'm the only developer using git-cache, which is sad. Hopefully these fixes will make it easier to adapt this to developer usage some time in the FUTURE. BUG=583420 TEST=Works for me R=agable@chromium.org,tandrii@chromium.org Review URL: https://codereview.chromium.org/1650993005 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@298531 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@@ -2049,6 +2049,9 @@ def CMDsync(parser, args):
|
||||
help='Don\'t bootstrap from Google Storage.')
|
||||
parser.add_option('--ignore_locks', action='store_true',
|
||||
help='GIT ONLY - Ignore cache locks.')
|
||||
parser.add_option('--lock_timeout', type='int', default=0,
|
||||
help='GIT ONLY - Deadline (in seconds) to wait for git '
|
||||
'cache lock to become available.')
|
||||
(options, args) = parser.parse_args(args)
|
||||
client = GClient.LoadCurrentConfig(options)
|
||||
|
||||
|
||||
@@ -871,7 +871,8 @@ class GitWrapper(SCMWrapper):
|
||||
mirror.populate(verbose=options.verbose,
|
||||
bootstrap=not getattr(options, 'no_bootstrap', False),
|
||||
depth=depth,
|
||||
ignore_lock=getattr(options, 'ignore_locks', False))
|
||||
ignore_lock=getattr(options, 'ignore_locks', False),
|
||||
lock_timeout=getattr(options, 'lock_timeout', 0))
|
||||
mirror.unlock()
|
||||
|
||||
def _Clone(self, revision, url, options):
|
||||
|
||||
44
git_cache.py
44
git_cache.py
@@ -44,8 +44,9 @@ class RefsHeadsFailedToFetch(Exception):
|
||||
class Lockfile(object):
|
||||
"""Class to represent a cross-platform process-specific lockfile."""
|
||||
|
||||
def __init__(self, path):
|
||||
def __init__(self, path, timeout=0):
|
||||
self.path = os.path.abspath(path)
|
||||
self.timeout = timeout
|
||||
self.lockfile = self.path + ".lock"
|
||||
self.pid = os.getpid()
|
||||
|
||||
@@ -91,16 +92,26 @@ class Lockfile(object):
|
||||
def lock(self):
|
||||
"""Acquire the lock.
|
||||
|
||||
Note: This is a NON-BLOCKING FAIL-FAST operation.
|
||||
Do. Or do not. There is no try.
|
||||
This will block with a deadline of self.timeout seconds.
|
||||
If self.timeout is zero, this is a NON-BLOCKING FAIL-FAST operation.
|
||||
"""
|
||||
try:
|
||||
self._make_lockfile()
|
||||
except OSError as e:
|
||||
if e.errno == errno.EEXIST:
|
||||
raise LockError("%s is already locked" % self.path)
|
||||
else:
|
||||
raise LockError("Failed to create %s (err %s)" % (self.path, e.errno))
|
||||
elapsed = 0
|
||||
while True:
|
||||
try:
|
||||
self._make_lockfile()
|
||||
return
|
||||
except OSError as e:
|
||||
if elapsed < self.timeout:
|
||||
sleep_time = min(3, self.timeout - elapsed)
|
||||
logging.info('Could not create git cache lockfile; '
|
||||
'will retry after sleep(%d).', sleep_time);
|
||||
elapsed += sleep_time
|
||||
time.sleep(sleep_time)
|
||||
continue
|
||||
if e.errno == errno.EEXIST:
|
||||
raise LockError("%s is already locked" % self.path)
|
||||
else:
|
||||
raise LockError("Failed to create %s (err %s)" % (self.path, e.errno))
|
||||
|
||||
def unlock(self):
|
||||
"""Release the lock."""
|
||||
@@ -401,13 +412,13 @@ class Mirror(object):
|
||||
logging.warn('Fetch of %s failed' % spec)
|
||||
|
||||
def populate(self, depth=None, shallow=False, bootstrap=False,
|
||||
verbose=False, ignore_lock=False):
|
||||
verbose=False, ignore_lock=False, lock_timeout=0):
|
||||
assert self.GetCachePath()
|
||||
if shallow and not depth:
|
||||
depth = 10000
|
||||
gclient_utils.safe_makedirs(self.GetCachePath())
|
||||
|
||||
lockfile = Lockfile(self.mirror_path)
|
||||
lockfile = Lockfile(self.mirror_path, lock_timeout)
|
||||
if not ignore_lock:
|
||||
lockfile.lock()
|
||||
|
||||
@@ -582,6 +593,7 @@ def CMDpopulate(parser, args):
|
||||
'shallow': options.shallow,
|
||||
'bootstrap': not options.no_bootstrap,
|
||||
'ignore_lock': options.ignore_locks,
|
||||
'lock_timeout': options.timeout,
|
||||
}
|
||||
if options.depth:
|
||||
kwargs['depth'] = options.depth
|
||||
@@ -625,7 +637,8 @@ def CMDfetch(parser, args):
|
||||
git_dir = os.path.abspath(git_dir)
|
||||
if git_dir.startswith(cachepath):
|
||||
mirror = Mirror.FromPath(git_dir)
|
||||
mirror.populate(bootstrap=not options.no_bootstrap)
|
||||
mirror.populate(
|
||||
bootstrap=not options.no_bootstrap, lock_timeout=options.timeout)
|
||||
return 0
|
||||
for remote in remotes:
|
||||
remote_url = subprocess.check_output(
|
||||
@@ -634,7 +647,8 @@ def CMDfetch(parser, args):
|
||||
mirror = Mirror.FromPath(remote_url)
|
||||
mirror.print = lambda *args: None
|
||||
print('Updating git cache...')
|
||||
mirror.populate(bootstrap=not options.no_bootstrap)
|
||||
mirror.populate(
|
||||
bootstrap=not options.no_bootstrap, lock_timeout=options.timeout)
|
||||
subprocess.check_call([Mirror.git_exe, 'fetch', remote])
|
||||
return 0
|
||||
|
||||
@@ -683,6 +697,8 @@ class OptionParser(optparse.OptionParser):
|
||||
help='Increase verbosity (can be passed multiple times)')
|
||||
self.add_option('-q', '--quiet', action='store_true',
|
||||
help='Suppress all extraneous output')
|
||||
self.add_option('--timeout', type='int', default=0,
|
||||
help='Timeout for acquiring cache lock, in seconds')
|
||||
|
||||
def parse_args(self, args=None, values=None):
|
||||
options, args = optparse.OptionParser.parse_args(self, args, values)
|
||||
|
||||
Reference in New Issue
Block a user