| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import argparse | 5 import argparse |
| 6 import plistlib | 6 import plistlib |
| 7 import os | 7 import os |
| 8 import re | 8 import re |
| 9 import subprocess | 9 import subprocess |
| 10 import sys | 10 import sys |
| 11 import tempfile | 11 import tempfile |
| 12 import shlex | 12 import shlex |
| 13 | 13 |
| 14 | 14 |
| 15 # Xcode substitutes variables like ${PRODUCT_NAME} when compiling Info.plist. | 15 # Xcode substitutes variables like ${PRODUCT_NAME} when compiling Info.plist. |
| 16 # It also supports supports modifiers like :identifier or :rfc1034identifier. | 16 # It also supports supports modifiers like :identifier or :rfc1034identifier. |
| 17 # SUBST_RE matches a variable substitution pattern with an optional modifier, | 17 # SUBST_RE matches a variable substitution pattern with an optional modifier, |
| 18 # while IDENT_RE matches all characters that are not valid in an "identifier" | 18 # while IDENT_RE matches all characters that are not valid in an "identifier" |
| 19 # value (used when applying the modifier). | 19 # value (used when applying the modifier). |
| 20 SUBST_RE = re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}') | 20 SUBST_RE = re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}') |
| 21 IDENT_RE = re.compile(r'[/\s]') | 21 IDENT_RE = re.compile(r'[_/\s]') |
| 22 | 22 |
| 23 | 23 |
| 24 class ArgumentParser(argparse.ArgumentParser): | 24 class ArgumentParser(argparse.ArgumentParser): |
| 25 """Subclass of argparse.ArgumentParser to work with GN response files. | 25 """Subclass of argparse.ArgumentParser to work with GN response files. |
| 26 | 26 |
| 27 GN response file writes all the arguments on a single line and assumes | 27 GN response file writes all the arguments on a single line and assumes |
| 28 that the python script uses shlext.split() to extract them. Since the | 28 that the python script uses shlext.split() to extract them. Since the |
| 29 default ArgumentParser expects a single argument per line, we need to | 29 default ArgumentParser expects a single argument per line, we need to |
| 30 provide a subclass to have the correct support for @{{response_file_name}}. | 30 provide a subclass to have the correct support for @{{response_file_name}}. |
| 31 """ | 31 """ |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 A new string with all variables references ${VARIABLES} replaced by their | 66 A new string with all variables references ${VARIABLES} replaced by their |
| 67 value in |substitutions| or None if any of the variable has no substitution. | 67 value in |substitutions| or None if any of the variable has no substitution. |
| 68 """ | 68 """ |
| 69 result = value | 69 result = value |
| 70 for match in reversed(list(SUBST_RE.finditer(value))): | 70 for match in reversed(list(SUBST_RE.finditer(value))): |
| 71 variable = match.group('id') | 71 variable = match.group('id') |
| 72 if variable not in substitutions: | 72 if variable not in substitutions: |
| 73 return None | 73 return None |
| 74 # Some values need to be identifier and thus the variables references may | 74 # Some values need to be identifier and thus the variables references may |
| 75 # contains :modifier attributes to indicate how they should be converted | 75 # contains :modifier attributes to indicate how they should be converted |
| 76 # to identifiers ("identifier" replaces all invalid characters by '-' and | 76 # to identifiers ("identifier" replaces all invalid characters by '_' and |
| 77 # "rfc1034identifier" replaces them by "_" to make valid URI too). | 77 # "rfc1034identifier" replaces them by "-" to make valid URI too). |
| 78 modifier = match.group('modifier') | 78 modifier = match.group('modifier') |
| 79 if modifier == 'identifier': | 79 if modifier == ':identifier': |
| 80 interpolated = IDENT_RE.sub('_', substitutions[variable]) |
| 81 elif modifier == ':rfc1034identifier': |
| 80 interpolated = IDENT_RE.sub('-', substitutions[variable]) | 82 interpolated = IDENT_RE.sub('-', substitutions[variable]) |
| 81 elif modifier == 'rfc1034identifier': | |
| 82 interpolated = IDENT_RE.sub('_', substitutions[variable]) | |
| 83 else: | 83 else: |
| 84 interpolated = substitutions[variable] | 84 interpolated = substitutions[variable] |
| 85 result = result[:match.start()] + interpolated + result[match.end():] | 85 result = result[:match.start()] + interpolated + result[match.end():] |
| 86 return result | 86 return result |
| 87 | 87 |
| 88 | 88 |
| 89 def InterpolateValue(value, substitutions): | 89 def InterpolateValue(value, substitutions): |
| 90 """Interpolates variable references into |value| using |substitutions|. | 90 """Interpolates variable references into |value| using |substitutions|. |
| 91 | 91 |
| 92 Inputs: | 92 Inputs: |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 substitutions[key] = value | 200 substitutions[key] = value |
| 201 data = {} | 201 data = {} |
| 202 for filename in args.path: | 202 for filename in args.path: |
| 203 data = MergePList(data, LoadPList(filename)) | 203 data = MergePList(data, LoadPList(filename)) |
| 204 data = Interpolate(data, substitutions) | 204 data = Interpolate(data, substitutions) |
| 205 SavePList(args.output, args.format, data) | 205 SavePList(args.output, args.format, data) |
| 206 return 0 | 206 return 0 |
| 207 | 207 |
| 208 if __name__ == '__main__': | 208 if __name__ == '__main__': |
| 209 sys.exit(main()) | 209 sys.exit(main()) |
| OLD | NEW |