scripts/x

branch
trunk
changeset 17
481a2b4be471
parent 16
29794d4d41aa
child 18
1600807a32bd
equal deleted inserted replaced
16:29794d4d41aa 17:481a2b4be471
68 68
69 class FilenameChecker(object): 69 class FilenameChecker(object):
70 def __init__(self, original_name): 70 def __init__(self, original_name):
71 self.original_name = original_name 71 self.original_name = original_name
72 72
73 def is_free(self, filename=None): 73 def is_free(self, filename):
74 if filename is None:
75 filename = self.original_name
76 return self._is_free(filename)
77
78 def _is_free(self, filename):
79 return not os.path.exists(filename) 74 return not os.path.exists(filename)
80 75
81 def check(self): 76 def check(self):
82 for suffix in [''] + ['.%s' % (x,) for x in range(1, 10)]: 77 for suffix in [''] + ['.%s' % (x,) for x in range(1, 10)]:
83 filename = '%s%s' % (self.original_name, suffix) 78 filename = '%s%s' % (self.original_name, suffix)
86 raise ValueError("all alternatives for name %s taken" % 81 raise ValueError("all alternatives for name %s taken" %
87 (self.original_name,)) 82 (self.original_name,))
88 83
89 84
90 class DirectoryChecker(FilenameChecker): 85 class DirectoryChecker(FilenameChecker):
91 def _is_free(self, filename): 86 def is_free(self, filename):
92 try: 87 try:
93 os.mkdir(filename) 88 os.mkdir(filename)
94 except OSError, error: 89 except OSError, error:
95 if error.errno == errno.EEXIST: 90 if error.errno == errno.EEXIST:
96 return False 91 return False
320 def __init__(self, extractor, contents, options): 315 def __init__(self, extractor, contents, options):
321 self.logger = logging.getLogger('x-log') 316 self.logger = logging.getLogger('x-log')
322 self.extractor = extractor 317 self.extractor = extractor
323 self.contents = contents 318 self.contents = contents
324 self.options = options 319 self.options = options
325 320 self.target = None
326 ## def extract(self):
327 ## raise NotImplementedError
328 ## checker = self.extractor.name_checker(self.extractor.basename())
329 ## if self.options.flat:
330 ## self.target = '.'
331 ## return self.do_extract('.')
332 ## elif self.options.overwrite or checker.is_free():
333 ## self.target = self.extractor.basename()
334 ## return self.overwrite()
335 ## else:
336 ## self.target = checker.check()
337 ## return self.safe_extract()
338 321
339 def extract(self): 322 def extract(self):
340 try: 323 try:
341 self.extractor.extract(self.target) 324 self.extractor.extract(self.target)
342 except ExtractorError, error: 325 except (ExtractorError, IOError, OSError), error:
343 return str(error) 326 return str(error)
344 327
345 def cleanup(self): 328 def cleanup(self):
346 raise NotImplementedError 329 if self.target is None:
347 if self.options.flat: 330 return
348 self.cleanup_files()
349 else:
350 self.cleanup_directory()
351
352 def cleanup_files(self):
353 for filename in self.extractor.get_filenames():
354 stat_info = os.stat(filename)
355 perms = stat.S_IRUSR | stat.S_IWUSR
356 if stat.S_ISDIR(stat_info.st_mode):
357 perms |= stat.S_IXUSR
358 os.chmod(filename, stat_info.st_mode | perms)
359
360 def cleanup_directory(self):
361 command = 'find' 331 command = 'find'
362 status = subprocess.call(['find', self.target, '-type', 'd', 332 status = subprocess.call(['find', self.target, '-type', 'd',
363 '-exec', 'chmod', 'u+rwx', '{}', ';']) 333 '-exec', 'chmod', 'u+rwx', '{}', ';'])
364 if status == 0: 334 if status == 0:
365 command = 'chmod' 335 command = 'chmod'
374 # Flat Overwrite None 344 # Flat Overwrite None
375 # File basename basename FilenameChecked 345 # File basename basename FilenameChecked
376 # Match . . tempdir + checked 346 # Match . . tempdir + checked
377 # Bomb . basename DirectoryChecked 347 # Bomb . basename DirectoryChecked
378 348
379
380 class FlatHandler(BaseHandler): 349 class FlatHandler(BaseHandler):
381 def can_handle(contents, options): 350 def can_handle(contents, options):
382 return ((options.flat and (contents != COMPRESSED)) or 351 return ((options.flat and (contents != COMPRESSED)) or
383 (options.overwrite and (contents == MATCHING_DIRECTORY))) 352 (options.overwrite and (contents == MATCHING_DIRECTORY)))
384 can_handle = staticmethod(can_handle) 353 can_handle = staticmethod(can_handle)
385 354
386 target = '.' 355 def __init__(self, extractor, contents, options):
387 cleanup = BaseHandler.cleanup_files 356 BaseHandler.__init__(self, extractor, contents, options)
357 self.target = '.'
358
359 def cleanup(self):
360 for filename in self.extractor.get_filenames():
361 stat_info = os.stat(filename)
362 perms = stat.S_IRUSR | stat.S_IWUSR
363 if stat.S_ISDIR(stat_info.st_mode):
364 perms |= stat.S_IXUSR
365 os.chmod(filename, stat_info.st_mode | perms)
388 366
389 367
390 class OverwriteHandler(BaseHandler): 368 class OverwriteHandler(BaseHandler):
391 def can_handle(contents, options): 369 def can_handle(contents, options):
392 return ((options.flat and (contents == COMPRESSED)) or 370 return ((options.flat and (contents == COMPRESSED)) or
394 can_handle = staticmethod(can_handle) 372 can_handle = staticmethod(can_handle)
395 373
396 def __init__(self, extractor, contents, options): 374 def __init__(self, extractor, contents, options):
397 BaseHandler.__init__(self, extractor, contents, options) 375 BaseHandler.__init__(self, extractor, contents, options)
398 self.target = self.extractor.basename() 376 self.target = self.extractor.basename()
399
400 cleanup = BaseHandler.cleanup_directory
401 377
402 378
403 class MatchHandler(BaseHandler): 379 class MatchHandler(BaseHandler):
404 def can_handle(contents, options): 380 def can_handle(contents, options):
405 return contents == MATCHING_DIRECTORY 381 return contents == MATCHING_DIRECTORY
406 can_handle = staticmethod(can_handle) 382 can_handle = staticmethod(can_handle)
407 383
408 def extract(self): 384 def extract(self):
409 basename = self.extractor.basename() 385 basename = self.extractor.basename()
410 self.target = tempfile.mkdtemp() 386 self.target = tempfile.mkdtemp(dir='.')
411 result = BaseHandler.extract(self) 387 result = BaseHandler.extract(self)
412 if result is None: 388 if result is None:
413 tempdir = self.target 389 tempdir = self.target
414 checker = self.extractor.name_checker(basename) 390 checker = self.extractor.name_checker(basename)
415 self.target = checker.check() 391 self.target = checker.check()
416 os.rename(os.path.join(tempdir, basename), self.target) 392 os.rename(os.path.join(tempdir, basename), self.target)
417 os.rmdir(tempdir) 393 os.rmdir(tempdir)
418 return result 394 return result
419 395
420 cleanup = BaseHandler.cleanup_directory
421
422 396
423 class EmptyHandler(object): 397 class EmptyHandler(object):
424 def can_handle(contents, options): 398 def can_handle(contents, options):
425 return contents == EMPTY 399 return contents == EMPTY
426 can_handle = staticmethod(can_handle) 400 can_handle = staticmethod(can_handle)
438 def __init__(self, extractor, contents, options): 412 def __init__(self, extractor, contents, options):
439 BaseHandler.__init__(self, extractor, contents, options) 413 BaseHandler.__init__(self, extractor, contents, options)
440 checker = self.extractor.name_checker(self.extractor.basename()) 414 checker = self.extractor.name_checker(self.extractor.basename())
441 self.target = checker.check() 415 self.target = checker.check()
442 416
443 cleanup = BaseHandler.cleanup_directory 417
444
445
446 ## class BombHandler(BaseHandler):
447 ## def safe_extract(self):
448 ## return self.do_extract(self.target)
449
450 ## def overwrite(self):
451 ## self.target = self.extractor.basename()
452 ## return self.do_extract(self.target)
453
454
455 extractor_map = {'application/x-tar': TarExtractor, 418 extractor_map = {'application/x-tar': TarExtractor,
456 'application/zip': ZipExtractor, 419 'application/zip': ZipExtractor,
457 'application/x-msdos-program': ZipExtractor, 420 'application/x-msdos-program': ZipExtractor,
458 'application/x-debian-package': DebExtractor, 421 'application/x-debian-package': DebExtractor,
459 'application/x-redhat-package-manager': RPMExtractor, 422 'application/x-redhat-package-manager': RPMExtractor,
538 directory = os.path.join(self.current_directory, 501 directory = os.path.join(self.current_directory,
539 self.current_handler.target, tail_path) 502 self.current_handler.target, tail_path)
540 self.archives.setdefault(directory, []).append(basename) 503 self.archives.setdefault(directory, []).append(basename)
541 504
542 def report(self, function, *args): 505 def report(self, function, *args):
543 error = function(*args) 506 try:
507 error = function(*args)
508 except (ExtractorError, IOError, OSError), exception:
509 error = str(exception)
544 if error: 510 if error:
545 self.logger.error("%s: %s", self.current_filename, error) 511 self.logger.error("%s: %s", self.current_filename, error)
546 return False 512 return False
547 return True 513 return True
548 514
550 while self.archives: 516 while self.archives:
551 self.current_directory, filenames = self.archives.popitem() 517 self.current_directory, filenames = self.archives.popitem()
552 for filename in filenames: 518 for filename in filenames:
553 os.chdir(self.current_directory) 519 os.chdir(self.current_directory)
554 self.current_filename = filename 520 self.current_filename = filename
555 self.cleanup_actions = []
556 success = self.report(self.get_extractor) 521 success = self.report(self.get_extractor)
557 if success: 522 if success:
558 for name in 'extract', 'cleanup': 523 for name in 'extract', 'cleanup':
559 success = (self.report(getattr(self.current_handler, 524 success = (self.report(getattr(self.current_handler,
560 name)) and success) 525 name)) and success)

mercurial