Commit e3da35f6 authored by maruel@chromium.org's avatar maruel@chromium.org

Add a --snapshot option for revinfo. If set, revinfo prints a .gclient file

set to sync to the current revisions/hashes on disk

Add a --gclientfile=FILENAME option.  If set, gclient loads FILENAME
rather than .gclient for configuration info.

Patch contributed by jneddo@nvidia.com

BUG=1658
TEST=Verify that --snapshot prints a valid configuration file
     Verify that when --gclientfile is set the correct file is used
     Verify that gclient sync --gclientfile sets the correct revisions

Review URL: http://codereview.chromium.org/672004

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@41078 0039d316-1c4b-4281-b951-d872f2087c98
parent 83b6e4ba
......@@ -279,6 +279,32 @@ solutions = [
]
""")
DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\
{ "name" : "%(solution_name)s",
"url" : "%(solution_url)s",
"custom_deps" : {
%(solution_deps)s,
},
"safesync_url": "%(safesync_url)s"
},
""")
DEFAULT_SNAPSHOT_FILE_TEXT = ("""\
# An element of this array (a "solution") describes a repository directory
# that will be checked out into your working copy. Each solution may
# optionally define additional dependencies (via its DEPS file) to be
# checked out alongside the solution's directory. A solution may also
# specify custom dependencies (via the "custom_deps" property) that
# override or augment the dependencies specified by the DEPS file.
# If a "safesync_url" is specified, it is assumed to reference the location of
# a text file which contains nothing but the last known good SCM revision to
# sync against. It is fetched if specified and used unless --head is passed
solutions = [
%(solution_list)s
]
""")
## GClient implementation.
......@@ -801,9 +827,6 @@ class GClient(object):
if not solutions:
raise gclient_utils.Error("No solution specified")
entries = {}
entries_deps_content = {}
# Inner helper to generate base url and rev tuple (including honoring
# |revision_overrides|)
def GetURLAndRev(name, original_url):
......@@ -820,13 +843,21 @@ class GClient(object):
else:
return (url, revision)
# text of the snapshot gclient file
new_gclient = ""
# Dictionary of { path : SCM url } to ensure no duplicate solutions
solution_names = {}
# Run on the base solutions first.
for solution in solutions:
# Dictionary of { path : SCM url } to describe the gclient checkout
entries = {}
entries_deps_content = {}
name = solution["name"]
if name in entries:
if name in solution_names:
raise gclient_utils.Error("solution %s specified more than once" % name)
(url, rev) = GetURLAndRev(name, solution["url"])
entries[name] = "%s@%s" % (url, rev)
solution_names[name] = "%s@%s" % (url, rev)
deps_file = solution.get("deps_file", self._options.deps_file)
if '/' in deps_file or '\\' in deps_file:
raise gclient_utils.Error('deps_file name must not be a path, just a '
......@@ -840,33 +871,55 @@ class GClient(object):
deps_content = ""
entries_deps_content[name] = deps_content
# Process the dependencies next (sort alphanumerically to ensure that
# containing directories get populated first and for readability)
deps = self._ParseAllDeps(entries, entries_deps_content)
deps_to_process = deps.keys()
deps_to_process.sort()
# First pass for direct dependencies.
for d in deps_to_process:
if type(deps[d]) == str:
(url, rev) = GetURLAndRev(d, deps[d])
entries[d] = "%s@%s" % (url, rev)
# Process the dependencies next (sort alphanumerically to ensure that
# containing directories get populated first and for readability)
deps = self._ParseAllDeps(entries, entries_deps_content)
deps_to_process = deps.keys()
deps_to_process.sort()
# First pass for direct dependencies.
for d in deps_to_process:
if type(deps[d]) == str:
(url, rev) = GetURLAndRev(d, deps[d])
entries[d] = "%s@%s" % (url, rev)
# Second pass for inherited deps (via the From keyword)
for d in deps_to_process:
if type(deps[d]) != str:
deps_parent_url = entries[deps[d].module_name]
if deps_parent_url.find("@") < 0:
raise gclient_utils.Error("From %s missing revisioned url" %
deps[d].module_name)
content = gclient_utils.FileRead(os.path.join(
self._root_dir,
deps[d].module_name,
self._options.deps_file))
sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {})
(url, rev) = GetURLAndRev(d, sub_deps[d])
entries[d] = "%s@%s" % (url, rev)
# Build the snapshot configuration string
if self._options.snapshot:
url = entries.pop(name)
custom_deps = ",\n ".join(["\"%s\": \"%s\"" % (x, entries[x])
for x in sorted(entries.keys())])
new_gclient += DEFAULT_SNAPSHOT_SOLUTION_TEXT % {
'solution_name': name,
'solution_url': url,
'safesync_url' : "",
'solution_deps': custom_deps,
}
else:
print(";\n".join(["%s: %s" % (x, entries[x])
for x in sorted(entries.keys())]))
# Second pass for inherited deps (via the From keyword)
for d in deps_to_process:
if type(deps[d]) != str:
deps_parent_url = entries[deps[d].module_name]
if deps_parent_url.find("@") < 0:
raise gclient_utils.Error("From %s missing revisioned url" %
deps[d].module_name)
content = gclient_utils.FileRead(os.path.join(self._root_dir,
deps[d].module_name,
self._options.deps_file))
sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {})
(url, rev) = GetURLAndRev(d, sub_deps[d])
entries[d] = "%s@%s" % (url, rev)
print(";\n".join(["%s: %s" % (x, entries[x])
for x in sorted(entries.keys())]))
# Print the snapshot configuration file
if self._options.snapshot:
config = DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}
snapclient = GClient(self._root_dir, self._options)
snapclient.SetConfig(config)
print(snapclient._config_content)
## gclient commands.
......@@ -1151,6 +1204,12 @@ def Main(argv):
action="store_true", default=False,
help=("on update, delete any unexpected "
"unversioned trees that are in the checkout"))
option_parser.add_option("", "--snapshot", action="store_true", default=False,
help=("(revinfo only), create a snapshot file "
"of the current version of all repositories"))
option_parser.add_option("", "--gclientfile", default=None,
metavar="FILENAME",
help=("specify an alternate .gclient file"))
if len(argv) < 2:
# Users don't need to be told to use the 'help' command.
......@@ -1177,7 +1236,9 @@ def Main(argv):
# Files used for configuration and state saving.
options.config_filename = os.environ.get("GCLIENT_FILE", ".gclient")
options.entries_filename = ".gclient_entries"
if options.gclientfile:
options.config_filename = options.gclientfile
options.entries_filename = options.config_filename + "_entries"
options.deps_file = "DEPS"
options.platform = sys.platform
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment