# HG changeset patch # User brett # Date 1177818756 14400 # Node ID 039dd321a7d0ed1f74af0889f36e61ebb1c9fa29 # Parent b240777ae53e24bb9bfe9f56c894f76ba21f6201 [svn] If an archive contains other archives, and the user didn't specify that they wanted recursion, prompt them to find out what they want to do. This required some changes in the way prompting for one-item archives works too, because if an archive inside another archive is itself a one-item archive, things get really weird. I'm still not really sure what the right policy is for that. I'm not wild about this code. It feels like programming a bunch of special cases. I need to figure out a better way to abstract it. I'm thinking some kind of Policy class.... diff -r b240777ae53e -r 039dd321a7d0 scripts/dtrx --- a/scripts/dtrx Sat Apr 21 13:09:58 2007 -0400 +++ b/scripts/dtrx Sat Apr 28 23:52:36 2007 -0400 @@ -1,7 +1,7 @@ #!/usr/bin/env python # # dtrx -- Intelligently extract various archive types. -# Copyright (c) 2006 Brett Smith . +# Copyright (c) 2006, 2007 Brett Smith . # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -32,7 +32,7 @@ VERSION = "4.0" VERSION_BANNER = """dtrx version %s -Copyright (c) 2006 Brett Smith +Copyright (c) 2006, 2007 Brett Smith This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -54,6 +54,11 @@ EXTRACT_WRAP = 2 EXTRACT_RENAME = 3 +RECURSE_ALWAYS = 1 +RECURSE_ONCE = 2 +RECURSE_NOT_NOW = 3 +RECURSE_NEVER = 4 + mimetypes.encodings_map.setdefault('.bz2', 'bzip2') mimetypes.types_map['.exe'] = 'application/x-msdos-program' @@ -468,6 +473,9 @@ class ExtractorApplication(object): policy_answers = {'h': EXTRACT_HERE, 'i': EXTRACT_WRAP, 'r': EXTRACT_RENAME, '': EXTRACT_WRAP} + recursive_answers = {'o': RECURSE_ONCE, 'a': RECURSE_ALWAYS, + 'n': RECURSE_NOT_NOW, 'v': RECURSE_NEVER, + '': RECURSE_NOT_NOW} def __init__(self, arguments): self.parse_options(arguments) @@ -503,7 +511,6 @@ action='store_true', default=False, help="don't ask how to handle special cases") self.options, filenames = parser.parse_args(arguments) - self.options.onedir_policy = self.policy_answers[''] if not filenames: parser.error("you did not list any archives") self.archives = {os.path.realpath(os.curdir): filenames} @@ -550,7 +557,7 @@ def get_handler(self): try: content, content_name = self.current_extractor.check_contents() - if content == ONE_ENTRY: + if (content == ONE_ENTRY) and (self.options.onedir_policy is None): question = textwrap.wrap("%s contains one entry: %s." % (self.current_filename, content_name)) question.extend(["You can:", @@ -569,8 +576,34 @@ except ExtractorError, error: return str(error) + def get_recursion_policy(self): + if len(self.current_extractor.included_archives) > 1: + question = ("%s contains %s other archive files." % + (self.current_filename, + len(self.current_extractor.included_archives))) + else: + question = ("%s contains another archive: %s." % + (self.current_filename, + self.current_extractor.included_archives[0])) + question = textwrap.wrap(question) + question.extend(["You can:", + " * Always extract included archives", + " * extract included archives this Once", + " * choose Not to extract included archives", + " * neVer extract included archives", + "What do you want to do? (a/o/N/v) "]) + self.options.recurse_policy = self.ask_question(question, + self.recursive_answers) + def recurse(self): - if not self.options.recursive: + if not self.current_extractor.included_archives: + return + if self.options.recurse_policy is None: + if self.options.recursive: + self.options.recurse_policy = RECURSE_ALWAYS + else: + self.get_recursion_policy() + if self.options.recurse_policy in (RECURSE_NOT_NOW, RECURSE_NEVER): return for filename in self.current_extractor.included_archives: tail_path, basename = os.path.split(filename) @@ -595,9 +628,17 @@ self.failures.append(self.current_filename) def extract(self): + self.options.recurse_policy = None + first_run = True while self.archives: self.current_directory, filenames = self.archives.popitem() + self.options.onedir_policy = EXTRACT_WRAP for filename in filenames: + if first_run: + self.options.onedir_policy = None + if self.options.recurse_policy not in (RECURSE_ALWAYS, + RECURSE_NEVER): + self.options.recurse_policy = None os.chdir(self.current_directory) self.current_filename = filename success = (self.report(self.get_extractor) and @@ -608,6 +649,7 @@ name)) and success) self.recurse() self.record_status(success) + first_run = False def show_contents(self): for filename in self.current_extractor.get_filenames(): diff -r b240777ae53e -r 039dd321a7d0 tests/tests.yml --- a/tests/tests.yml Sat Apr 21 13:09:58 2007 -0400 +++ b/tests/tests.yml Sat Apr 28 23:52:36 2007 -0400 @@ -43,7 +43,7 @@ mkdir test-badperms cd test-badperms tar -xf ../test-badperms.tar - chmod 755 testdir + chmod 700 testdir posttest: | if [ "x`cat test-recursive-badperms/test-badperms/testdir/testfile`" = \ "xhey" ]; then exit 0; else exit 1; fi @@ -274,3 +274,73 @@ input: h baseline: | tar -zxf $1 + +- name: two one-item archives with different answers + filenames: test-onedir.tar.gz test-onedir.tar.gz + options: "" + input: | + h + r + baseline: | + tar -zxf $1 + mv test test-onedir + tar -zxf $1 + +- name: interactive recursion (always) + filenames: test-recursive-badperms.tar.bz2 test-recursive-badperms.tar.bz2 + options: "" + input: | + i + a + i + baseline: | + extract() { + mkdir test-recursive-badperms$2 + cd test-recursive-badperms$2 + tar -jxf ../$1 + mkdir test-badperms + cd test-badperms + tar -xf ../test-badperms.tar + chmod 700 testdir + cd ../.. + } + extract $1 + extract $1 .1 + +- name: interactive recursion (once) + filenames: test-recursive-badperms.tar.bz2 test-recursive-badperms.tar.bz2 + options: "" + input: | + i + o + i + n + baseline: | + mkdir test-recursive-badperms + cd test-recursive-badperms + tar -jxf ../$1 + mkdir test-badperms + cd test-badperms + tar -xf ../test-badperms.tar + chmod 700 testdir + cd ../.. + mkdir test-recursive-badperms.1 + cd test-recursive-badperms.1 + tar -jxf ../$1 + +- name: interactive recursion (never) + filenames: test-recursive-badperms.tar.bz2 test-recursive-badperms.tar.bz2 + options: "" + input: | + i + v + i + baseline: | + extract() { + mkdir test-recursive-badperms$2 + cd test-recursive-badperms$2 + tar -jxf ../$1 + cd .. + } + extract $1 + extract $1 .1