| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # | |
| 3 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 """Utility for dart_pkg and dart_pkg_app rules""" | |
| 8 | |
| 9 import argparse | |
| 10 import errno | |
| 11 import json | |
| 12 import os | |
| 13 import shutil | |
| 14 import subprocess | |
| 15 import sys | |
| 16 | |
| 17 USE_LINKS = sys.platform != "win32" | |
| 18 | |
| 19 DART_ANALYZE = os.path.join(os.path.dirname(os.path.abspath(__file__)), | |
| 20 "dart_analyze.py") | |
| 21 | |
| 22 def dart_filter(path): | |
| 23 if os.path.isdir(path): | |
| 24 return True | |
| 25 _, ext = os.path.splitext(path) | |
| 26 # .dart includes '.mojom.dart' | |
| 27 return ext == '.dart' | |
| 28 | |
| 29 | |
| 30 def ensure_dir_exists(path): | |
| 31 abspath = os.path.abspath(path) | |
| 32 if not os.path.exists(abspath): | |
| 33 os.makedirs(abspath) | |
| 34 | |
| 35 | |
| 36 def has_pubspec_yaml(paths): | |
| 37 for path in paths: | |
| 38 _, filename = os.path.split(path) | |
| 39 if 'pubspec.yaml' == filename: | |
| 40 return True | |
| 41 return False | |
| 42 | |
| 43 | |
| 44 def link(from_root, to_root): | |
| 45 ensure_dir_exists(os.path.dirname(to_root)) | |
| 46 try: | |
| 47 os.unlink(to_root) | |
| 48 except OSError as e: | |
| 49 if e.errno == errno.ENOENT: | |
| 50 pass | |
| 51 | |
| 52 try: | |
| 53 os.symlink(from_root, to_root) | |
| 54 except OSError as e: | |
| 55 if e.errno == errno.EEXIST: | |
| 56 pass | |
| 57 | |
| 58 | |
| 59 def copy(from_root, to_root, filter_func=None): | |
| 60 if not os.path.exists(from_root): | |
| 61 return | |
| 62 if os.path.isfile(from_root): | |
| 63 ensure_dir_exists(os.path.dirname(to_root)) | |
| 64 shutil.copy(from_root, to_root) | |
| 65 return | |
| 66 | |
| 67 ensure_dir_exists(to_root) | |
| 68 | |
| 69 for root, dirs, files in os.walk(from_root): | |
| 70 # filter_func expects paths not names, so wrap it to make them absolute. | |
| 71 wrapped_filter = None | |
| 72 if filter_func: | |
| 73 wrapped_filter = lambda name: filter_func(os.path.join(root, name)) | |
| 74 | |
| 75 for name in filter(wrapped_filter, files): | |
| 76 from_path = os.path.join(root, name) | |
| 77 root_rel_path = os.path.relpath(from_path, from_root) | |
| 78 to_path = os.path.join(to_root, root_rel_path) | |
| 79 to_dir = os.path.dirname(to_path) | |
| 80 if not os.path.exists(to_dir): | |
| 81 os.makedirs(to_dir) | |
| 82 shutil.copy(from_path, to_path) | |
| 83 | |
| 84 dirs[:] = filter(wrapped_filter, dirs) | |
| 85 | |
| 86 | |
| 87 def copy_or_link(from_root, to_root, filter_func=None): | |
| 88 if USE_LINKS: | |
| 89 link(from_root, to_root) | |
| 90 else: | |
| 91 copy(from_root, to_root, filter_func) | |
| 92 | |
| 93 | |
| 94 def link_if_possible(from_root, to_root): | |
| 95 if USE_LINKS: | |
| 96 link(from_root, to_root) | |
| 97 | |
| 98 | |
| 99 def remove_if_exists(path): | |
| 100 try: | |
| 101 os.remove(path) | |
| 102 except OSError as e: | |
| 103 if e.errno != errno.ENOENT: | |
| 104 raise | |
| 105 | |
| 106 | |
| 107 def list_files(from_root, filter_func=None): | |
| 108 file_list = [] | |
| 109 for root, dirs, files in os.walk(from_root): | |
| 110 # filter_func expects paths not names, so wrap it to make them absolute. | |
| 111 wrapped_filter = None | |
| 112 if filter_func: | |
| 113 wrapped_filter = lambda name: filter_func(os.path.join(root, name)) | |
| 114 for name in filter(wrapped_filter, files): | |
| 115 path = os.path.join(root, name) | |
| 116 file_list.append(path) | |
| 117 dirs[:] = filter(wrapped_filter, dirs) | |
| 118 return file_list | |
| 119 | |
| 120 | |
| 121 def remove_broken_symlink(path): | |
| 122 try: | |
| 123 link_path = os.readlink(path) | |
| 124 except OSError as e: | |
| 125 # Path was not a symlink. | |
| 126 if e.errno == errno.EINVAL: | |
| 127 pass | |
| 128 else: | |
| 129 if not os.path.exists(link_path): | |
| 130 remove_if_exists(path) | |
| 131 | |
| 132 | |
| 133 def remove_broken_symlinks(root_dir): | |
| 134 for current_dir, _, child_files in os.walk(root_dir): | |
| 135 for filename in child_files: | |
| 136 path = os.path.join(current_dir, filename) | |
| 137 remove_broken_symlink(path) | |
| 138 | |
| 139 | |
| 140 def analyze_entrypoints(dart_sdk, package_root, entrypoints): | |
| 141 cmd = [ "python", DART_ANALYZE ] | |
| 142 cmd.append("--dart-sdk") | |
| 143 cmd.append(dart_sdk) | |
| 144 cmd.append("--entrypoints") | |
| 145 cmd.extend(entrypoints) | |
| 146 cmd.append("--package-root") | |
| 147 cmd.append(package_root) | |
| 148 cmd.append("--no-hints") | |
| 149 try: | |
| 150 subprocess.check_output(cmd, stderr=subprocess.STDOUT) | |
| 151 except subprocess.CalledProcessError as e: | |
| 152 print('Failed analyzing %s' % entrypoints) | |
| 153 print(e.output) | |
| 154 return e.returncode | |
| 155 return 0 | |
| 156 | |
| 157 | |
| 158 def main(): | |
| 159 parser = argparse.ArgumentParser(description='Generate a dart-pkg') | |
| 160 parser.add_argument('--dart-sdk', | |
| 161 action='store', | |
| 162 metavar='dart_sdk', | |
| 163 help='Path to the Dart SDK.') | |
| 164 parser.add_argument('--package-name', | |
| 165 action='store', | |
| 166 metavar='package_name', | |
| 167 help='Name of package', | |
| 168 required=True) | |
| 169 parser.add_argument('--pkg-directory', | |
| 170 metavar='pkg_directory', | |
| 171 help='Directory where dart_pkg should go', | |
| 172 required=True) | |
| 173 parser.add_argument('--package-root', | |
| 174 metavar='package_root', | |
| 175 help='packages/ directory', | |
| 176 required=True) | |
| 177 parser.add_argument('--stamp-file', | |
| 178 metavar='stamp_file', | |
| 179 help='timestamp file', | |
| 180 required=True) | |
| 181 parser.add_argument('--entries-file', | |
| 182 metavar='entries_file', | |
| 183 help='script entries file', | |
| 184 required=True) | |
| 185 parser.add_argument('--package-sources', | |
| 186 metavar='package_sources', | |
| 187 help='Package sources', | |
| 188 nargs='+') | |
| 189 parser.add_argument('--package-entrypoints', | |
| 190 metavar='package_entrypoints', | |
| 191 help='Package entry points for analyzer', | |
| 192 nargs='*', | |
| 193 default=[]) | |
| 194 parser.add_argument('--sdk-ext-directories', | |
| 195 metavar='sdk_ext_directories', | |
| 196 help='Directory containing .dart sources', | |
| 197 nargs='*', | |
| 198 default=[]) | |
| 199 parser.add_argument('--sdk-ext-files', | |
| 200 metavar='sdk_ext_files', | |
| 201 help='List of .dart files that are part of of sdk_ext.', | |
| 202 nargs='*', | |
| 203 default=[]) | |
| 204 parser.add_argument('--sdk-ext-mappings', | |
| 205 metavar='sdk_ext_mappings', | |
| 206 help='Mappings for SDK extension libraries.', | |
| 207 nargs='*', | |
| 208 default=[]) | |
| 209 parser.add_argument('--read_only', | |
| 210 action='store_true', | |
| 211 dest='read_only', | |
| 212 help='Package is a read only package.', | |
| 213 default=False) | |
| 214 args = parser.parse_args() | |
| 215 | |
| 216 # We must have a pubspec.yaml. | |
| 217 assert has_pubspec_yaml(args.package_sources) | |
| 218 | |
| 219 target_dir = os.path.join(args.pkg_directory, args.package_name) | |
| 220 target_packages_dir = os.path.join(target_dir, 'packages') | |
| 221 lib_path = os.path.join(target_dir, "lib") | |
| 222 ensure_dir_exists(lib_path) | |
| 223 | |
| 224 mappings = {} | |
| 225 for mapping in args.sdk_ext_mappings: | |
| 226 library, path = mapping.split(',', 1) | |
| 227 mappings[library] = '../sdk_ext/%s' % path | |
| 228 | |
| 229 sdkext_path = os.path.join(lib_path, '_sdkext') | |
| 230 if mappings: | |
| 231 with open(sdkext_path, 'w') as stream: | |
| 232 json.dump(mappings, stream, sort_keys=True, | |
| 233 indent=2, separators=(',', ': ')) | |
| 234 else: | |
| 235 remove_if_exists(sdkext_path) | |
| 236 | |
| 237 # Copy or symlink package sources into pkg directory. | |
| 238 common_source_prefix = os.path.dirname(os.path.commonprefix( | |
| 239 args.package_sources)) | |
| 240 for source in args.package_sources: | |
| 241 relative_source = os.path.relpath(source, common_source_prefix) | |
| 242 target = os.path.join(target_dir, relative_source) | |
| 243 copy_or_link(source, target) | |
| 244 | |
| 245 entrypoint_targets = [] | |
| 246 for source in args.package_entrypoints: | |
| 247 relative_source = os.path.relpath(source, common_source_prefix) | |
| 248 target = os.path.join(target_dir, relative_source) | |
| 249 copy_or_link(source, target) | |
| 250 entrypoint_targets.append(target) | |
| 251 | |
| 252 # Copy sdk-ext sources into pkg directory | |
| 253 sdk_ext_dir = os.path.join(target_dir, 'sdk_ext') | |
| 254 for directory in args.sdk_ext_directories: | |
| 255 sdk_ext_sources = list_files(directory, dart_filter) | |
| 256 common_prefix = os.path.commonprefix(sdk_ext_sources) | |
| 257 for source in sdk_ext_sources: | |
| 258 relative_source = os.path.relpath(source, common_prefix) | |
| 259 target = os.path.join(sdk_ext_dir, relative_source) | |
| 260 copy_or_link(source, target) | |
| 261 | |
| 262 common_source_prefix = os.path.dirname(os.path.commonprefix( | |
| 263 args.sdk_ext_files)) | |
| 264 for source in args.sdk_ext_files: | |
| 265 relative_source = os.path.relpath(source, common_source_prefix) | |
| 266 target = os.path.join(sdk_ext_dir, relative_source) | |
| 267 copy_or_link(source, target) | |
| 268 | |
| 269 # Symlink packages/ | |
| 270 package_path = os.path.join(args.package_root, args.package_name) | |
| 271 link(lib_path, package_path) | |
| 272 | |
| 273 # Link dart-pkg/$package/packages to dart-pkg/packages | |
| 274 link_if_possible(args.package_root, target_packages_dir) | |
| 275 | |
| 276 # Remove any broken symlinks in target_dir and package root. | |
| 277 remove_broken_symlinks(target_dir) | |
| 278 remove_broken_symlinks(args.package_root) | |
| 279 | |
| 280 # If any entrypoints are defined, write them to disk so that the analyzer | |
| 281 # test can find them. | |
| 282 with open(args.entries_file, 'w') as f: | |
| 283 for entrypoint in entrypoint_targets: | |
| 284 f.write(entrypoint + '\n') | |
| 285 | |
| 286 # Write stamp file. | |
| 287 with open(args.stamp_file, 'w'): | |
| 288 pass | |
| 289 | |
| 290 return 0 | |
| 291 | |
| 292 if __name__ == '__main__': | |
| 293 sys.exit(main()) | |
| OLD | NEW |