Chromium Code Reviews| 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 from __future__ import print_function | |
| 7 | |
| 6 import fnmatch | 8 import fnmatch |
| 7 import glob | 9 import glob |
| 8 import optparse | 10 import argparse |
| 9 import os | 11 import os |
| 10 import posixpath | 12 import posixpath |
| 11 import shutil | 13 import shutil |
| 12 import stat | 14 import stat |
| 13 import sys | 15 import sys |
| 14 import time | 16 import time |
| 15 import zipfile | 17 import zipfile |
| 16 | 18 |
| 17 if sys.version_info < (2, 6, 0): | 19 if sys.version_info < (2, 6, 0): |
| 18 sys.stderr.write("python 2.6 or later is required run this script\n") | 20 sys.stderr.write("python 2.6 or later is required run this script\n") |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 filter.""" | 57 filter.""" |
| 56 if options.includes: | 58 if options.includes: |
| 57 if not IncludeFiles(options.includes, [src]): | 59 if not IncludeFiles(options.includes, [src]): |
| 58 return | 60 return |
| 59 | 61 |
| 60 if options.excludes: | 62 if options.excludes: |
| 61 if not ExcludeFiles(options.excludes, [src]): | 63 if not ExcludeFiles(options.excludes, [src]): |
| 62 return | 64 return |
| 63 | 65 |
| 64 if options.verbose: | 66 if options.verbose: |
| 65 print 'cp %s %s' % (src, dst) | 67 print('cp %s %s' % (src, dst)) |
| 66 | 68 |
| 67 # If the source is a single file, copy it individually | 69 # If the source is a single file, copy it individually |
| 68 if os.path.isfile(src): | 70 if os.path.isfile(src): |
| 69 # We can not copy over a directory with a file. | 71 # We can not copy over a directory with a file. |
| 70 if os.path.exists(dst): | 72 if os.path.exists(dst): |
| 71 if not os.path.isfile(dst): | 73 if not os.path.isfile(dst): |
| 72 msg = "cp: cannot overwrite non-file '%s' with file." % dst | 74 msg = "cp: cannot overwrite non-file '%s' with file." % dst |
| 73 raise OSError(msg) | 75 raise OSError(msg) |
| 74 # If the destination exists as a file, remove it before copying to avoid | 76 # If the destination exists as a file, remove it before copying to avoid |
| 75 # 'readonly' issues. | 77 # 'readonly' issues. |
| 76 os.remove(dst) | 78 os.remove(dst) |
| 77 | 79 |
| 78 # Now copy to the non-existent fully qualified target | 80 # Now copy to the non-existent fully qualified target |
| 79 shutil.copy(src, dst) | 81 shutil.copy(src, dst) |
| 80 return | 82 return |
| 81 | 83 |
| 82 # Otherwise it's a directory, ignore it unless allowed | 84 # Otherwise it's a directory, ignore it unless allowed |
| 83 if os.path.isdir(src): | 85 if os.path.isdir(src): |
| 84 if not options.recursive: | 86 if not options.recursive: |
| 85 print "cp: omitting directory '%s'" % src | 87 print("cp: omitting directory '%s'" % src) |
| 86 return | 88 return |
| 87 | 89 |
| 88 # We can not copy over a file with a directory. | 90 # We can not copy over a file with a directory. |
| 89 if os.path.exists(dst): | 91 if os.path.exists(dst): |
| 90 if not os.path.isdir(dst): | 92 if not os.path.isdir(dst): |
| 91 msg = "cp: cannot overwrite non-directory '%s' with directory." % dst | 93 msg = "cp: cannot overwrite non-directory '%s' with directory." % dst |
| 92 raise OSError(msg) | 94 raise OSError(msg) |
| 93 else: | 95 else: |
| 94 # if it didn't exist, create the directory | 96 # if it didn't exist, create the directory |
| 95 os.makedirs(dst) | 97 os.makedirs(dst) |
| 96 | 98 |
| 97 # Now copy all members | 99 # Now copy all members |
| 98 for filename in os.listdir(src): | 100 for filename in os.listdir(src): |
| 99 srcfile = os.path.join(src, filename) | 101 srcfile = os.path.join(src, filename) |
| 100 dstfile = os.path.join(dst, filename) | 102 dstfile = os.path.join(dst, filename) |
| 101 CopyPath(options, srcfile, dstfile) | 103 CopyPath(options, srcfile, dstfile) |
| 102 return | 104 return |
| 103 | 105 |
| 104 | 106 |
| 105 def Copy(args): | 107 def Copy(args): |
| 106 """A Unix cp style copy. | 108 """A Unix cp style copy. |
| 107 | 109 |
| 108 Copies multiple sources to a single destination using the normal cp | 110 Copies multiple sources to a single destination using the normal cp |
| 109 semantics. In addition, it support inclusion and exclusion filters which | 111 semantics. In addition, it support inclusion and exclusion filters which |
| 110 allows the copy to skip certain types of files.""" | 112 allows the copy to skip certain types of files.""" |
| 111 parser = optparse.OptionParser(usage='usage: cp [Options] sources... dest') | 113 parser = argparse.ArgumentParser(usage='cp [Options] sources... dest') |
|
binji
2014/11/13 23:57:04
use doc?
Sam Clegg
2014/11/30 17:55:13
Done.
| |
| 112 parser.add_option( | 114 parser.add_argument( |
| 113 '-R', '-r', '--recursive', dest='recursive', action='store_true', | 115 '-R', '-r', '--recursive', dest='recursive', action='store_true', |
| 114 default=False, | 116 default=False, |
| 115 help='copy directories recursively.') | 117 help='copy directories recursively.') |
| 116 parser.add_option( | 118 parser.add_argument( |
| 117 '-v', '--verbose', dest='verbose', action='store_true', | 119 '-v', '--verbose', dest='verbose', action='store_true', |
| 118 default=False, | 120 default=False, |
| 119 help='verbose output.') | 121 help='verbose output.') |
| 120 parser.add_option( | 122 parser.add_argument( |
| 121 '--include', dest='includes', action='append', default=[], | 123 '--include', dest='includes', action='append', default=[], |
| 122 help='include files matching this expression.') | 124 help='include files matching this expression.') |
| 123 parser.add_option( | 125 parser.add_argument( |
| 124 '--exclude', dest='excludes', action='append', default=[], | 126 '--exclude', dest='excludes', action='append', default=[], |
| 125 help='exclude files matching this expression.') | 127 help='exclude files matching this expression.') |
| 126 options, files = parser.parse_args(args) | 128 parser.add_argument('src', nargs='+', help='files to copy') |
|
binji
2014/11/13 23:57:04
srcs
Sam Clegg
2014/11/30 17:55:13
Done.
| |
| 127 if len(files) < 2: | 129 parser.add_argument('dest', help='destination') |
| 128 parser.error('ERROR: expecting SOURCE(s) and DEST.') | |
| 129 | 130 |
| 130 srcs = files[:-1] | 131 options = parser.parse_args(args) |
| 131 dst = files[-1] | |
| 132 | 132 |
| 133 src_list = [] | 133 src_list = [] |
| 134 for src in srcs: | 134 for src in options.src: |
| 135 files = glob.glob(src) | 135 files = glob.glob(src) |
| 136 if not files: | 136 if not files: |
| 137 raise OSError('cp: no such file or directory: ' + src) | 137 raise OSError('cp: no such file or directory: ' + src) |
| 138 if files: | 138 if files: |
| 139 src_list.extend(files) | 139 src_list.extend(files) |
| 140 | 140 |
| 141 for src in src_list: | 141 for src in src_list: |
| 142 # If the destination is a directory, then append the basename of the src | 142 # If the destination is a directory, then append the basename of the src |
| 143 # to the destination. | 143 # to the destination. |
| 144 if os.path.isdir(dst): | 144 if os.path.isdir(options.dest): |
| 145 CopyPath(options, src, os.path.join(dst, os.path.basename(src))) | 145 CopyPath(options, src, os.path.join(options.dest, os.path.basename(src))) |
| 146 else: | 146 else: |
| 147 CopyPath(options, src, dst) | 147 CopyPath(options, src, options.dest) |
| 148 | 148 |
| 149 | 149 |
| 150 def Mkdir(args): | 150 def Mkdir(args): |
| 151 """A Unix style mkdir""" | 151 """A Unix style mkdir""" |
| 152 parser = optparse.OptionParser(usage='usage: mkdir [Options] DIRECTORY...') | 152 parser = argparse.ArgumentParser(usage='mkdir [Options] DIRECTORY...') |
|
binji
2014/11/13 23:57:04
use doc?
Sam Clegg
2014/11/30 17:55:13
Done.
| |
| 153 parser.add_option( | 153 parser.add_argument( |
| 154 '-p', '--parents', dest='parents', action='store_true', | 154 '-p', '--parents', dest='parents', action='store_true', |
| 155 default=False, | 155 default=False, |
| 156 help='ignore existing parents, create parents as needed.') | 156 help='ignore existing parents, create parents as needed.') |
| 157 parser.add_option( | 157 parser.add_argument( |
| 158 '-v', '--verbose', dest='verbose', action='store_true', | 158 '-v', '--verbose', dest='verbose', action='store_true', |
| 159 default=False, | 159 default=False, |
| 160 help='verbose output.') | 160 help='verbose output.') |
| 161 parser.add_argument('dirs', nargs='+', help='directoy to create') | |
|
binji
2014/11/13 23:57:04
sp: directories
Sam Clegg
2014/11/30 17:55:13
Done.
| |
| 161 | 162 |
| 162 options, dsts = parser.parse_args(args) | 163 options = parser.parse_args(args) |
| 163 if len(dsts) < 1: | |
| 164 parser.error('ERROR: expecting DIRECTORY...') | |
| 165 | 164 |
| 166 for dst in dsts: | 165 for dst in options.dirs: |
| 167 if options.verbose: | 166 if options.verbose: |
| 168 print 'mkdir ' + dst | 167 print('mkdir %s' % dst) |
| 169 try: | 168 try: |
| 170 os.makedirs(dst) | 169 os.makedirs(dst) |
| 171 except OSError: | 170 except OSError: |
| 172 if os.path.isdir(dst): | 171 if os.path.isdir(dst): |
| 173 if options.parents: | 172 if options.parents: |
| 174 continue | 173 continue |
| 175 raise OSError('mkdir: Already exists: ' + dst) | 174 raise OSError('mkdir: Already exists: ' + dst) |
| 176 else: | 175 else: |
| 177 raise OSError('mkdir: Failed to create: ' + dst) | 176 raise OSError('mkdir: Failed to create: ' + dst) |
| 178 return 0 | 177 return 0 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 193 if os.path.exists(dst): | 192 if os.path.exists(dst): |
| 194 if options.force: | 193 if options.force: |
| 195 Remove(['-vfr', dst]) | 194 Remove(['-vfr', dst]) |
| 196 if os.path.exists(dst): | 195 if os.path.exists(dst): |
| 197 raise OSError('mv: FAILED TO REMOVE ' + dst) | 196 raise OSError('mv: FAILED TO REMOVE ' + dst) |
| 198 else: | 197 else: |
| 199 raise OSError('mv: already exists ' + dst) | 198 raise OSError('mv: already exists ' + dst) |
| 200 for _ in range(5): | 199 for _ in range(5): |
| 201 try: | 200 try: |
| 202 os.rename(src, dst) | 201 os.rename(src, dst) |
| 203 return | 202 break |
| 204 except OSError as error: | 203 except OSError as error: |
| 205 print 'Failed on %s with %s, retrying' % (src, error) | 204 print('Failed on %s with %s, retrying' % (src, error)) |
| 206 time.sleep(5) | 205 time.sleep(5) |
| 207 print 'Gave up.' | 206 else: |
|
binji
2014/11/13 23:57:04
I find for/else confusing, but OK
Sam Clegg
2014/11/30 17:55:13
I will re-write this as a function and/or context
| |
| 208 raise OSError('mv: ' + error) | 207 print('Gave up.') |
| 208 raise OSError('mv: ' + error) | |
| 209 | 209 |
| 210 | 210 |
| 211 def Move(args): | 211 def Move(args): |
| 212 parser = optparse.OptionParser(usage='usage: mv [Options] sources... dest') | 212 parser = argparse.ArgumentParser(usage='mv [Options] sources... dest') |
|
binji
2014/11/13 23:57:04
use doc?
Sam Clegg
2014/11/30 17:55:13
Done.
| |
| 213 parser.add_option( | 213 parser.add_argument( |
| 214 '-v', '--verbose', dest='verbose', action='store_true', | 214 '-v', '--verbose', dest='verbose', action='store_true', |
| 215 default=False, | 215 default=False, |
| 216 help='verbose output.') | 216 help='verbose output.') |
| 217 parser.add_option( | 217 parser.add_argument( |
| 218 '-f', '--force', dest='force', action='store_true', | 218 '-f', '--force', dest='force', action='store_true', |
| 219 default=False, | 219 default=False, |
| 220 help='force, do not error it files already exist.') | 220 help='force, do not error it files already exist.') |
| 221 options, files = parser.parse_args(args) | 221 parser.add_argument('source', nargs='+') |
|
binji
2014/11/13 23:57:04
srcs
| |
| 222 if len(files) < 2: | 222 parser.add_argument('dest') |
| 223 parser.error('ERROR: expecting SOURCE... and DEST.') | |
| 224 | 223 |
| 225 srcs = files[:-1] | 224 options = parser.parse_args(args) |
| 226 dst = files[-1] | |
| 227 | 225 |
| 228 if options.verbose: | 226 if options.verbose: |
| 229 print 'mv %s %s' % (' '.join(srcs), dst) | 227 print('mv %s %s' % (' '.join(options.srcs), options.dest)) |
| 230 | 228 |
| 231 for src in srcs: | 229 for src in options.srcs: |
| 232 MovePath(options, src, dst) | 230 MovePath(options, src, options.dest) |
| 233 return 0 | 231 return 0 |
| 234 | 232 |
| 235 | 233 |
| 236 def Remove(args): | 234 def Remove(args): |
| 237 """A Unix style rm. | 235 """A Unix style rm. |
| 238 | 236 |
| 239 Removes the list of paths. Because of possible temporary failures do to locks | 237 Removes the list of paths. Because of possible temporary failures do to locks |
| 240 (such as anti-virus software on Windows), the function will retry up to five | 238 (such as anti-virus software on Windows), the function will retry up to five |
| 241 times.""" | 239 times.""" |
| 242 parser = optparse.OptionParser(usage='usage: rm [Options] PATHS...') | 240 parser = argparse.ArgumentParser(usage='rm [Options] PATHS...') |
| 243 parser.add_option( | 241 parser.add_argument( |
| 244 '-R', '-r', '--recursive', dest='recursive', action='store_true', | 242 '-R', '-r', '--recursive', dest='recursive', action='store_true', |
| 245 default=False, | 243 default=False, |
| 246 help='remove directories recursively.') | 244 help='remove directories recursively.') |
| 247 parser.add_option( | 245 parser.add_argument( |
| 248 '-v', '--verbose', dest='verbose', action='store_true', | 246 '-v', '--verbose', dest='verbose', action='store_true', |
| 249 default=False, | 247 default=False, |
| 250 help='verbose output.') | 248 help='verbose output.') |
| 251 parser.add_option( | 249 parser.add_argument( |
| 252 '-f', '--force', dest='force', action='store_true', | 250 '-f', '--force', dest='force', action='store_true', |
| 253 default=False, | 251 default=False, |
| 254 help='force, do not error it files does not exist.') | 252 help='force, do not error it files does not exist.') |
| 255 options, files = parser.parse_args(args) | 253 parser.add_argument('files', nargs='+') |
| 256 if len(files) < 1: | 254 options = parser.parse_args(args) |
| 257 parser.error('ERROR: expecting FILE...') | |
| 258 | 255 |
| 259 try: | 256 try: |
| 260 for pattern in files: | 257 for pattern in options.files: |
| 261 dst_files = glob.glob(pattern) | 258 dst_files = glob.glob(pattern) |
| 262 if not dst_files: | 259 if not dst_files: |
| 263 # Ignore non existing files when using force | 260 # Ignore non existing files when using force |
| 264 if options.force: | 261 if options.force: |
| 265 continue | 262 continue |
| 266 raise OSError('rm: no such file or directory: ' + pattern) | 263 raise OSError('rm: no such file or directory: ' + pattern) |
| 267 | 264 |
| 268 for dst in dst_files: | 265 for dst in dst_files: |
| 269 if options.verbose: | 266 if options.verbose: |
| 270 print 'rm ' + dst | 267 print('rm ' + dst) |
| 271 | 268 |
| 272 if os.path.isfile(dst) or os.path.islink(dst): | 269 if os.path.isfile(dst) or os.path.islink(dst): |
| 273 for i in range(5): | 270 for _ in range(5): |
| 274 try: | 271 try: |
| 275 # Check every time, since it may have been deleted after the | 272 # Check every time, since it may have been deleted after the |
| 276 # previous failed attempt. | 273 # previous failed attempt. |
| 277 if os.path.isfile(dst) or os.path.islink(dst): | 274 if os.path.isfile(dst) or os.path.islink(dst): |
| 278 os.remove(dst) | 275 os.remove(dst) |
| 279 break | 276 break |
| 280 except OSError as error: | 277 except OSError as error: |
| 281 if i == 5: | 278 print('Failed remove with %s, retrying' % error) |
| 282 print 'Gave up.' | |
| 283 raise OSError('rm: ' + str(error)) | |
| 284 print 'Failed remove with %s, retrying' % error | |
| 285 time.sleep(5) | 279 time.sleep(5) |
| 280 else: | |
| 281 print('Gave up.') | |
| 282 raise OSError('rm: ' + str(error)) | |
| 286 | 283 |
| 287 if options.recursive: | 284 if options.recursive: |
| 288 for i in range(5): | 285 for _ in range(5): |
| 289 try: | 286 try: |
| 290 if os.path.isdir(dst): | 287 if os.path.isdir(dst): |
| 291 shutil.rmtree(dst) | 288 shutil.rmtree(dst) |
| 292 break | 289 break |
| 293 except OSError as error: | 290 except OSError as error: |
| 294 if i == 5: | 291 print('Failed rmtree with %s, retrying' % error) |
| 295 print 'Gave up.' | |
| 296 raise OSError('rm: ' + str(error)) | |
| 297 print 'Failed rmtree with %s, retrying' % error | |
| 298 time.sleep(5) | 292 time.sleep(5) |
| 293 else: | |
| 294 print('Gave up.') | |
| 295 raise OSError('rm: ' + str(error)) | |
| 299 | 296 |
| 300 except OSError as error: | 297 except OSError as error: |
| 301 print error | 298 print(error) |
| 299 | |
| 302 return 0 | 300 return 0 |
| 303 | 301 |
| 304 | 302 |
| 305 def MakeZipPath(os_path, isdir, iswindows): | 303 def MakeZipPath(os_path, isdir, iswindows): |
| 306 """Changes a path into zipfile format. | 304 """Changes a path into zipfile format. |
| 307 | 305 |
| 308 # doctest doesn't seem to honor r'' strings, so the backslashes need to be | 306 # doctest doesn't seem to honor r'' strings, so the backslashes need to be |
| 309 # escaped. | 307 # escaped. |
| 310 >>> MakeZipPath(r'C:\\users\\foobar\\blah', False, True) | 308 >>> MakeZipPath(r'C:\\users\\foobar\\blah', False, True) |
| 311 'users/foobar/blah' | 309 'users/foobar/blah' |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 336 | 334 |
| 337 | 335 |
| 338 def OSMakeZipPath(os_path): | 336 def OSMakeZipPath(os_path): |
| 339 return MakeZipPath(os_path, os.path.isdir(os_path), sys.platform == 'win32') | 337 return MakeZipPath(os_path, os.path.isdir(os_path), sys.platform == 'win32') |
| 340 | 338 |
| 341 | 339 |
| 342 def Zip(args): | 340 def Zip(args): |
| 343 """A Unix style zip. | 341 """A Unix style zip. |
| 344 | 342 |
| 345 Compresses the listed files.""" | 343 Compresses the listed files.""" |
| 346 parser = optparse.OptionParser(usage='usage: zip [Options] zipfile list') | 344 parser = argparse.ArgumentParser(description=Zip.__doc__) |
| 347 parser.add_option( | 345 parser.add_argument( |
| 348 '-r', dest='recursive', action='store_true', | 346 '-r', dest='recursive', action='store_true', |
| 349 default=False, | 347 default=False, |
| 350 help='recurse into directories') | 348 help='recurse into directories') |
| 351 parser.add_option( | 349 parser.add_argument( |
| 352 '-q', dest='quiet', action='store_true', | 350 '-q', dest='quiet', action='store_true', |
| 353 default=False, | 351 default=False, |
| 354 help='quiet operation') | 352 help='quiet operation') |
| 355 options, files = parser.parse_args(args) | 353 parser.add_argument('zipfile') |
| 356 if len(files) < 2: | 354 parser.add_argument('filenames', nargs='+') |
| 357 parser.error('ERROR: expecting ZIPFILE and LIST.') | 355 options = parser.parse_args(args) |
| 358 | |
| 359 dest_zip = files[0] | |
| 360 src_args = files[1:] | |
| 361 | 356 |
| 362 src_files = [] | 357 src_files = [] |
| 363 for src_arg in src_args: | 358 for filename in options.filenames: |
| 364 globbed_src_args = glob.glob(src_arg) | 359 globbed_src_args = glob.glob(filename) |
| 365 if not globbed_src_args: | 360 if not globbed_src_args: |
| 366 if not options.quiet: | 361 if not options.quiet: |
| 367 print 'zip warning: name not matched: %s' % (src_arg,) | 362 print('zip warning: name not matched: %s' % filename) |
| 368 | 363 |
| 369 for src_file in globbed_src_args: | 364 for src_file in globbed_src_args: |
| 370 src_file = os.path.normpath(src_file) | 365 src_file = os.path.normpath(src_file) |
| 371 src_files.append(src_file) | 366 src_files.append(src_file) |
| 372 if options.recursive and os.path.isdir(src_file): | 367 if options.recursive and os.path.isdir(src_file): |
| 373 for root, dirs, files in os.walk(src_file): | 368 for root, dirs, files in os.walk(src_file): |
| 374 for dirname in dirs: | 369 for dirname in dirs: |
| 375 src_files.append(os.path.join(root, dirname)) | 370 src_files.append(os.path.join(root, dirname)) |
| 376 for filename in files: | 371 for filename in files: |
| 377 src_files.append(os.path.join(root, filename)) | 372 src_files.append(os.path.join(root, filename)) |
| 378 | 373 |
| 379 zip_stream = None | |
| 380 # zip_data represents a list of the data to be written or appended to the | 374 # zip_data represents a list of the data to be written or appended to the |
| 381 # zip_stream. It is a list of tuples: | 375 # zip_stream. It is a list of tuples: |
| 382 # (OS file path, zip path/zip file info, and file data) | 376 # (OS file path, zip path/zip file info, and file data) |
| 383 # In all cases one of the |os path| or the |file data| will be None. | 377 # In all cases one of the |os path| or the |file data| will be None. |
| 384 # |os path| is None when there is no OS file to write to the archive (i.e. | 378 # |os path| is None when there is no OS file to write to the archive (i.e. |
| 385 # the file data already existed in the archive). |file data| is None when the | 379 # the file data already existed in the archive). |file data| is None when the |
| 386 # file is new (never existed in the archive) or being updated. | 380 # file is new (never existed in the archive) or being updated. |
| 387 zip_data = [] | 381 zip_data = [] |
| 388 new_files_to_add = [OSMakeZipPath(src_file) for src_file in src_files] | 382 new_files_to_add = [OSMakeZipPath(src_file) for src_file in src_files] |
| 389 zip_path_to_os_path_dict = dict((new_files_to_add[i], src_files[i]) | 383 zip_path_to_os_path_dict = dict((new_files_to_add[i], src_files[i]) |
| 390 for i in range(len(src_files))) | 384 for i in range(len(src_files))) |
| 391 write_mode = 'a' | 385 write_mode = 'a' |
| 392 try: | 386 if os.path.exists(options.zipfile): |
| 393 zip_stream = zipfile.ZipFile(dest_zip, 'r') | 387 with zipfile.ZipFile(options.zipfile, 'r') as zip_stream: |
| 394 files_to_update = set(new_files_to_add).intersection( | 388 try: |
| 395 set(zip_stream.namelist())) | 389 files_to_update = set(new_files_to_add).intersection( |
| 396 if files_to_update: | 390 set(zip_stream.namelist())) |
| 397 # As far as I can tell, there is no way to update a zip entry using | 391 if files_to_update: |
| 398 # zipfile; the best you can do is rewrite the archive. | 392 # As far as I can tell, there is no way to update a zip entry using |
| 399 # Iterate through the zipfile to maintain file order. | 393 # zipfile; the best you can do is rewrite the archive. |
| 400 write_mode = 'w' | 394 # Iterate through the zipfile to maintain file order. |
| 401 for zip_path in zip_stream.namelist(): | 395 write_mode = 'w' |
| 402 if zip_path in files_to_update: | 396 for zip_path in zip_stream.namelist(): |
| 403 os_path = zip_path_to_os_path_dict[zip_path] | 397 if zip_path in files_to_update: |
| 404 zip_data.append((os_path, zip_path, None)) | 398 os_path = zip_path_to_os_path_dict[zip_path] |
| 405 new_files_to_add.remove(zip_path) | 399 zip_data.append((os_path, zip_path, None)) |
| 406 else: | 400 new_files_to_add.remove(zip_path) |
| 407 file_bytes = zip_stream.read(zip_path) | 401 else: |
| 408 file_info = zip_stream.getinfo(zip_path) | 402 file_bytes = zip_stream.read(zip_path) |
| 409 zip_data.append((None, file_info, file_bytes)) | 403 file_info = zip_stream.getinfo(zip_path) |
| 410 except IOError: | 404 zip_data.append((None, file_info, file_bytes)) |
| 411 pass | 405 except IOError: |
| 412 finally: | 406 pass |
| 413 if zip_stream: | |
| 414 zip_stream.close() | |
| 415 | 407 |
| 416 for zip_path in new_files_to_add: | 408 for zip_path in new_files_to_add: |
| 417 zip_data.append((zip_path_to_os_path_dict[zip_path], zip_path, None)) | 409 zip_data.append((zip_path_to_os_path_dict[zip_path], zip_path, None)) |
| 418 | 410 |
| 419 if not zip_data: | 411 if not zip_data: |
| 420 print 'zip error: Nothing to do! (%s)' % (dest_zip,) | 412 print('zip error: Nothing to do! (%s)' % options.zipfile) |
| 421 return 1 | 413 return 1 |
| 422 | 414 |
| 423 try: | 415 with zipfile.ZipFile(options.zipfile, write_mode, |
| 424 zip_stream = zipfile.ZipFile(dest_zip, write_mode, zipfile.ZIP_DEFLATED) | 416 zipfile.ZIP_DEFLATED) as zip_stream: |
| 425 for os_path, file_info_or_zip_path, file_bytes in zip_data: | 417 for os_path, file_info_or_zip_path, file_bytes in zip_data: |
| 426 if isinstance(file_info_or_zip_path, zipfile.ZipInfo): | 418 if isinstance(file_info_or_zip_path, zipfile.ZipInfo): |
| 427 zip_path = file_info_or_zip_path.filename | 419 zip_path = file_info_or_zip_path.filename |
| 428 else: | 420 else: |
| 429 zip_path = file_info_or_zip_path | 421 zip_path = file_info_or_zip_path |
| 430 | 422 |
| 431 if os_path: | 423 if os_path: |
| 432 st = os.stat(os_path) | 424 st = os.stat(os_path) |
| 433 if stat.S_ISDIR(st.st_mode): | 425 if stat.S_ISDIR(st.st_mode): |
| 434 # Python 2.6 on the buildbots doesn't support writing directories to | 426 # Python 2.6 on the buildbots doesn't support writing directories to |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 451 zip_stream.writestr(file_info_or_zip_path, file_bytes) | 443 zip_stream.writestr(file_info_or_zip_path, file_bytes) |
| 452 | 444 |
| 453 if not options.quiet: | 445 if not options.quiet: |
| 454 if zip_path in new_files_to_add: | 446 if zip_path in new_files_to_add: |
| 455 operation = 'adding' | 447 operation = 'adding' |
| 456 else: | 448 else: |
| 457 operation = 'updating' | 449 operation = 'updating' |
| 458 zip_info = zip_stream.getinfo(zip_path) | 450 zip_info = zip_stream.getinfo(zip_path) |
| 459 if (zip_info.compress_type == zipfile.ZIP_STORED or | 451 if (zip_info.compress_type == zipfile.ZIP_STORED or |
| 460 zip_info.file_size == 0): | 452 zip_info.file_size == 0): |
| 461 print ' %s: %s (stored 0%%)' % (operation, zip_path) | 453 print(' %s: %s (stored 0%%)' % (operation, zip_path)) |
| 462 elif zip_info.compress_type == zipfile.ZIP_DEFLATED: | 454 elif zip_info.compress_type == zipfile.ZIP_DEFLATED: |
| 463 print ' %s: %s (deflated %d%%)' % (operation, zip_path, | 455 print(' %s: %s (deflated %d%%)' % (operation, zip_path, |
| 464 100 - zip_info.compress_size * 100 / zip_info.file_size) | 456 100 - zip_info.compress_size * 100 / zip_info.file_size)) |
| 465 finally: | |
| 466 zip_stream.close() | |
| 467 | 457 |
| 468 return 0 | 458 return 0 |
| 469 | 459 |
| 470 | 460 |
| 471 def FindExeInPath(filename): | 461 def FindExeInPath(filename): |
| 472 env_path = os.environ.get('PATH', '') | 462 env_path = os.environ.get('PATH', '') |
| 473 paths = env_path.split(os.pathsep) | 463 paths = env_path.split(os.pathsep) |
| 474 | 464 |
| 475 def IsExecutableFile(path): | 465 def IsExecutableFile(path): |
| 476 return os.path.isfile(path) and os.access(path, os.X_OK) | 466 return os.path.isfile(path) and os.access(path, os.X_OK) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 487 | 477 |
| 488 def Which(args): | 478 def Which(args): |
| 489 """A Unix style which. | 479 """A Unix style which. |
| 490 | 480 |
| 491 Looks for all arguments in the PATH environment variable, and prints their | 481 Looks for all arguments in the PATH environment variable, and prints their |
| 492 path if they are executable files. | 482 path if they are executable files. |
| 493 | 483 |
| 494 Note: If you pass an argument with a path to which, it will just test if it | 484 Note: If you pass an argument with a path to which, it will just test if it |
| 495 is executable, not if it is in the path. | 485 is executable, not if it is in the path. |
| 496 """ | 486 """ |
| 497 parser = optparse.OptionParser(usage='usage: which args...') | 487 parser = argparse.ArgumentParser(description=Which.__doc__) |
| 498 _, files = parser.parse_args(args) | 488 parser.add_argument('files', nargs='+') |
| 499 if not files: | 489 options = parser.parse_args(args) |
| 500 return 0 | |
| 501 | 490 |
| 502 retval = 0 | 491 retval = 0 |
| 503 for filename in files: | 492 for filename in options.files: |
| 504 fullname = FindExeInPath(filename) | 493 fullname = FindExeInPath(filename) |
| 505 if fullname: | 494 if fullname: |
| 506 print fullname | 495 print(fullname) |
| 507 else: | 496 else: |
| 508 retval = 1 | 497 retval = 1 |
| 509 | 498 |
| 510 return retval | 499 return retval |
| 511 | 500 |
| 512 | 501 |
| 513 FuncMap = { | 502 FuncMap = { |
| 514 'cp': Copy, | 503 'cp': Copy, |
| 515 'mkdir': Mkdir, | 504 'mkdir': Mkdir, |
| 516 'mv': Move, | 505 'mv': Move, |
| 517 'rm': Remove, | 506 'rm': Remove, |
| 518 'zip': Zip, | 507 'zip': Zip, |
| 519 'which': Which, | 508 'which': Which, |
| 520 } | 509 } |
| 521 | 510 |
| 522 | 511 |
| 523 def main(args): | 512 def main(args): |
| 524 if not args: | 513 if not args: |
| 525 print 'No command specified' | 514 print('No command specified') |
| 526 print 'Available commands: %s' % ' '.join(FuncMap) | 515 print('Available commands: %s' % ' '.join(FuncMap)) |
| 527 return 1 | 516 return 1 |
| 528 func_name = args[0] | 517 func_name = args[0] |
| 529 func = FuncMap.get(func_name) | 518 func = FuncMap.get(func_name) |
| 530 if not func: | 519 if not func: |
| 531 print 'Do not recognize command: %s' % func_name | 520 print('Do not recognize command: %s' % func_name) |
| 532 print 'Available commands: %s' % ' '.join(FuncMap) | 521 print('Available commands: %s' % ' '.join(FuncMap)) |
| 533 return 1 | 522 return 1 |
| 534 try: | 523 try: |
| 535 return func(args[1:]) | 524 return func(args[1:]) |
| 536 except KeyboardInterrupt: | 525 except KeyboardInterrupt: |
| 537 print '%s: interrupted' % func_name | 526 print('%s: interrupted' % func_name) |
| 538 return 1 | 527 return 1 |
| 539 | 528 |
| 540 if __name__ == '__main__': | 529 if __name__ == '__main__': |
| 541 sys.exit(main(sys.argv[1:])) | 530 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |