scripts/dtrx

branch
trunk
changeset 22
b240777ae53e
parent 20
69c93c3e6972
child 23
039dd321a7d0
--- a/scripts/dtrx	Sat Apr 21 10:22:32 2007 -0400
+++ b/scripts/dtrx	Sat Apr 21 13:09:58 2007 -0400
@@ -45,10 +45,10 @@
 Public License for more details.""" % (VERSION,)
 
 MATCHING_DIRECTORY = 1
-# ONE_DIRECTORY = 2
+ONE_ENTRY = 2
 BOMB = 3
 EMPTY = 4
-COMPRESSED = 5
+ONE_ENTRY_KNOWN = 5
 
 EXTRACT_HERE = 1
 EXTRACT_WRAP = 2
@@ -171,28 +171,53 @@
     def prepare(self):
         pass
 
-    def check_contents(self):
-        archive_type = None
-        filenames = self.get_filenames()
+    def check_included_archive(self, filename):
+        if extractor_map.has_key(mimetypes.guess_type(filename)[0]):
+            self.included_archives.append(filename)
+
+    def check_first_filename(self, filenames):
         try:
-            filename = filenames.next()
-            if extractor_map.has_key(mimetypes.guess_type(filename)[0]):
-                self.included_archives.append(filename)
-            first_part = filename.split('/', 1)[0] + '/'
+            first_filename = filenames.next()
         except StopIteration:
             filenames.stop()
-            return EMPTY
+            return (None, None)
+        self.check_included_archive(first_filename)
+        parts = first_filename.split('/')
+        first_part = [parts[0]]
+        if parts[0] == '.':
+            first_part.append(parts[1])
+        return (first_filename, '/'.join(first_part + ['']))
+
+    def check_second_filename(self, filenames, first_part, first_filename):
+        try:
+            filename = filenames.next()
+        except StopIteration:
+            return ONE_ENTRY, first_filename
+        self.check_included_archive(filename)
+        if not filename.startswith(first_part):
+            return BOMB, None
+        return None, first_part
+        
+    def check_contents(self):
+        filenames = self.get_filenames()
+        first_filename, first_part = self.check_first_filename(filenames)
+        if first_filename is None:
+            return (EMPTY, None)
+        archive_type, type_info = self.check_second_filename(filenames,
+                                                             first_part,
+                                                             first_filename)
         for filename in filenames:
-            if extractor_map.has_key(mimetypes.guess_type(filename)[0]):
-                self.included_archives.append(filename)
-            if (archive_type is None) and (not filename.startswith(first_part)):
+            self.check_included_archive(filename)
+            if (archive_type != BOMB) and (not filename.startswith(first_part)):
                 archive_type = BOMB
+                type_info = None
         filenames.stop()
-        if archive_type:
-            return archive_type
-        if self.basename() == first_part[:-1]:
-            return MATCHING_DIRECTORY
-        return first_part
+        if archive_type is None:
+            if self.basename() == first_part[:-1]:
+                archive_type = MATCHING_DIRECTORY
+            else:
+                archive_type = ONE_ENTRY
+        return archive_type, type_info
 
     def basename(self):
         pieces = os.path.basename(self.filename).split('.')
@@ -270,7 +295,7 @@
 
     def check_contents(self):
         CpioExtractor.check_contents(self)
-        return BOMB
+        return (BOMB, None)
 
 
 class DebExtractor(TarExtractor):
@@ -291,7 +316,7 @@
 
     def check_contents(self):
         TarExtractor.check_contents(self)
-        return BOMB
+        return (BOMB, None)
         
 
 class CompressionExtractor(BaseExtractor):
@@ -308,19 +333,21 @@
         yield self.basename()
 
     def check_contents(self):
-        return COMPRESSED
+        return (ONE_ENTRY_KNOWN, self.basename())
 
     def extract(self, path):
         output = open(path, 'w')
+        self.archive.seek(0, 0)
         self.run(['cat'], "output write", stdin=self.archive, stdout=output)
         output.close()
         
 
 class BaseHandler(object):
-    def __init__(self, extractor, contents, options):
+    def __init__(self, extractor, contents, content_name, options):
         self.logger = logging.getLogger('dtrx-log')
         self.extractor = extractor
         self.contents = contents
+        self.content_name = content_name
         self.options = options
         self.target = None
 
@@ -353,12 +380,12 @@
 
 class FlatHandler(BaseHandler):
     def can_handle(contents, options):
-        return ((options.flat and (contents != COMPRESSED)) or
+        return ((options.flat and (contents != ONE_ENTRY_KNOWN)) or
                 (options.overwrite and (contents == MATCHING_DIRECTORY)))
     can_handle = staticmethod(can_handle)
 
-    def __init__(self, extractor, contents, options):
-        BaseHandler.__init__(self, extractor, contents, options)
+    def __init__(self, extractor, contents, content_name, options):
+        BaseHandler.__init__(self, extractor, contents, content_name, options)
         self.target = '.'
 
     def cleanup(self):
@@ -372,19 +399,19 @@
 
 class OverwriteHandler(BaseHandler):
     def can_handle(contents, options):
-        return ((options.flat and (contents == COMPRESSED)) or
+        return ((options.flat and (contents == ONE_ENTRY_KNOWN)) or
                 (options.overwrite and (contents != MATCHING_DIRECTORY)))
     can_handle = staticmethod(can_handle)
 
-    def __init__(self, extractor, contents, options):
-        BaseHandler.__init__(self, extractor, contents, options)
+    def __init__(self, extractor, contents, content_name, options):
+        BaseHandler.__init__(self, extractor, contents, content_name, options)
         self.target = self.extractor.basename()
         
 
 class MatchHandler(BaseHandler):
     def can_handle(contents, options):
         return ((contents == MATCHING_DIRECTORY) or
-                (hasattr(contents, 'encode') and
+                ((contents == ONE_ENTRY) and
                  (options.onedir_policy in (EXTRACT_RENAME, EXTRACT_HERE))))
     can_handle = staticmethod(can_handle)
 
@@ -392,9 +419,9 @@
         if self.contents == MATCHING_DIRECTORY:
             basename = destination = self.extractor.basename()
         elif self.options.onedir_policy == EXTRACT_HERE:
-            basename = destination = self.contents.rstrip('/')
+            basename = destination = self.content_name.rstrip('/')
         else:
-            basename = self.contents.rstrip('/')
+            basename = self.content_name.rstrip('/')
             destination = self.extractor.basename()
         self.target = tempdir = tempfile.mkdtemp(dir='.')
         result = BaseHandler.extract(self)
@@ -411,7 +438,7 @@
         return contents == EMPTY
     can_handle = staticmethod(can_handle)
 
-    def __init__(self, extractor, contents, options): pass
+    def __init__(self, extractor, contents, content_name, options): pass
     def extract(self): pass
     def cleanup(self): pass
 
@@ -421,8 +448,8 @@
         return True
     can_handle = staticmethod(can_handle)
 
-    def __init__(self, extractor, contents, options):
-        BaseHandler.__init__(self, extractor, contents, options)
+    def __init__(self, extractor, contents, content_name, options):
+        BaseHandler.__init__(self, extractor, contents, content_name, options)
         checker = self.extractor.name_checker(self.extractor.basename())
         self.target = checker.check()
 
@@ -496,7 +523,10 @@
         last_line = question.pop()
         while True:
             print "\n".join(question)
-            answer = raw_input(last_line)
+            try:
+                answer = raw_input(last_line)
+            except EOFError:
+                return answers['']
             try:
                 return answers[answer.lower()]
             except KeyError:
@@ -519,11 +549,10 @@
 
     def get_handler(self):
         try:
-            content = self.current_extractor.check_contents()
-            if hasattr(content, 'encode'):  # Archive contains one directory.
-                question = textwrap.wrap("%s contains one directory: %s.  %s" %
-                                         (self.current_filename, content,
-                                          "You can:"))
+            content, content_name = self.current_extractor.check_contents()
+            if content == ONE_ENTRY:
+                question = textwrap.wrap("%s contains one entry: %s." %
+                                         (self.current_filename, content_name))
                 question.extend(["You can:",
                                  " * extract it Inside another directory",
                                  " * extract it and Rename the directory",
@@ -534,7 +563,8 @@
             for handler in handlers:
                 if handler.can_handle(content, self.options):
                     self.current_handler = handler(self.current_extractor,
-                                                   content, self.options)
+                                                   content, content_name,
+                                                   self.options)
                     break
         except ExtractorError, error:
             return str(error)

mercurial