Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3088)

Unified Diff: build/config/ios/ios_gen_plist.py

Issue 1611363003: Add support for iOS application bundle to GN. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn-bundles
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: build/config/ios/ios_gen_plist.py
diff --git a/build/config/ios/ios_gen_plist.py b/build/config/ios/ios_gen_plist.py
new file mode 100644
index 0000000000000000000000000000000000000000..77dc67c65ec1a147d69d7133e2a6e16cb5517467
--- /dev/null
+++ b/build/config/ios/ios_gen_plist.py
@@ -0,0 +1,128 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import plistlib
+import os
+import re
+import subprocess
+import sys
+import tempfile
+import shlex
+
+
+IDENT_RE = re.compile(r'[/\s]')
brettw 2016/01/22 19:00:12 Can you provide documentation for these about what
sdefresne 2016/01/25 14:01:22 Done.
+SUBST_RE = re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}')
+
+
+class ArgumentParser(argparse.ArgumentParser):
+
brettw 2016/01/22 19:00:12 Delete blank line.
sdefresne 2016/01/25 14:01:22 Done.
+ """Subclass of argparse.ArgumentParser to work with GN response files."""
+
+ def convert_arg_line_to_args(self, arg_line):
+ return shlex.split(arg_line)
+
+
+def Merge(plist1, plist2):
+ """Recursively merges |plist2| into |plist1|."""
+ if not plist1:
+ return plist2
+ for key in plist2:
+ value = plist2[key]
+ if isinstance(value, dict):
+ plist1[key] = Merge(plist1.get(key, {}), value)
+ else:
+ plist1[key] = value
+ return plist1
+
+
+def Interpolate(plist, substitutions):
+ """Interpolates ${variable} into |plist| using mapping in |substitutions|."""
+ result = []
+ groups = SUBST_RE.split(plistlib.writePlistToString(plist))
+ # SUBST_RE defines two patterns, so given a string, SUBST_RE.split will
+ # return a list whose position correspond to an unmatched fragment, a
+ # match identifier or a match modifier (may be None as it is optional).
+ # Enumerate over the value and check the index modulo 3 to figure out
+ # the category of the value.
+ for i, value in enumerate(groups):
+ if i % 3 == 0:
+ result.append(value)
+ elif i % 3 == 1:
+ if value in substitutions:
+ result.append(substitutions[value])
+ else:
+ result.append('${%s}' % value)
+ elif i % 3 == 2:
+ value, modifier = result[-1], value
+ if modifier == 'identifier':
+ value = IDENT_RE.sub('-', value)
+ elif modifier == 'rfc1034identifier':
+ value = IDENT_RE.sub('_', value)
+ result[-1] = value
+ return CleanPlist(plistlib.readPlistFromString(''.join(result)))
+
+
+def CleanPlist(plist):
+ """Removes all key of |plist| with unexpanded variables substitution."""
+ key_to_remove = []
+ for key in plist:
+ value = plist[key]
+ data = plistlib.writePlistToString(value)
+ if SUBST_RE.search(data):
+ key_to_remove.append(key)
+ for key in key_to_remove:
+ del plist[key]
+ return plist
+
+
+def LoadPList(path):
+ """Loads Plist at |path| and returns it as a dictionary."""
+ fd, name = tempfile.mkstemp()
+ try:
+ subprocess.check_call(['plutil', '-convert', 'xml1', '-o', name, path])
+ with os.fdopen(fd, 'r') as f:
+ return plistlib.readPlist(f)
+ finally:
+ os.unlink(name)
+
+
+def SavePList(path, data):
+ """Saves |data| as a Plist to |path| in binary1 format."""
+ fd, name = tempfile.mkstemp()
+ try:
+ with os.fdopen(fd, 'w') as f:
+ plistlib.writePlist(data, f)
+ subprocess.check_call(['plutil', '-convert', 'binary1', '-o', path, name])
+ finally:
+ os.unlink(name)
+
+
+def main():
+ parser = ArgumentParser(
+ description='A script to generate iOS application Info.plist.',
+ fromfile_prefix_chars='@')
+ parser.add_argument('-o', '--output', required=True,
+ help='Path to output plist file.')
+ parser.add_argument('-s', '--subst', action='append', default=[],
+ help='Substitution rule in the format "key=value".')
+ parser.add_argument('path', nargs="+", help='Path to input plist files.')
+ args = parser.parse_args()
+
+ substitutions = {}
+ for subst in args.subst:
+ key, value = subst.split('=', 1)
+ substitutions[key] = value
+
+ data = {}
+ for path in args.path:
+ data = Merge(data, LoadPList(path))
+
+ data = Interpolate(data, substitutions)
+ SavePList(args.output, data)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())

Powered by Google App Engine
This is Rietveld 408576698