mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-08 13:36:58 +02:00
208 lines
5.2 KiB
Python
Executable File
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)
|