| Index: src/scripts/make_relative_solution
|
| diff --git a/src/scripts/make_relative_solution b/src/scripts/make_relative_solution
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..d12159e1b247cd2dfc46ae05959b526aae8d6c7b
|
| --- /dev/null
|
| +++ b/src/scripts/make_relative_solution
|
| @@ -0,0 +1,207 @@
|
| +#!/usr/bin/python
|
| +#
|
| +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Generates a pinned solutions file with relative git repository URLs.
|
| +
|
| +make_relative_solution reads a pinned solution file generated by
|
| +'gclient revinfo --snapshot' and writes to stdout a pinned solution file
|
| +with relative git repository URLs.
|
| +
|
| +
|
| +The resulting solution file can be used to check out a fixed version of
|
| +a gclient set of repositories. The base URL to fetch from can be changed
|
| +by editing one line in the generated solution file.
|
| +"""
|
| +
|
| +import optparse
|
| +import sys
|
| +
|
| +
|
| +def ReadSnapshot(filename):
|
| + """Reads a gclient revinfo snapshot file.
|
| +
|
| + Minimal verification of the structure of the file is performed.
|
| +
|
| + Args:
|
| + filename: The name of a snapshot file to read.
|
| +
|
| + Returns:
|
| + The solutions array parsed from the snapshot file.
|
| + """
|
| +
|
| + env = {}
|
| + execfile(filename, env)
|
| +
|
| + assert 'solutions' in env
|
| + assert env['solutions']
|
| +
|
| + return env['solutions']
|
| +
|
| +
|
| +def BaseRepository(url):
|
| + """Finds the base repository path.
|
| +
|
| + This only works if the top level repository is not in a subdirectory relative
|
| + to the other repositories on the server.
|
| +
|
| + Args:
|
| + url: git repository url
|
| +
|
| + Returns:
|
| + The prefix of the URL that does not contain the repository name and SHA.
|
| + """
|
| +
|
| + base, versioned_repository = url.rsplit('/', 1)
|
| +
|
| + assert base and versioned_repository
|
| + return base
|
| +
|
| +
|
| +def WriteBaseURL(base, solution):
|
| + print ' "%s": "%s",' % (solution['name'], base)
|
| +
|
| +
|
| +def IsRelativeRepository(base, url):
|
| + return url.startswith(base)
|
| +
|
| +
|
| +def RelativeRepository(base, url):
|
| + if IsRelativeRepository(base, url):
|
| + return url[len(base):]
|
| + else:
|
| + return url
|
| +
|
| +
|
| +def RelativeDep(base, dep):
|
| + path, repository = dep
|
| +
|
| + return (path,
|
| + RelativeRepository(base, repository),
|
| + IsRelativeRepository(base, repository))
|
| +
|
| +
|
| +def RelativeDeps(base, solution):
|
| + return [RelativeDep(base, dep) for dep in solution['custom_deps'].items()]
|
| +
|
| +
|
| +def WritePinnedDep(name, dep, indent):
|
| + """Writes a pinned dep.
|
| +
|
| + The output is indented so that the URLs all line up for ease of reading. If
|
| + the dep is for a relative git repository then we emit the base_url lookup as
|
| + well.
|
| +
|
| + Args:
|
| + name: The name of the solution that is being written out.
|
| + dep: The relative dep that is to be written out.
|
| + indent: The total number of characters to use for the path component.
|
| +
|
| + Returns:
|
| + Nothing
|
| + """
|
| +
|
| + path, repository, relative = dep
|
| + remainder = path.partition('/')[2]
|
| + spaces = indent - len(path)
|
| +
|
| + if remainder == 'deps':
|
| + return
|
| +
|
| + if relative:
|
| + print ' "%s": %*sbase_url["%s"] + "%s",' % (path,
|
| + spaces, '',
|
| + name,
|
| + repository)
|
| + else:
|
| + print ' "%s": %*s"%s",' % (path,
|
| + spaces, '',
|
| + repository)
|
| +
|
| +
|
| +def WritePinnedSolution(solution):
|
| + """Writes out a pinned and solution file with relative repository paths.
|
| +
|
| + The relative repository paths make it easier for a user to modify where
|
| + they are pulling source from.
|
| +
|
| + Args:
|
| + solution: gclient solution object.
|
| +
|
| + Returns:
|
| + Nothing
|
| + """
|
| +
|
| + base = BaseRepository(solution['url'])
|
| + url = RelativeRepository(base, solution['url'])
|
| + deps = RelativeDeps(base, solution)
|
| + indent = max(len(dep[0]) for dep in deps)
|
| +
|
| + deps.sort(key=lambda dep: dep[1])
|
| +
|
| + print (' { "name" : "%s",\n'
|
| + ' "url" : base_url["%s"] + "%s",\n'
|
| + ' "custom_deps" : {') % (solution['name'],
|
| + solution['name'],
|
| + url)
|
| +
|
| + for dep in deps:
|
| + WritePinnedDep(solution['name'], dep, indent)
|
| +
|
| + print (' },\n'
|
| + ' },')
|
| +
|
| +
|
| +def main(argv):
|
| + usage = 'Usage: %prog [options] filename'
|
| + option_parser = optparse.OptionParser(usage=usage)
|
| + option_parser.disable_interspersed_args()
|
| + option_parser.add_option('-s', '--substitute',
|
| + action='store_true',
|
| + dest='substitute',
|
| + default=False,
|
| + help='substitute a new base git URL')
|
| + option_parser.add_option('-b', '--base',
|
| + dest='base',
|
| + default='http://src.chromium.org/git',
|
| + metavar='URL',
|
| + help='base git URL to substitute [%default]')
|
| +
|
| + options, args = option_parser.parse_args(argv[1:])
|
| +
|
| + if len(args) != 1:
|
| + option_parser.print_help()
|
| + return 1
|
| +
|
| + filename = args.pop(0)
|
| + solutions = ReadSnapshot(filename)
|
| +
|
| + print ('#\n'
|
| + '# Autogenerated pinned gclient solution file. This file was\n'
|
| + '# created by running make_relative_solution.\n'
|
| + '#\n'
|
| + '\n'
|
| + 'base_url = {')
|
| +
|
| + for solution in solutions:
|
| + if options.substitute:
|
| + base = options.base
|
| + else:
|
| + base = BaseRepository(solution['url'])
|
| +
|
| + WriteBaseURL(base, solution)
|
| +
|
| + print ('}\n'
|
| + '\n'
|
| + 'solutions = [')
|
| +
|
| + for solution in solutions:
|
| + WritePinnedSolution(solution)
|
| +
|
| + print ']\n'
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + main(sys.argv)
|
|
|