diff --git a/.gitignore b/.gitignore index 17874aa0..b2ef4c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Ignore other VCSs. +.repo/ .svn/ # Ignore common compiled artifacts. diff --git a/DEPS b/DEPS index 2de510a5..0a06f1bb 100644 --- a/DEPS +++ b/DEPS @@ -72,4 +72,9 @@ hooks = [ "--no-circular-check", "src/src/client/windows/breakpad_client.gyp"], }, + { + # Keep the manifest up to date. + "action": ["python", "src/src/tools/python/deps-to-manifest.py", + "src/DEPS", "src/default.xml"], + }, ] diff --git a/default.xml b/default.xml new file mode 100644 index 00000000..77aea228 --- /dev/null +++ b/default.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tools/python/deps-to-manifest.py b/src/tools/python/deps-to-manifest.py new file mode 100755 index 00000000..b4562854 --- /dev/null +++ b/src/tools/python/deps-to-manifest.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +# Copyright 2016 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Convert gclient's DEPS file to repo's manifest xml file.""" + +from __future__ import print_function + +import argparse +import os +import sys + + +REMOTES = { + 'chromium': 'https://chromium.googlesource.com/', + 'github': 'https://github.com/', +} +REVIEWS = { + 'chromium': 'https://chromium-review.googlesource.com', +} + +MANIFEST_HEAD = """ + + + + +""" + +MANIFEST_REMOTE = """ + +""" + +MANIFEST_PROJECT = """ + +""" + +MANIFEST_TAIL = """ + +""" + + +def ConvertDepsToManifest(deps, manifest): + """Convert the |deps| file to the |manifest|.""" + # Load the DEPS file data. + ctx = {} + execfile(deps, ctx) + + new_contents = '' + + # Write out the common header. + data = { + 'prog': os.path.basename(__file__), + } + new_contents += MANIFEST_HEAD % data + + # Write out the sections. + for name, fetch in REMOTES.items(): + data = { + 'name': name, + 'fetch': fetch, + 'review': REVIEWS.get(name, ''), + } + new_contents += MANIFEST_REMOTE % data + + # Write out the main repo itself. + data = { + 'path': 'src', + 'name': 'breakpad/breakpad', + 'revision': 'refs/heads/master', + 'remote': 'chromium', + } + new_contents += MANIFEST_PROJECT % data + + # Write out the sections. + for path, url in ctx['deps'].items(): + for name, fetch in REMOTES.items(): + if url.startswith(fetch): + remote = name + break + else: + raise ValueError('Unknown DEPS remote: %s: %s' % (path, url)) + + # The DEPS url will look like: + # https://chromium.googlesource.com/external/gyp/@e8ab0833a42691cd2 + remote_path, rev = url.split('@') + remote_path = remote_path[len(fetch):] + + # If it's not a revision, assume it's a tag. Repo wants full ref names. + if len(rev) != 40: + rev = 'refs/tags/%s' % rev + + data = { + 'path': path, + 'name': remote_path, + 'revision': rev, + 'remote': remote, + } + new_contents += MANIFEST_PROJECT % data + + # Write out the common footer. + new_contents += MANIFEST_TAIL + + # See if the manifest has actually changed contents to avoid thrashing. + try: + old_contents = open(manifest).read() + except IOError: + # In case the file doesn't exist yet. + old_contents = '' + if old_contents != new_contents: + print('Updating %s due to changed %s' % (manifest, deps)) + with open(manifest, 'w') as fp: + fp.write(new_contents) + + +def GetParser(): + """Return a CLI parser.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('deps', + help='The DEPS file to convert') + parser.add_argument('manifest', + help='The manifest xml to generate') + return parser + + +def main(argv): + """The main func!""" + parser = GetParser() + opts = parser.parse_args(argv) + ConvertDepsToManifest(opts.deps, opts.manifest) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))