OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
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 """Creates a zip archive for the Chrome Remote Desktop Host installer. | 6 """Creates a zip archive for the Chrome Remote Desktop Host installer. |
7 | 7 |
8 This script builds a zip file that contains all the files needed to build an | 8 This script builds a zip file that contains all the files needed to build an |
9 installer for Chrome Remote Desktop Host. | 9 installer for Chrome Remote Desktop Host. |
10 | 10 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 zipfile_base = os.path.splitext(os.path.basename(zip_path))[0] | 64 zipfile_base = os.path.splitext(os.path.basename(zip_path))[0] |
65 zip = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) | 65 zip = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) |
66 for (root, dirs, files) in os.walk(directory): | 66 for (root, dirs, files) in os.walk(directory): |
67 for f in files: | 67 for f in files: |
68 full_path = os.path.join(root, f) | 68 full_path = os.path.join(root, f) |
69 rel_path = os.path.relpath(full_path, directory) | 69 rel_path = os.path.relpath(full_path, directory) |
70 zip.write(full_path, os.path.join(zipfile_base, rel_path)) | 70 zip.write(full_path, os.path.join(zipfile_base, rel_path)) |
71 zip.close() | 71 zip.close() |
72 | 72 |
73 | 73 |
74 def remapSrcFile(dst_root, src_root, src_file): | 74 def remapSrcFile(dst_root, src_roots, src_file): |
75 """Calculates destination file path and creates directory. | 75 """Calculates destination file path and creates directory. |
76 | 76 |
77 The |src_root| prefix is stripped from |src_file| before | 77 Any matching |src_roots| prefix is stripped from |src_file| before |
78 appending to |dst_root|. | 78 appending to |dst_root|. |
79 | 79 |
80 For example, given: | 80 For example, given: |
81 dst_root = /output | 81 dst_root = '/output' |
82 src_root = host/installer/mac | 82 src_roots = ['host/installer/mac'] |
83 src_file = host/installer/mac/Scripts/keystone_install.sh | 83 src_file = 'host/installer/mac/Scripts/keystone_install.sh' |
84 The final calculated path is: | 84 The final calculated path is: |
85 /output/Scripts/keystone_install.sh | 85 '/output/Scripts/keystone_install.sh' |
| 86 |
| 87 The |src_file| must match one of the |src_roots| prefixes. If there are no |
| 88 matches, then an error is reported. |
| 89 |
| 90 If multiple |src_roots| match, then only the first match is applied. Because |
| 91 of this, if you have roots that share a common prefix, the longest string |
| 92 should be first in this array. |
86 | 93 |
87 Args: | 94 Args: |
88 dst_root: Target directory where files are copied. | 95 dst_root: Target directory where files are copied. |
89 src_root: Path prefix which is stripped of |src_file| before appending | 96 src_roots: Array of path prefixes which will be stripped of |src_file| |
90 it to the |dst_root|. | 97 (if they match) before appending it to the |dst_root|. |
91 src_file: Source file to be copied. | 98 src_file: Source file to be copied. |
92 Returns: | 99 Returns: |
93 Full path to destination file in |dst_root|. | 100 Full path to destination file in |dst_root|. |
94 """ | 101 """ |
95 # Strip of directory prefix. | 102 # Strip of directory prefix. |
96 if src_file.startswith(src_root): | 103 found_root = False |
97 src_file = src_file[len(src_root):] | 104 for root in src_roots: |
| 105 if src_file.startswith(root): |
| 106 src_file = src_file[len(root):] |
| 107 found_root = True |
| 108 break |
| 109 |
| 110 if not found_root: |
| 111 error('Unable to match prefix for %s' % src_file) |
| 112 |
98 dst_file = os.path.join(dst_root, src_file) | 113 dst_file = os.path.join(dst_root, src_file) |
99 # Make sure target directory exists. | 114 # Make sure target directory exists. |
100 dst_dir = os.path.dirname(dst_file) | 115 dst_dir = os.path.dirname(dst_file) |
101 if not os.path.exists(dst_dir): | 116 if not os.path.exists(dst_dir): |
102 os.makedirs(dst_dir, 0775) | 117 os.makedirs(dst_dir, 0775) |
103 return dst_file | 118 return dst_file |
104 | 119 |
105 | 120 |
106 def copyFileWithDefs(src_file, dst_file, defs): | 121 def copyFileWithDefs(src_file, dst_file, defs): |
107 """Copies from src_file to dst_file, performing variable substitution. | 122 """Copies from src_file to dst_file, performing variable substitution. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 159 |
145 # Unzip into correct dir in out_dir. | 160 # Unzip into correct dir in out_dir. |
146 out_zip_path = remapSrcFile(out_dir, files_root, zip_file) | 161 out_zip_path = remapSrcFile(out_dir, files_root, zip_file) |
147 out_zip_dir = os.path.dirname(out_zip_path) | 162 out_zip_dir = os.path.dirname(out_zip_path) |
148 | 163 |
149 (src_dir, ignore1) = os.path.splitext(zip_file) | 164 (src_dir, ignore1) = os.path.splitext(zip_file) |
150 (base_dir_name, ignore2) = os.path.splitext(base_zip_name) | 165 (base_dir_name, ignore2) = os.path.splitext(base_zip_name) |
151 shutil.copytree(src_dir, os.path.join(out_zip_dir, base_dir_name)) | 166 shutil.copytree(src_dir, os.path.join(out_zip_dir, base_dir_name)) |
152 | 167 |
153 | 168 |
154 def buildHostArchive(temp_dir, zip_path, source_files_root, source_files, | 169 def buildHostArchive(temp_dir, zip_path, source_file_roots, source_files, |
155 gen_files, gen_files_dst, defs): | 170 gen_files, gen_files_dst, defs): |
156 """Builds a zip archive with the files needed to build the installer. | 171 """Builds a zip archive with the files needed to build the installer. |
157 | 172 |
158 Args: | 173 Args: |
159 temp_dir: Temporary dir used to build up the contents for the archive. | 174 temp_dir: Temporary dir used to build up the contents for the archive. |
160 zip_path: Full path to the zip file to create. | 175 zip_path: Full path to the zip file to create. |
161 source_files_root: Path prefix to strip off |files| when adding to archive. | 176 source_file_roots: Array of path prefixes to strip off |files| when adding |
| 177 to the archive. |
162 source_files: The array of files to add to archive. The path structure is | 178 source_files: The array of files to add to archive. The path structure is |
163 preserved (except for the |files_root| prefix). | 179 preserved (except for the |files_root| prefix). |
164 gen_files: Full path to binaries to add to archive. | 180 gen_files: Full path to binaries to add to archive. |
165 gen_files_dst: Relative path of where to add binary files in archive. | 181 gen_files_dst: Relative path of where to add binary files in archive. |
166 This array needs to parallel |binaries_src|. | 182 This array needs to parallel |binaries_src|. |
167 defs: Dictionary of variable definitions. | 183 defs: Dictionary of variable definitions. |
168 """ | 184 """ |
169 cleanDir(temp_dir) | 185 cleanDir(temp_dir) |
170 | 186 |
171 for f in source_files: | 187 for f in source_files: |
172 dst_file = remapSrcFile(temp_dir, source_files_root, f) | 188 dst_file = remapSrcFile(temp_dir, source_file_roots, f) |
173 base_file = os.path.basename(f) | 189 base_file = os.path.basename(f) |
174 (base, ext) = os.path.splitext(f) | 190 (base, ext) = os.path.splitext(f) |
175 if ext == '.zip': | 191 if ext == '.zip': |
176 copyZipIntoArchive(temp_dir, source_files_root, f) | 192 copyZipIntoArchive(temp_dir, source_file_roots, f) |
177 elif ext in ['.sh', '.packproj', '.plist']: | 193 elif ext in ['.sh', '.packproj', '.plist']: |
178 copyFileWithDefs(f, dst_file, defs) | 194 copyFileWithDefs(f, dst_file, defs) |
179 else: | 195 else: |
180 shutil.copy2(src_file, dst_file) | 196 shutil.copy2(f, dst_file) |
181 | 197 |
182 for bs, bd in zip(gen_files, gen_files_dst): | 198 for bs, bd in zip(gen_files, gen_files_dst): |
183 dst_file = remapSrcFile(temp_dir, source_files_root, bd) | 199 dst_file = os.path.join(temp_dir, bd) |
184 if os.path.isdir(bs): | 200 if os.path.isdir(bs): |
185 shutil.copytree(bs, dst_file) | 201 shutil.copytree(bs, dst_file) |
186 else: | 202 else: |
187 shutil.copy2(bs, dst_file) | 203 shutil.copy2(bs, dst_file) |
188 | 204 |
189 createZip(zip_path, temp_dir) | 205 createZip(zip_path, temp_dir) |
190 | 206 |
191 | 207 |
192 def error(msg): | 208 def error(msg): |
193 sys.stderr.write('ERROR: %s' % msg) | 209 sys.stderr.write('ERROR: %s\n' % msg) |
194 sys.exit(1) | 210 sys.exit(1) |
195 | 211 |
196 | 212 |
197 def usage(): | 213 def usage(): |
198 """Display basic usage information.""" | 214 """Display basic usage information.""" |
199 print ('Usage: %s\n' | 215 print ('Usage: %s\n' |
200 ' <temp-dir> <zip-path> <files-root-dir>\n' | 216 ' <temp-dir> <zip-path>\n' |
| 217 ' --source-file-roots <list of roots to strip off source files...>\n' |
201 ' --source-files <list of source files...>\n' | 218 ' --source-files <list of source files...>\n' |
202 ' --generated-files <list of generated target files...>\n' | 219 ' --generated-files <list of generated target files...>\n' |
203 ' --generated-files-dst <dst for each generated file...>\n' | 220 ' --generated-files-dst <dst for each generated file...>\n' |
204 ' --defs <list of VARIABLE=value definitions...>' | 221 ' --defs <list of VARIABLE=value definitions...>' |
205 ) % sys.argv[0] | 222 ) % sys.argv[0] |
206 | 223 |
207 | 224 |
208 def main(): | 225 def main(): |
209 if len(sys.argv) < 3: | 226 if len(sys.argv) < 2: |
210 usage() | 227 usage() |
211 error('Too few arguments') | 228 error('Too few arguments') |
212 | 229 |
213 temp_dir = sys.argv[1] | 230 temp_dir = sys.argv[1] |
214 zip_path = sys.argv[2] | 231 zip_path = sys.argv[2] |
215 source_files_root = sys.argv[3] | |
216 | 232 |
217 arg_mode = '' | 233 arg_mode = '' |
| 234 source_file_roots = [] |
218 source_files = [] | 235 source_files = [] |
219 generated_files = [] | 236 generated_files = [] |
220 generated_files_dst = [] | 237 generated_files_dst = [] |
221 definitions = [] | 238 definitions = [] |
222 for arg in sys.argv[4:]: | 239 for arg in sys.argv[3:]: |
223 if arg == '--source-files': | 240 if arg == '--source-file-roots': |
| 241 arg_mode = 'src-roots' |
| 242 elif arg == '--source-files': |
224 arg_mode = 'files' | 243 arg_mode = 'files' |
225 elif arg == '--generated-files': | 244 elif arg == '--generated-files': |
226 arg_mode = 'gen-src' | 245 arg_mode = 'gen-src' |
227 elif arg == '--generated-files-dst': | 246 elif arg == '--generated-files-dst': |
228 arg_mode = 'gen-dst' | 247 arg_mode = 'gen-dst' |
229 elif arg == '--defs': | 248 elif arg == '--defs': |
230 arg_mode = 'defs' | 249 arg_mode = 'defs' |
231 | 250 |
| 251 elif arg_mode == 'src-roots': |
| 252 source_file_roots.append(arg) |
232 elif arg_mode == 'files': | 253 elif arg_mode == 'files': |
233 source_files.append(arg) | 254 source_files.append(arg) |
234 elif arg_mode == 'gen-src': | 255 elif arg_mode == 'gen-src': |
235 generated_files.append(arg) | 256 generated_files.append(arg) |
236 elif arg_mode == 'gen-dst': | 257 elif arg_mode == 'gen-dst': |
237 generated_files_dst.append(arg) | 258 generated_files_dst.append(arg) |
238 elif arg_mode == 'defs': | 259 elif arg_mode == 'defs': |
239 definitions.append(arg) | 260 definitions.append(arg) |
240 else: | 261 else: |
241 usage() | 262 usage() |
242 error('Expected --source-files') | 263 error('Expected --source-files') |
243 | 264 |
244 # Make sure at least one file was specified. | 265 # Make sure at least one file was specified. |
245 if len(source_files) == 0 and len(generated_files) == 0: | 266 if len(source_files) == 0 and len(generated_files) == 0: |
246 error('At least one input file must be specified.') | 267 error('At least one input file must be specified.') |
247 | 268 |
248 # Ensure that source_files_root ends with a directory separator. | 269 # Ensure that each path in source_file_roots ends with a directory separator. |
249 if source_files_root[-1:] != os.sep: | 270 for root in source_file_roots: |
250 source_files_root += os.sep | 271 if root[-1:] != os.sep: |
| 272 error('Each source-file-root should end with a "\": %s' % root) |
| 273 |
| 274 # Sort roots to ensure the longest one is first. See comment in remapSrcFile |
| 275 # for why this is necessary. |
| 276 source_file_roots.sort(key=len, reverse=True) |
251 | 277 |
252 # Verify that the 2 generated_files arrays have the same number of elements. | 278 # Verify that the 2 generated_files arrays have the same number of elements. |
253 if len(generated_files) != len(generated_files_dst): | 279 if len(generated_files) != len(generated_files_dst): |
254 error('len(--generated-files) != len(--generated-files-dst)') | 280 error('len(--generated-files) != len(--generated-files-dst)') |
255 | 281 |
256 defs = buildDefDictionary(definitions) | 282 defs = buildDefDictionary(definitions) |
257 | 283 |
258 result = buildHostArchive(temp_dir, zip_path, source_files_root, | 284 result = buildHostArchive(temp_dir, zip_path, source_file_roots, |
259 source_files, generated_files, generated_files_dst, | 285 source_files, generated_files, generated_files_dst, |
260 defs) | 286 defs) |
261 | 287 |
262 return 0 | 288 return 0 |
263 | 289 |
264 | 290 |
265 if __name__ == '__main__': | 291 if __name__ == '__main__': |
266 sys.exit(main()) | 292 sys.exit(main()) |
OLD | NEW |