xref: /aosp_15_r20/external/google-breakpad/src/tools/python/deps-to-manifest.py (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle#!/usr/bin/env python3
2*9712c20fSFrederick Mayle# Copyright 2016 Google LLC
3*9712c20fSFrederick Mayle#
4*9712c20fSFrederick Mayle# Redistribution and use in source and binary forms, with or without
5*9712c20fSFrederick Mayle# modification, are permitted provided that the following conditions are
6*9712c20fSFrederick Mayle# met:
7*9712c20fSFrederick Mayle#
8*9712c20fSFrederick Mayle#     * Redistributions of source code must retain the above copyright
9*9712c20fSFrederick Mayle# notice, this list of conditions and the following disclaimer.
10*9712c20fSFrederick Mayle#     * Redistributions in binary form must reproduce the above
11*9712c20fSFrederick Mayle# copyright notice, this list of conditions and the following disclaimer
12*9712c20fSFrederick Mayle# in the documentation and/or other materials provided with the
13*9712c20fSFrederick Mayle# distribution.
14*9712c20fSFrederick Mayle#     * Neither the name of Google LLC nor the names of its
15*9712c20fSFrederick Mayle# contributors may be used to endorse or promote products derived from
16*9712c20fSFrederick Mayle# this software without specific prior written permission.
17*9712c20fSFrederick Mayle#
18*9712c20fSFrederick Mayle# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*9712c20fSFrederick Mayle# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*9712c20fSFrederick Mayle# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21*9712c20fSFrederick Mayle# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22*9712c20fSFrederick Mayle# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23*9712c20fSFrederick Mayle# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24*9712c20fSFrederick Mayle# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25*9712c20fSFrederick Mayle# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26*9712c20fSFrederick Mayle# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*9712c20fSFrederick Mayle# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28*9712c20fSFrederick Mayle# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*9712c20fSFrederick Mayle
30*9712c20fSFrederick Mayle"""Convert gclient's DEPS file to repo's manifest xml file."""
31*9712c20fSFrederick Mayle
32*9712c20fSFrederick Mayleimport argparse
33*9712c20fSFrederick Mayleimport os
34*9712c20fSFrederick Mayleimport sys
35*9712c20fSFrederick Mayle
36*9712c20fSFrederick Mayle
37*9712c20fSFrederick MayleREMOTES = {
38*9712c20fSFrederick Mayle    'chromium': 'https://chromium.googlesource.com/',
39*9712c20fSFrederick Mayle    'github': 'https://github.com/',
40*9712c20fSFrederick Mayle}
41*9712c20fSFrederick MayleREVIEWS = {
42*9712c20fSFrederick Mayle    'chromium': 'https://chromium-review.googlesource.com',
43*9712c20fSFrederick Mayle}
44*9712c20fSFrederick Mayle
45*9712c20fSFrederick MayleMANIFEST_HEAD = """<?xml version='1.0' encoding='UTF-8'?>
46*9712c20fSFrederick Mayle<!-- AUTOGENERATED BY %(prog)s; DO NOT EDIT -->
47*9712c20fSFrederick Mayle<manifest>
48*9712c20fSFrederick Mayle
49*9712c20fSFrederick Mayle  <default revision='refs/heads/main'
50*9712c20fSFrederick Mayle           remote='chromium'
51*9712c20fSFrederick Mayle           sync-c='true'
52*9712c20fSFrederick Mayle           sync-j='8' />
53*9712c20fSFrederick Mayle"""
54*9712c20fSFrederick Mayle
55*9712c20fSFrederick MayleMANIFEST_REMOTE = """
56*9712c20fSFrederick Mayle  <remote  name='%(name)s'
57*9712c20fSFrederick Mayle           fetch='%(fetch)s'
58*9712c20fSFrederick Mayle           review='%(review)s' />
59*9712c20fSFrederick Mayle"""
60*9712c20fSFrederick Mayle
61*9712c20fSFrederick MayleMANIFEST_PROJECT = """
62*9712c20fSFrederick Mayle  <project path='%(path)s'
63*9712c20fSFrederick Mayle           name='%(name)s'
64*9712c20fSFrederick Mayle           revision='%(revision)s'
65*9712c20fSFrederick Mayle           remote='%(remote)s' />
66*9712c20fSFrederick Mayle"""
67*9712c20fSFrederick Mayle
68*9712c20fSFrederick MayleMANIFEST_TAIL = """
69*9712c20fSFrederick Mayle</manifest>
70*9712c20fSFrederick Mayle"""
71*9712c20fSFrederick Mayle
72*9712c20fSFrederick Mayle
73*9712c20fSFrederick Mayledef ConvertDepsToManifest(deps, manifest):
74*9712c20fSFrederick Mayle  """Convert the |deps| file to the |manifest|."""
75*9712c20fSFrederick Mayle  # Load the DEPS file data.
76*9712c20fSFrederick Mayle  ctx = {}
77*9712c20fSFrederick Mayle  with open(deps, 'rb') as file:
78*9712c20fSFrederick Mayle    exec(compile(file.read(), deps, 'exec'), ctx)
79*9712c20fSFrederick Mayle
80*9712c20fSFrederick Mayle  new_contents = ''
81*9712c20fSFrederick Mayle
82*9712c20fSFrederick Mayle  # Write out the common header.
83*9712c20fSFrederick Mayle  data = {
84*9712c20fSFrederick Mayle      'prog': os.path.basename(__file__),
85*9712c20fSFrederick Mayle  }
86*9712c20fSFrederick Mayle  new_contents += MANIFEST_HEAD % data
87*9712c20fSFrederick Mayle
88*9712c20fSFrederick Mayle  # Write out the <remote> sections.
89*9712c20fSFrederick Mayle  for name, fetch in REMOTES.items():
90*9712c20fSFrederick Mayle    data = {
91*9712c20fSFrederick Mayle        'name': name,
92*9712c20fSFrederick Mayle        'fetch': fetch,
93*9712c20fSFrederick Mayle        'review': REVIEWS.get(name, ''),
94*9712c20fSFrederick Mayle    }
95*9712c20fSFrederick Mayle    new_contents += MANIFEST_REMOTE % data
96*9712c20fSFrederick Mayle
97*9712c20fSFrederick Mayle  # Write out the main repo itself.
98*9712c20fSFrederick Mayle  data = {
99*9712c20fSFrederick Mayle      'path': 'src',
100*9712c20fSFrederick Mayle      'name': 'breakpad/breakpad',
101*9712c20fSFrederick Mayle      'revision': 'refs/heads/main',
102*9712c20fSFrederick Mayle      'remote': 'chromium',
103*9712c20fSFrederick Mayle  }
104*9712c20fSFrederick Mayle  new_contents += MANIFEST_PROJECT % data
105*9712c20fSFrederick Mayle
106*9712c20fSFrederick Mayle  # Write out the <project> sections.
107*9712c20fSFrederick Mayle  for path, url in ctx['deps'].items():
108*9712c20fSFrederick Mayle    for name, fetch in REMOTES.items():
109*9712c20fSFrederick Mayle      if url.startswith(fetch):
110*9712c20fSFrederick Mayle        remote = name
111*9712c20fSFrederick Mayle        break
112*9712c20fSFrederick Mayle    else:
113*9712c20fSFrederick Mayle      raise ValueError('Unknown DEPS remote: %s: %s' % (path, url))
114*9712c20fSFrederick Mayle
115*9712c20fSFrederick Mayle    # The DEPS url will look like:
116*9712c20fSFrederick Mayle    # https://chromium.googlesource.com/external/gyp/@e8ab0833a42691cd2
117*9712c20fSFrederick Mayle    remote_path, rev = url.split('@')
118*9712c20fSFrederick Mayle    remote_path = remote_path[len(fetch):]
119*9712c20fSFrederick Mayle
120*9712c20fSFrederick Mayle    # If it's not a revision, assume it's a tag.  Repo wants full ref names.
121*9712c20fSFrederick Mayle    if len(rev) != 40:
122*9712c20fSFrederick Mayle      rev = 'refs/tags/%s' % rev
123*9712c20fSFrederick Mayle
124*9712c20fSFrederick Mayle    data = {
125*9712c20fSFrederick Mayle        'path': path,
126*9712c20fSFrederick Mayle        'name': remote_path,
127*9712c20fSFrederick Mayle        'revision': rev,
128*9712c20fSFrederick Mayle        'remote': remote,
129*9712c20fSFrederick Mayle    }
130*9712c20fSFrederick Mayle    new_contents += MANIFEST_PROJECT % data
131*9712c20fSFrederick Mayle
132*9712c20fSFrederick Mayle  # Write out the common footer.
133*9712c20fSFrederick Mayle  new_contents += MANIFEST_TAIL
134*9712c20fSFrederick Mayle
135*9712c20fSFrederick Mayle  # See if the manifest has actually changed contents to avoid thrashing.
136*9712c20fSFrederick Mayle  try:
137*9712c20fSFrederick Mayle    old_contents = open(manifest).read()
138*9712c20fSFrederick Mayle  except IOError:
139*9712c20fSFrederick Mayle    # In case the file doesn't exist yet.
140*9712c20fSFrederick Mayle    old_contents = ''
141*9712c20fSFrederick Mayle  if old_contents != new_contents:
142*9712c20fSFrederick Mayle    print('Updating %s due to changed %s' % (manifest, deps))
143*9712c20fSFrederick Mayle    with open(manifest, 'w') as fp:
144*9712c20fSFrederick Mayle      fp.write(new_contents)
145*9712c20fSFrederick Mayle
146*9712c20fSFrederick Mayle
147*9712c20fSFrederick Mayledef GetParser():
148*9712c20fSFrederick Mayle  """Return a CLI parser."""
149*9712c20fSFrederick Mayle  parser = argparse.ArgumentParser(description=__doc__)
150*9712c20fSFrederick Mayle  parser.add_argument('deps',
151*9712c20fSFrederick Mayle                      help='The DEPS file to convert')
152*9712c20fSFrederick Mayle  parser.add_argument('manifest',
153*9712c20fSFrederick Mayle                      help='The manifest xml to generate')
154*9712c20fSFrederick Mayle  return parser
155*9712c20fSFrederick Mayle
156*9712c20fSFrederick Mayle
157*9712c20fSFrederick Mayledef main(argv):
158*9712c20fSFrederick Mayle  """The main func!"""
159*9712c20fSFrederick Mayle  parser = GetParser()
160*9712c20fSFrederick Mayle  opts = parser.parse_args(argv)
161*9712c20fSFrederick Mayle  ConvertDepsToManifest(opts.deps, opts.manifest)
162*9712c20fSFrederick Mayle
163*9712c20fSFrederick Mayle
164*9712c20fSFrederick Mayleif __name__ == '__main__':
165*9712c20fSFrederick Mayle  sys.exit(main(sys.argv[1:]))
166