| OLD | NEW |
| 1 # coding=utf-8 | 1 # coding=utf-8 |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Common code to manage .isolate format. | 6 """Common code to manage .isolate format. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 import logging | 9 import logging |
| 10 import os | 10 import os |
| 11 import posixpath | 11 import posixpath |
| 12 import re |
| 12 import sys | 13 import sys |
| 13 | 14 |
| 15 import trace_inputs |
| 16 |
| 17 |
| 18 PATH_VARIABLES = ('DEPTH', 'PRODUCT_DIR') |
| 14 | 19 |
| 15 KEY_TRACKED = 'isolate_dependency_tracked' | 20 KEY_TRACKED = 'isolate_dependency_tracked' |
| 16 KEY_UNTRACKED = 'isolate_dependency_untracked' | 21 KEY_UNTRACKED = 'isolate_dependency_untracked' |
| 17 | 22 |
| 18 _GIT_PATH = os.path.sep + '.git' + os.path.sep | 23 _GIT_PATH = os.path.sep + '.git' + os.path.sep |
| 19 _SVN_PATH = os.path.sep + '.svn' + os.path.sep | 24 _SVN_PATH = os.path.sep + '.svn' + os.path.sep |
| 20 | 25 |
| 21 | 26 |
| 22 def posix_relpath(path, root): | 27 def posix_relpath(path, root): |
| 23 """posix.relpath() that keeps trailing slash.""" | 28 """posix.relpath() that keeps trailing slash.""" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 47 'sunos5': 'solaris', | 52 'sunos5': 'solaris', |
| 48 'freebsd7': 'freebsd', | 53 'freebsd7': 'freebsd', |
| 49 'freebsd8': 'freebsd', | 54 'freebsd8': 'freebsd', |
| 50 } | 55 } |
| 51 return flavors.get(sys.platform, 'linux') | 56 return flavors.get(sys.platform, 'linux') |
| 52 | 57 |
| 53 | 58 |
| 54 def default_blacklist(f): | 59 def default_blacklist(f): |
| 55 """Filters unimportant files normally ignored.""" | 60 """Filters unimportant files normally ignored.""" |
| 56 return ( | 61 return ( |
| 57 f.endswith('.pyc') or | 62 f.endswith(('.pyc', 'testserver.log')) or |
| 58 _GIT_PATH in f or | 63 _GIT_PATH in f or |
| 59 _SVN_PATH in f) | 64 _SVN_PATH in f) |
| 60 | 65 |
| 61 | 66 |
| 62 def generate_dict(files, cwd_dir, product_dir): | 67 def classify_files(files): |
| 63 """Converts the list of files into a .isolate dictionary. | 68 """Converts the list of files into a .isolate 'variables' dictionary. |
| 64 | 69 |
| 65 Arguments: | 70 Arguments: |
| 66 - files: list of files to generate a dictionary out of. | 71 - files: list of files names to generate a dictionary out of. |
| 67 - cwd_dir: directory to base all the files from, relative to root_dir. | |
| 68 - product_dir: directory to replace with <(PRODUCT_DIR), relative to root_dir. | |
| 69 """ | 72 """ |
| 70 cwd_dir = cleanup_path(cwd_dir) | 73 files = list(files) |
| 71 product_dir = cleanup_path(product_dir) | 74 tracked = sorted(f for f in files if not f.endswith('/') and ' ' not in f) |
| 72 | 75 untracked = sorted(f for f in files if f.endswith('/') or ' ' in f) |
| 73 def fix(f): | |
| 74 """Bases the file on the most restrictive variable.""" | |
| 75 logging.debug('fix(%s)' % f) | |
| 76 # Important, GYP stores the files with / and not \. | |
| 77 f = f.replace(os.path.sep, '/') | |
| 78 if product_dir and f.startswith(product_dir): | |
| 79 return '<(PRODUCT_DIR)/%s' % f[len(product_dir):] | |
| 80 else: | |
| 81 # cwd_dir is usually the directory containing the gyp file. It may be | |
| 82 # empty if the whole directory containing the gyp file is needed. | |
| 83 return posix_relpath(f, cwd_dir) or './' | |
| 84 | |
| 85 corrected = [fix(f) for f in files] | |
| 86 tracked = [f for f in corrected if not f.endswith('/') and ' ' not in f] | |
| 87 untracked = [f for f in corrected if f.endswith('/') or ' ' in f] | |
| 88 variables = {} | 76 variables = {} |
| 89 if tracked: | 77 if tracked: |
| 90 variables[KEY_TRACKED] = tracked | 78 variables[KEY_TRACKED] = tracked |
| 91 if untracked: | 79 if untracked: |
| 92 variables[KEY_UNTRACKED] = untracked | 80 variables[KEY_UNTRACKED] = untracked |
| 93 return variables | 81 return variables |
| 94 | 82 |
| 95 | 83 |
| 84 def generate_simplified(files, root_dir, variables, relative_cwd): |
| 85 """Generates a clean and complete .isolate 'variables' dictionary. |
| 86 |
| 87 Cleans up and extracts only files from within root_dir then processes |
| 88 variables and relative_cwd. |
| 89 """ |
| 90 # Constants. |
| 91 # Skip log in PRODUCT_DIR. |
| 92 LOG_FILE = re.compile(r'^\<\(PRODUCT_DIR\)\/[^/]+\.log$') |
| 93 EXECUTABLE = re.compile( |
| 94 r'^(\<\(PRODUCT_DIR\)\/[^/\.]+)' + |
| 95 re.escape(variables.get('EXECUTABLE_SUFFIX', '')) + |
| 96 r'$') |
| 97 |
| 98 # Preparation work. |
| 99 relative_cwd = cleanup_path(relative_cwd) |
| 100 # Creates the right set of variables here. We only care about |
| 101 # PATH_VARIABLES. |
| 102 variables = dict( |
| 103 ('<(%s)' % k, variables[k]) for k in PATH_VARIABLES if k in variables) |
| 104 |
| 105 # Actual work: Process the files. |
| 106 files = trace_inputs.extract_directories(root_dir, files) |
| 107 files = (f.replace_variables(variables) for f in files) |
| 108 |
| 109 def fix(f): |
| 110 """Bases the file on the most restrictive variable.""" |
| 111 logging.debug('fix(%s)' % f) |
| 112 # Important, GYP stores the files with / and not \. |
| 113 f = f.replace(os.path.sep, '/') |
| 114 # If it's not already a variable. |
| 115 if not f.startswith('<'): |
| 116 # relative_cwd is usually the directory containing the gyp file. It may be |
| 117 # empty if the whole directory containing the gyp file is needed. |
| 118 f = posix_relpath(f, relative_cwd) or './' |
| 119 |
| 120 # Now strips off known files we want to ignore and to any specific mangling |
| 121 # as necessary. It's easier to do it here than generate a blacklist. |
| 122 match = EXECUTABLE.match(f) |
| 123 if match: |
| 124 return match.group(1) + '<(EXECUTABLE_SUFFIX)' |
| 125 if LOG_FILE.match(f): |
| 126 return None |
| 127 return f |
| 128 |
| 129 return classify_files(filter(None, (fix(f.path) for f in files))) |
| 130 |
| 131 |
| 132 def generate_isolate(files, root_dir, variables, relative_cwd): |
| 133 """Generates a clean and complete .isolate file.""" |
| 134 result = generate_simplified(files, root_dir, variables, relative_cwd) |
| 135 return { |
| 136 'conditions': [ |
| 137 ['OS=="%s"' % get_flavor(), { |
| 138 'variables': result, |
| 139 }], |
| 140 ], |
| 141 } |
| 142 |
| 143 |
| 96 def pretty_print(variables, stdout): | 144 def pretty_print(variables, stdout): |
| 97 """Outputs a gyp compatible list from the decoded variables. | 145 """Outputs a gyp compatible list from the decoded variables. |
| 98 | 146 |
| 99 Similar to pprint.print() but with NIH syndrome. | 147 Similar to pprint.print() but with NIH syndrome. |
| 100 """ | 148 """ |
| 101 # Order the dictionary keys by these keys in priority. | 149 # Order the dictionary keys by these keys in priority. |
| 102 ORDER = ( | 150 ORDER = ( |
| 103 'variables', 'condition', 'command', 'relative_cwd', 'read_only', | 151 'variables', 'condition', 'command', 'relative_cwd', 'read_only', |
| 104 KEY_TRACKED, KEY_UNTRACKED) | 152 KEY_TRACKED, KEY_UNTRACKED) |
| 105 | 153 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 stdout.write( | 202 stdout.write( |
| 155 '\'%s\',\n' % item.replace('\\', '\\\\').replace('\'', '\\\'')) | 203 '\'%s\',\n' % item.replace('\\', '\\\\').replace('\'', '\\\'')) |
| 156 elif item in (True, False, None): | 204 elif item in (True, False, None): |
| 157 stdout.write('%s\n' % item) | 205 stdout.write('%s\n' % item) |
| 158 else: | 206 else: |
| 159 assert False, item | 207 assert False, item |
| 160 | 208 |
| 161 stdout.write('{\n') | 209 stdout.write('{\n') |
| 162 loop_dict(' ', variables) | 210 loop_dict(' ', variables) |
| 163 stdout.write('}\n') | 211 stdout.write('}\n') |
| OLD | NEW |