flatcar-scripts/make_relative_solution

208 lines
5.2 KiB
Python
Executable File

#!/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)