Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2418)

Unified Diff: deps2git.py

Issue 281183003: Eliminate redundant work and control parallelism. (Closed) Base URL: http://src.chromium.org/svn/trunk/tools/deps2git
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | git_tools.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: deps2git.py
diff --git a/deps2git.py b/deps2git.py
index f29e67c989715d640c65a38bb97abe9fcceba76a..2f64ba62fcb0fe1f4bdd33bf170bf95685abbfc6 100755
--- a/deps2git.py
+++ b/deps2git.py
@@ -6,6 +6,7 @@
"""Convert SVN based DEPS into .DEPS.git for use with NewGit."""
import collections
+from cStringIO import StringIO
import json
import optparse
import os
@@ -13,14 +14,29 @@ import Queue
import shutil
import subprocess
import sys
+import threading
import time
-from multiprocessing.pool import ThreadPool
-
import deps_utils
import git_tools
import svn_to_git_public
+try:
+ import git_cache
+except ImportError:
+ for p in os.environ['PATH'].split(os.pathsep):
+ if (os.path.basename(p) == 'depot_tools' and
+ os.path.exists(os.path.join(p, 'git_cache.py'))):
+ sys.path.append(p)
+ import git_cache
+
+Job = collections.namedtuple(
+ 'Job',
+ ['dep', 'git_url', 'dep_url', 'path', 'git_host', 'dep_rev', 'svn_branch'])
+
+ConversionResults = collections.namedtuple(
+ 'ConversionResults',
+ ['new_deps', 'deps_vars', 'bad_git_urls', 'bad_dep_urls', 'bad_git_hash'])
# This is copied from depot_tools/gclient.py
DEPS_OS_CHOICES = {
@@ -36,6 +52,7 @@ DEPS_OS_CHOICES = {
"android": "android",
}
+
def SplitScmUrl(url):
"""Given a repository, return a set containing the URL and the revision."""
url_split = url.split('@')
@@ -46,14 +63,15 @@ def SplitScmUrl(url):
return (scm_url, scm_rev)
-def SvnRevToGitHash(svn_rev, git_url, repos_path, workspace, dep_path,
- git_host, svn_branch_name=None, cache_dir=None):
+def SvnRevToGitHash(
+ svn_rev, git_url, repos_path, workspace, dep_path, git_host,
+ svn_branch_name=None, cache_dir=None, outbuf=None, shallow=None):
"""Convert a SVN revision to a Git commit id."""
git_repo = None
if git_url.startswith(git_host):
git_repo = git_url.replace(git_host, '')
else:
- raise Exception('Unknown git server %s, host %s' % (git_url, git_host))
+ raise RuntimeError('Unknown git server %s, host %s' % (git_url, git_host))
if repos_path is None and workspace is None and cache_dir is None:
# We're running without a repository directory (i.e. no -r option).
# We cannot actually find the commit id, but this mode is useful
@@ -64,11 +82,10 @@ def SvnRevToGitHash(svn_rev, git_url, repos_path, workspace, dep_path,
mirror = True
git_repo_path = os.path.join(repos_path, git_repo)
if not os.path.exists(git_repo_path) or not os.listdir(git_repo_path):
- git_tools.Clone(git_url, git_repo_path, mirror)
+ git_tools.Clone(git_url, git_repo_path, mirror, outbuf)
elif cache_dir:
- mirror = 'bare'
- git_tools.Clone(git_url, None, mirror, cache_dir=cache_dir)
- git_repo_path = git_tools.GetCacheRepoDir(git_url, cache_dir)
+ mirror = True
+ git_repo_path = git_tools.PopulateCache(git_url, shallow)
else:
mirror = False
git_repo_path = os.path.join(workspace, dep_path)
@@ -84,7 +101,7 @@ def SvnRevToGitHash(svn_rev, git_url, repos_path, workspace, dep_path,
else:
shutil.rmtree(git_repo_path)
if not os.path.exists(git_repo_path):
- git_tools.Clone(git_url, git_repo_path, mirror)
+ git_tools.Clone(git_url, git_repo_path, mirror, outbuf)
if svn_branch_name:
# svn branches are mirrored with:
@@ -102,110 +119,59 @@ def SvnRevToGitHash(svn_rev, git_url, repos_path, workspace, dep_path,
# Work-around for:
# http://code.google.com/p/chromium/issues/detail?id=362222
if (git_url.startswith('https://chromium.googlesource.com/external/pefile')
- and int(svn_rev) == 63):
+ and int(svn_rev) in (63, 141)):
return '1ceaa279daa62b71e3431e58f68be6a96dd1519a'
- try:
- return git_tools.Search(git_repo_path, svn_rev, mirror, refspec, git_url)
- except Exception:
- print >> sys.stderr, '%s <-> ERROR' % git_repo_path
- raise
+ return git_tools.Search(git_repo_path, svn_rev, mirror, refspec, git_url)
-def ConvertDepsToGit(deps, options, deps_vars, svn_to_git_objs):
- """Convert a 'deps' section in a DEPS file from SVN to Git."""
- new_deps = {}
- bad_git_urls = set([])
- bad_dep_urls = []
- bad_override = []
- bad_git_hash = []
- # Populate our deps list.
- deps_to_process = {}
- for dep, dep_url in deps.iteritems():
- if not dep_url: # dep is 'None' and emitted to exclude the dep
- new_deps[dep] = None
+def MessageMain(message_q, threads):
+ while True:
+ try:
+ msg = message_q.get(True, 10)
+ except Queue.Empty:
+ print >> sys.stderr, 'Still working on:'
+ for s in sorted([th.working_on for th in threads if th.working_on]):
+ print >> sys.stderr, ' %s' % s
continue
+ if msg is Queue.Empty:
+ return
+ if msg:
+ print >> sys.stderr, msg
- # Get the URL and the revision/hash for this dependency.
- dep_url, dep_rev = SplitScmUrl(deps[dep])
-
- path = dep
- git_url = dep_url
- svn_branch = None
- git_host = dep_url
-
- if not dep_url.endswith('.git'):
- # Convert this SVN URL to a Git URL.
- for svn_git_converter in svn_to_git_objs:
- converted_data = svn_git_converter.SvnUrlToGitUrl(dep, dep_url)
- if converted_data:
- path, git_url, git_host = converted_data[:3]
- if len(converted_data) > 3:
- svn_branch = converted_data[3]
- break
- else:
- # Make all match failures fatal to catch errors early. When a match is
- # found, we break out of the loop so the exception is not thrown.
- if options.no_fail_fast:
- bad_dep_urls.append(dep_url)
- continue
- raise Exception('No match found for %s' % dep_url)
-
- Job = collections.namedtuple('Job', ['git_url', 'dep_url', 'path',
- 'git_host', 'dep_rev', 'svn_branch'])
- deps_to_process[dep] = Job(
- git_url, dep_url, path, git_host, dep_rev, svn_branch)
- # Lets pre-cache all of the git repos now if we have cache_dir turned on.
- if options.cache_dir:
- if not os.path.isdir(options.cache_dir):
- os.makedirs(options.cache_dir)
- pool = ThreadPool(processes=len(deps_to_process))
- output_queue = Queue.Queue()
- num_threads = 0
- for git_url, _, _, _, _, _ in deps_to_process.itervalues():
- print 'Populating cache for %s' % git_url
- num_threads += 1
- pool.apply_async(git_tools.Clone, (git_url, None, 'bare',
- output_queue, options.cache_dir,
- options.shallow))
- pool.close()
-
- # Stream stdout line by line.
- sec_since = 0
- while num_threads > 0:
- try:
- line = output_queue.get(block=True, timeout=1)
- sec_since = 0
- except Queue.Empty:
- sec_since += 1
- line = ('Main> Heartbeat ping. We are still alive!! '
- 'Seconds since last output: %d sec' % sec_since)
- if line is None:
- num_threads -= 1
- else:
- print line
- pool.join()
+def ConvertDepMain(dep_q, message_q, options, results):
+ cur_thread = threading.current_thread()
+ while True:
+ try:
+ job = dep_q.get(False)
+ dep, git_url, dep_url, path, git_host, dep_rev, svn_branch = job
+ cur_thread.working_on = dep
+ except Queue.Empty:
+ cur_thread.working_on = None
+ return
+
+ outbuf = StringIO()
+ def _print(s):
+ for l in s.splitlines():
+ outbuf.write('[%s] %s\n' % (dep, l))
- for dep, items in deps_to_process.iteritems():
- git_url, dep_url, path, git_host, dep_rev, svn_branch = items
if options.verify:
delay = 0.5
success = False
for try_index in range(1, 6):
- print >> sys.stderr, 'checking %s (try #%d) ...' % (git_url, try_index),
+ _print('checking %s (try #%d) ...' % (git_url, try_index))
if git_tools.Ping(git_url, verbose=True):
- print >> sys.stderr, ' success'
+ _print(' success')
success = True
break
-
- print >> sys.stderr, ' failure'
- print >> sys.stderr, 'sleeping for %.01f seconds ...' % delay
+ _print(' failure')
+ _print('sleeping for %.01f seconds ...' % delay)
time.sleep(delay)
delay *= 2
if not success:
- bad_git_urls.update([git_url])
+ results.bad_git_urls.add(git_url)
# Get the Git hash based off the SVN rev.
git_hash = ''
@@ -221,13 +187,13 @@ def ConvertDepsToGit(deps, options, deps_vars, svn_to_git_objs):
git_host, svn_branch, options.cache_dir)
except Exception as e:
if options.no_fail_fast:
- bad_git_hash.append(e)
+ results.bad_git_hash.append(e)
continue
raise
# If this is webkit, we need to add the var for the hash.
if dep == 'src/third_party/WebKit' and dep_rev:
- deps_vars['webkit_rev'] = git_hash
+ results.deps_vars['webkit_rev'] = git_hash
git_hash = 'VAR_WEBKIT_REV'
# Hack to preserve the angle_revision variable in .DEPS.git.
@@ -235,13 +201,78 @@ def ConvertDepsToGit(deps, options, deps_vars, svn_to_git_objs):
if dep == 'src/third_party/angle' and git_hash:
# Cut the leading '@' so this variable has the same semantics in
# DEPS and .DEPS.git.
- deps_vars['angle_revision'] = git_hash[1:]
+ results.deps_vars['angle_revision'] = git_hash[1:]
git_hash = 'VAR_ANGLE_REVISION'
# Add this Git dep to the new deps.
- new_deps[path] = '%s%s' % (git_url, git_hash)
+ results.new_deps[path] = '%s%s' % (git_url, git_hash)
- return new_deps, bad_git_urls, bad_dep_urls, bad_override, bad_git_hash
+ message_q.put(outbuf.getvalue())
+
+
+def ConvertDepsToGit(deps, options, deps_vars, svn_to_git_objs):
+ """Convert a 'deps' section in a DEPS file from SVN to Git."""
+ results = ConversionResults(
+ new_deps={},
+ deps_vars=deps_vars,
+ bad_git_urls=set([]),
+ bad_dep_urls=[],
+ bad_git_hash=[]
+ )
+
+ # Populate our deps list.
+ deps_to_process = Queue.Queue()
+ for dep, dep_url in deps.iteritems():
+ if not dep_url: # dep is 'None' and emitted to exclude the dep
+ results.new_deps[dep] = None
+ continue
+
+ # Get the URL and the revision/hash for this dependency.
+ dep_url, dep_rev = SplitScmUrl(deps[dep])
+
+ path = dep
+ git_url = dep_url
+ svn_branch = None
+ git_host = dep_url
+
+ if not dep_url.endswith('.git'):
+ # Convert this SVN URL to a Git URL.
+ for svn_git_converter in svn_to_git_objs:
+ converted_data = svn_git_converter.SvnUrlToGitUrl(dep, dep_url)
+ if converted_data:
+ path, git_url, git_host = converted_data[:3]
+ if len(converted_data) > 3:
+ svn_branch = converted_data[3]
+ break
+ else:
+ # Make all match failures fatal to catch errors early. When a match is
+ # found, we break out of the loop so the exception is not thrown.
+ if options.no_fail_fast:
+ results.bad_dep_urls.append(dep_url)
+ continue
+ raise RuntimeError('No match found for %s' % dep_url)
+
+ deps_to_process.put(
+ Job(dep, git_url, dep_url, path, git_host, dep_rev, svn_branch))
+
+ threads = []
+ message_q = Queue.Queue()
+ thread_args = (deps_to_process, message_q, options, results)
+ num_threads = options.num_threads or deps_to_process.qsize()
+ for _ in xrange(num_threads):
+ th = threading.Thread(target=ConvertDepMain, args=thread_args)
+ th.working_on = None
+ th.start()
+ threads.append(th)
+ message_th = threading.Thread(target=MessageMain, args=(message_q, threads))
+ message_th.start()
+
+ for th in threads:
+ th.join()
+ message_q.put(Queue.Empty)
+ message_th.join()
+
+ return results
def main():
@@ -250,6 +281,8 @@ def main():
help='path to the DEPS file to convert')
parser.add_option('-o', '--out',
help='path to the converted DEPS file (default: stdout)')
+ parser.add_option('-j', '--num-threads', type='int', default=4,
+ help='Maximum number of threads')
parser.add_option('-t', '--type',
help='[DEPRECATED] type of DEPS file (public, etc)')
parser.add_option('-x', '--extra-rules',
@@ -290,7 +323,7 @@ def main():
options.cache_dir = os.path.abspath(options.cache_dir)
if options.extra_rules and not os.path.exists(options.extra_rules):
- raise Exception('Can\'t locate rules file "%s".' % options.extra_rules)
+ raise RuntimeError('Can\'t locate rules file "%s".' % options.extra_rules)
# Create a var containing the Git and Webkit URL, this will make it easy for
# people to use a mirror instead.
@@ -332,6 +365,14 @@ def main():
if not options.cache_dir and 'cache_dir' in gclient_dict:
options.cache_dir = os.path.abspath(gclient_dict['cache_dir'])
+ if options.cache_dir:
+ git_cache.Mirror.SetCachePath(options.cache_dir)
+ else:
+ try:
+ options.cache_dir = git_cache.Mirror.GetCachePath()
+ except RuntimeError:
+ pass
+
# Do general pre-processing of the DEPS data.
for svn_git_converter in svn_to_git_objs:
if hasattr(svn_git_converter, 'CleanDeps'):
@@ -339,44 +380,39 @@ def main():
skip_child_includes, hooks)
# Convert the DEPS file to Git.
- deps, baddeps, badmaps, badvars, badhashes = ConvertDepsToGit(
+ results = ConvertDepsToGit(
deps, options, deps_vars, svn_to_git_objs)
for os_dep in deps_os:
- result = ConvertDepsToGit(deps_os[os_dep], options, deps_vars,
- svn_to_git_objs)
- deps_os[os_dep] = result[0]
- baddeps = baddeps.union(result[1])
- badmaps.extend(result[2])
- badvars.extend(result[3])
- badhashes.extend(result[4])
+ os_results = ConvertDepsToGit(deps_os[os_dep], options, deps_vars,
+ svn_to_git_objs)
+ deps_os[os_dep] = os_results.new_deps
+ results.bad_git_urls.update(os_results.bad_git_urls)
+ results.bad_dep_urls.extend(os_results.bad_dep_urls)
+ results.bad_git_hash.extend(os_results.bad_git_hash)
if options.json:
with open(options.json, 'w') as f:
- json.dump(list(baddeps), f, sort_keys=True, indent=2)
+ json.dump(list(results.bad_git_urls), f, sort_keys=True, indent=2)
- if baddeps:
+ if results.bad_git_urls:
print >> sys.stderr, ('\nUnable to resolve the following repositories. '
'Please make sure\nthat any svn URLs have a git mirror associated with '
'them.\nTo see the exact error, run `git ls-remote [repository]` where'
'\n[repository] is the URL ending in .git (strip off the @revision\n'
'number.) For more information, visit http://code.google.com\n'
'/p/chromium/wiki/UsingGit#Adding_new_repositories_to_DEPS.\n')
- for dep in baddeps:
+ for dep in results.bad_git_urls:
print >> sys.stderr, ' ' + dep
- if badmaps:
+ if results.bad_dep_urls:
print >> sys.stderr, '\nNo mappings found for the following urls:\n'
- for bad in badmaps:
- print >> sys.stderr, ' ' + bad
- if badvars:
- print >> sys.stderr, '\nMissing DEPS variables for overrides:\n'
- for bad in badvars:
+ for bad in results.bad_dep_urls:
print >> sys.stderr, ' ' + bad
- if badhashes:
+ if results.bad_git_hash:
print >> sys.stderr, '\nsvn rev to git hash failures:\n'
- for bad in badhashes:
+ for bad in results.bad_git_hash:
print >> sys.stderr, ' ' + str(bad)
- if baddeps or badmaps or badvars or badhashes:
+ if (results.bad_git_urls or results.bad_dep_urls or results.bad_git_hash):
return 2
if options.verify:
@@ -385,8 +421,8 @@ def main():
return 0
# Write the DEPS file to disk.
- deps_utils.WriteDeps(options.out, deps_vars, deps, deps_os, include_rules,
- skip_child_includes, hooks)
+ deps_utils.WriteDeps(options.out, deps_vars, results.new_deps, deps_os,
+ include_rules, skip_child_includes, hooks)
return 0
« no previous file with comments | « no previous file | git_tools.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698