3 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """A tool that updates remotes in all historical manifests to point to GoB.
9 It clones manifest-versions repository, scans through all manifests there and
10 replaces known old gerrit/gerrit-int URLs with Gerrit on Borg ones.
12 It doesn't commit or push any changes, just updates files in a working
19 from xml.etree import ElementTree
21 from chromite.buildbot import cbuildbot_config
22 from chromite.buildbot import manifest_version
23 from chromite.lib import commandline
24 from chromite.lib import cros_build_lib
25 from chromite.lib import osutils
28 GOB_EXTERNAL = "https://chromium.googlesource.com"
29 GOB_INTERNAL = "https://chrome-internal.googlesource.com"
32 GERRIT_EXTERNAL = "https://chromium-review.googlesource.com"
33 GERRIT_INTERNAL = "https://chrome-internal-review.googlesource.com"
36 # Old fetch URL -> new fetch URL.
37 # Old fetch urls are found by grepping through manifest-versions repo.
39 'http://git.chromium.org': GOB_EXTERNAL,
40 'http://git.chromium.org/git': GOB_EXTERNAL,
41 'https://git.chromium.org/git': GOB_EXTERNAL,
42 'ssh://gerrit.chromium.org:29418': GOB_EXTERNAL,
43 'ssh://git@gitrw.chromium.org:9222': GOB_EXTERNAL,
44 'ssh://gerrit-int.chromium.org:29419': GOB_INTERNAL,
48 # Old review URL -> new review URL.
50 'gerrit.chromium.org/gerrit': GERRIT_EXTERNAL,
51 'gerrit-int.chromium.org': GERRIT_INTERNAL,
55 # Single remote entry in a manifest.
56 Remote = collections.namedtuple('Remote', ['name', 'fetch', 'review'])
59 def EnumerateManifests(directory):
60 """Yields paths to manifest files inside a directory."""
61 for path, directories, files in os.walk(directory):
62 # Find regular (not a symlink) xml files.
64 if not name.endswith('.xml'):
66 full_path = os.path.join(path, name)
67 if os.path.isfile(full_path) and not os.path.islink(full_path):
69 # Skip 'hidden' directories.
70 for hidden in [name for name in directories if name.startswith('.')]:
71 directories.remove(hidden)
74 def UpdateRemotes(manifest):
75 """Updates remotes in manifest to use Gerrit on Borg URLs.
78 manifest: Path to manifest file to modify in place.
81 True if file was modified.
83 # Read manifest file as str.
84 body = osutils.ReadFile(manifest)
87 # Update fetch="..." entries.
88 for old, new in FETCH_URLS.iteritems():
89 body = body.replace('fetch="%s"' % old, 'fetch="%s"' % new)
91 # Update review="..." entries.
92 for old, new in REVIEW_URLS.iteritems():
93 body = body.replace('review="%s"' % old, 'review="%s"' % new)
95 # Write back only if modified.
97 osutils.WriteFile(manifest, body)
103 def GetRemotes(manifest):
104 """Returns list of remotes referenced in manifest.
107 manifest: Path to manifest file to scan for remotes.
110 List of Remote tuples.
112 doc = ElementTree.parse(manifest)
114 return [Remote(remote.attrib['name'], remote.attrib['fetch'],
115 remote.attrib.get('review')) for remote in root.findall('remote')]
119 """Creates the argparse parser."""
120 parser = commandline.ArgumentParser(description=__doc__)
121 parser.add_argument('--skip-update', action='store_true', default=False,
122 help='Do not revert versions manifest checkout to original state')
123 parser.add_argument('--remotes-summary', action='store_true', default=False,
124 help='Scan all manifests and print all various remotes found in them')
125 parser.add_argument('manifest_versions_dir', type='path',
126 help='Directory to checkout manifest versions repository into')
132 options = parser.parse_args(argv)
134 # Clone manifest-versions repository.
135 manifest_repo_url = cbuildbot_config.GetManifestVersionsRepoUrl(
136 internal_build=True, read_only=False)
137 if not options.skip_update:
138 manifest_version.RefreshManifestCheckout(
139 options.manifest_versions_dir, manifest_repo_url)
141 if options.remotes_summary:
142 # Find all unique remotes.
143 cros_build_lib.Info('Scanning manifests for remotes...')
145 for manifest in EnumerateManifests(options.manifest_versions_dir):
146 remotes.update(GetRemotes(manifest))
147 # Pretty print a table.
148 print 'Remotes found:'
149 row_formatter = lambda a, b, c: ''.join(
150 [a, ' ' * (16 - len(a)), b, ' ' * (45 - len(b)), c])
151 print row_formatter('Name', 'Remote', 'Review')
153 for remote in sorted(remotes):
154 print row_formatter(remote.name, remote.fetch, remote.review or '')
157 cros_build_lib.Info('Updating manifests...')
159 for manifest in EnumerateManifests(options.manifest_versions_dir):
160 if UpdateRemotes(manifest):
162 cros_build_lib.Info('Updated manifest: %s', manifest)
165 cros_build_lib.Info('All manifests are up to date')
167 cros_build_lib.Info('Done')