Sun, 30 Aug 2009 11:46:30 -0400
add support for xz compression
1 | 1 | #!/usr/bin/env python |
92
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
2 | # -*- coding: utf-8 -*- |
1 | 3 | # |
19 | 4 | # dtrx -- Intelligently extract various archive types. |
121 | 5 | # Copyright © 2006-2009 Brett Smith <brettcsmith@brettcsmith.org> |
114
d2a28fe2a8ff
use a real UTF-8 copyright symbol everywhere
Brett Smith <brettcsmith@brettcsmith.org>
parents:
111
diff
changeset
|
6 | # Copyright © 2008 Peter Kelemen <Peter.Kelemen@gmail.com> |
1 | 7 | # |
8 | # This program is free software; you can redistribute it and/or modify it | |
9 | # under the terms of the GNU General Public License as published by the | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
10 | # Free Software Foundation; either version 3 of the License, or (at your |
1 | 11 | # option) any later version. |
12 | # | |
13 | # This program is distributed in the hope that it will be useful, but | |
14 | # WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | |
16 | # Public License for more details. | |
17 | # | |
18 | # You should have received a copy of the GNU General Public License along | |
42 | 19 | # with this program; if not, see <http://www.gnu.org/licenses/>. |
1 | 20 | |
72
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
21 | # Python 2.3 string methods: 'rfind', 'rindex', 'rjust', 'rstrip' |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
22 | |
5 | 23 | import errno |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
24 | import fcntl |
12
5d202467c589
[svn] Introduce a real logging system. Right now all this really gets us is the
brett
parents:
11
diff
changeset
|
25 | import logging |
1 | 26 | import mimetypes |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
27 | import optparse |
1 | 28 | import os |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
29 | import re |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
30 | import shutil |
48 | 31 | import signal |
15
28dbd52a8bb8
[svn] Add a -f/--flat option, which will extract the archive contents into the
brett
parents:
14
diff
changeset
|
32 | import stat |
110
6cbe6cb5a903
Use string.rindex (which is in Python 2.3) instead of my own version.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
109
diff
changeset
|
33 | import string |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
34 | import struct |
1 | 35 | import subprocess |
36 | import sys | |
37 | import tempfile | |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
38 | import termios |
20
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
39 | import textwrap |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
40 | import traceback |
1 | 41 | |
94
6cdbdffa2e2e
Avoid DeprecationWarning under Python 2.6. Part of the 6.3 release.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
93
diff
changeset
|
42 | try: |
6cdbdffa2e2e
Avoid DeprecationWarning under Python 2.6. Part of the 6.3 release.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
93
diff
changeset
|
43 | set |
6cdbdffa2e2e
Avoid DeprecationWarning under Python 2.6. Part of the 6.3 release.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
93
diff
changeset
|
44 | except NameError: |
6cdbdffa2e2e
Avoid DeprecationWarning under Python 2.6. Part of the 6.3 release.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
93
diff
changeset
|
45 | from sets import Set as set |
36
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
46 | |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
47 | VERSION = "6.6" |
19 | 48 | VERSION_BANNER = """dtrx version %s |
121 | 49 | Copyright © 2006-2009 Brett Smith <brettcsmith@brettcsmith.org> |
117
c43771363c6f
convert more copyright symbols
Brett Smith <brettcsmith@brettcsmith.org>
parents:
115
diff
changeset
|
50 | Copyright © 2008 Peter Kelemen <Peter.Kelemen@gmail.com> |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
51 | |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
52 | This program is free software; you can redistribute it and/or modify it |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
53 | under the terms of the GNU General Public License as published by the |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
54 | Free Software Foundation; either version 3 of the License, or (at your |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
55 | option) any later version. |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
56 | |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
57 | This program is distributed in the hope that it will be useful, but |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
58 | WITHOUT ANY WARRANTY; without even the implied warranty of |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
59 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
60 | Public License for more details.""" % (VERSION,) |
1 | 61 | |
62 | MATCHING_DIRECTORY = 1 | |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
63 | ONE_ENTRY_KNOWN = 2 |
1 | 64 | BOMB = 3 |
65 | EMPTY = 4 | |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
66 | ONE_ENTRY_FILE = 'file' |
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
67 | ONE_ENTRY_DIRECTORY = 'directory' |
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
68 | |
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
69 | ONE_ENTRY_UNKNOWN = [ONE_ENTRY_FILE, ONE_ENTRY_DIRECTORY] |
1 | 70 | |
20
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
71 | EXTRACT_HERE = 1 |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
72 | EXTRACT_WRAP = 2 |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
73 | EXTRACT_RENAME = 3 |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
74 | |
23
039dd321a7d0
[svn] If an archive contains other archives, and the user didn't specify that
brett
parents:
22
diff
changeset
|
75 | RECURSE_ALWAYS = 1 |
039dd321a7d0
[svn] If an archive contains other archives, and the user didn't specify that
brett
parents:
22
diff
changeset
|
76 | RECURSE_ONCE = 2 |
039dd321a7d0
[svn] If an archive contains other archives, and the user didn't specify that
brett
parents:
22
diff
changeset
|
77 | RECURSE_NOT_NOW = 3 |
039dd321a7d0
[svn] If an archive contains other archives, and the user didn't specify that
brett
parents:
22
diff
changeset
|
78 | RECURSE_NEVER = 4 |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
79 | RECURSE_LIST = 5 |
23
039dd321a7d0
[svn] If an archive contains other archives, and the user didn't specify that
brett
parents:
22
diff
changeset
|
80 | |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
81 | mimetypes.encodings_map.setdefault('.bz2', 'bzip2') |
34
a8f875e02c83
[svn] Add support for LZMA compression. Holy crap that was easy.
brett
parents:
33
diff
changeset
|
82 | mimetypes.encodings_map.setdefault('.lzma', 'lzma') |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
83 | mimetypes.encodings_map.setdefault('.xz', 'xz') |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
84 | mimetypes.types_map.setdefault('.gem', 'application/x-ruby-gem') |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
85 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
86 | logger = logging.getLogger('dtrx-log') |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
87 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
88 | class FilenameChecker(object): |
58 | 89 | free_func = os.open |
90 | free_args = (os.O_CREAT | os.O_EXCL,) | |
91 | free_close = os.close | |
92 | ||
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
93 | def __init__(self, original_name): |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
94 | self.original_name = original_name |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
95 | |
17
481a2b4be471
[svn] Lots of tests for various boundary cases, and slightly better handling for
brett
parents:
16
diff
changeset
|
96 | def is_free(self, filename): |
58 | 97 | try: |
98 | result = self.free_func(filename, *self.free_args) | |
99 | except OSError, error: | |
100 | if error.errno == errno.EEXIST: | |
101 | return False | |
102 | raise | |
103 | if self.free_close: | |
104 | self.free_close(result) | |
105 | return True | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
106 | |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
107 | def create(self): |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
108 | fd, filename = tempfile.mkstemp(prefix=self.original_name + '.', |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
109 | dir='.') |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
110 | os.close(fd) |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
111 | return filename |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
112 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
113 | def check(self): |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
114 | for suffix in [''] + ['.%s' % (x,) for x in range(1, 10)]: |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
115 | filename = '%s%s' % (self.original_name, suffix) |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
116 | if self.is_free(filename): |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
117 | return filename |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
118 | return self.create() |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
119 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
120 | |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
121 | class DirectoryChecker(FilenameChecker): |
58 | 122 | free_func = os.mkdir |
123 | free_args = () | |
124 | free_close = None | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
125 | |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
126 | def create(self): |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
127 | return tempfile.mkdtemp(prefix=self.original_name + '.', dir='.') |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
128 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
129 | |
1 | 130 | class ExtractorError(Exception): |
131 | pass | |
132 | ||
133 | ||
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
134 | class ExtractorUnusable(Exception): |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
135 | pass |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
136 | |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
137 | |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
138 | EXTRACTION_ERRORS = (ExtractorError, ExtractorUnusable, OSError, IOError) |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
139 | |
1 | 140 | class BaseExtractor(object): |
34
a8f875e02c83
[svn] Add support for LZMA compression. Holy crap that was easy.
brett
parents:
33
diff
changeset
|
141 | decoders = {'bzip2': 'bzcat', 'gzip': 'zcat', 'compress': 'zcat', |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
142 | 'lzma': 'lzcat', 'xz': 'xzcat'} |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
143 | name_checker = DirectoryChecker |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
144 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
145 | def __init__(self, filename, encoding): |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
146 | if encoding and (not self.decoders.has_key(encoding)): |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
147 | raise ValueError("unrecognized encoding %s" % (encoding,)) |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
148 | self.filename = os.path.realpath(filename) |
1 | 149 | self.encoding = encoding |
69
35a2f45cdd3b
Count files in the archive and report that in the recursion prompt.
Brett Smith <brett@brettcsmith.org>
parents:
66
diff
changeset
|
150 | self.file_count = 0 |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
151 | self.included_archives = [] |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
152 | self.target = None |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
153 | self.content_type = None |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
154 | self.content_name = None |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
155 | self.pipes = [] |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
156 | self.stderr = tempfile.TemporaryFile() |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
157 | self.exit_codes = [] |
5 | 158 | try: |
159 | self.archive = open(filename, 'r') | |
160 | except (IOError, OSError), error: | |
161 | raise ExtractorError("could not open %s: %s" % | |
162 | (filename, error.strerror)) | |
1 | 163 | if encoding: |
164 | self.pipe([self.decoders[encoding]], "decoding") | |
165 | self.prepare() | |
166 | ||
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
167 | def pipe(self, command, description="extraction"): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
168 | self.pipes.append((command, description)) |
1 | 169 | |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
170 | def first_bad_exit_code(self): |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
171 | for index, code in enumerate(self.exit_codes): |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
172 | if code != 0: |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
173 | return index |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
174 | return None |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
175 | |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
176 | def add_process(self, processes, command, stdin, stdout): |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
177 | try: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
178 | processes.append(subprocess.Popen(command, stdin=stdin, |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
179 | stdout=stdout, |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
180 | stderr=self.stderr)) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
181 | except OSError, error: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
182 | if error.errno == errno.ENOENT: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
183 | raise ExtractorUnusable("could not run %s" % (command[0],)) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
184 | raise |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
185 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
186 | def run_pipes(self, final_stdout=None): |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
187 | if not self.pipes: |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
188 | return |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
189 | elif final_stdout is None: |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
190 | final_stdout = open('/dev/null', 'w') |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
191 | num_pipes = len(self.pipes) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
192 | last_pipe = num_pipes - 1 |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
193 | processes = [] |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
194 | for index, command in enumerate([pipe[0] for pipe in self.pipes]): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
195 | if index == 0: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
196 | stdin = self.archive |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
197 | else: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
198 | stdin = processes[-1].stdout |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
199 | if index == last_pipe: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
200 | stdout = final_stdout |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
201 | else: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
202 | stdout = subprocess.PIPE |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
203 | self.add_process(processes, command, stdin, stdout) |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
204 | self.exit_codes = [pipe.wait() for pipe in processes] |
1 | 205 | self.archive.close() |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
206 | for index in range(last_pipe): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
207 | processes[index].stdout.close() |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
208 | self.archive = final_stdout |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
209 | |
1 | 210 | def prepare(self): |
211 | pass | |
212 | ||
47 | 213 | def check_included_archives(self): |
214 | if (self.content_name is None) or (not self.content_name.endswith('/')): | |
215 | self.included_root = './' | |
216 | else: | |
217 | self.included_root = self.content_name | |
218 | start_index = len(self.included_root) | |
219 | for path, dirname, filenames in os.walk(self.included_root): | |
69
35a2f45cdd3b
Count files in the archive and report that in the recursion prompt.
Brett Smith <brett@brettcsmith.org>
parents:
66
diff
changeset
|
220 | self.file_count += len(filenames) |
47 | 221 | path = path[start_index:] |
222 | for filename in filenames: | |
223 | if (ExtractorBuilder.try_by_mimetype(filename) or | |
224 | ExtractorBuilder.try_by_extension(filename)): | |
225 | self.included_archives.append(os.path.join(path, filename)) | |
22
b240777ae53e
[svn] Improve the way we check archive contents. If all the entries look like
brett
parents:
20
diff
changeset
|
226 | |
b240777ae53e
[svn] Improve the way we check archive contents. If all the entries look like
brett
parents:
20
diff
changeset
|
227 | def check_contents(self): |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
228 | if not self.contents: |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
229 | self.content_type = EMPTY |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
230 | elif len(self.contents) == 1: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
231 | if self.basename() == self.contents[0]: |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
232 | self.content_type = MATCHING_DIRECTORY |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
233 | elif os.path.isdir(self.contents[0]): |
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
234 | self.content_type = ONE_ENTRY_DIRECTORY |
22
b240777ae53e
[svn] Improve the way we check archive contents. If all the entries look like
brett
parents:
20
diff
changeset
|
235 | else: |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
236 | self.content_type = ONE_ENTRY_FILE |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
237 | self.content_name = self.contents[0] |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
238 | if os.path.isdir(self.contents[0]): |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
239 | self.content_name += '/' |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
240 | else: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
241 | self.content_type = BOMB |
47 | 242 | self.check_included_archives() |
1 | 243 | |
244 | def basename(self): | |
5 | 245 | pieces = os.path.basename(self.filename).split('.') |
2
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
246 | extension = '.' + pieces[-1] |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
247 | if mimetypes.encodings_map.has_key(extension): |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
248 | pieces.pop() |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
249 | extension = '.' + pieces[-1] |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
250 | if (mimetypes.types_map.has_key(extension) or |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
251 | mimetypes.common_types.has_key(extension) or |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
252 | mimetypes.suffix_map.has_key(extension)): |
1 | 253 | pieces.pop() |
254 | return '.'.join(pieces) | |
255 | ||
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
256 | def get_stderr(self): |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
257 | self.stderr.seek(0, 0) |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
258 | errors = self.stderr.read(-1) |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
259 | self.stderr.close() |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
260 | return errors |
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
261 | |
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
262 | def check_success(self, got_output): |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
263 | error_index = self.first_bad_exit_code() |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
264 | if (not got_output) and (error_index is not None): |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
265 | command = ' '.join(self.pipes[error_index][0]) |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
266 | raise ExtractorError("%s error: '%s' returned status code %s" % |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
267 | (self.pipes[error_index][1], command, |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
268 | self.exit_codes[error_index])) |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
269 | |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
270 | def extract_archive(self): |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
271 | self.pipe(self.extract_pipe) |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
272 | self.run_pipes() |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
273 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
274 | def extract(self): |
40
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
275 | try: |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
276 | self.target = tempfile.mkdtemp(prefix='.dtrx-', dir='.') |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
277 | except (OSError, IOError), error: |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
278 | raise ExtractorError("cannot extract here: %s" % (error.strerror,)) |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
279 | old_path = os.path.realpath(os.curdir) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
280 | os.chdir(self.target) |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
281 | try: |
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
282 | self.archive.seek(0, 0) |
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
283 | self.extract_archive() |
91
ececf7836546
Make sure all extractors get self.contents defined.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
284 | self.contents = os.listdir('.') |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
285 | self.check_contents() |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
286 | self.check_success(self.content_type != EMPTY) |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
287 | except EXTRACTION_ERRORS: |
48 | 288 | self.archive.close() |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
289 | os.chdir(old_path) |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
290 | shutil.rmtree(self.target, ignore_errors=True) |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
291 | raise |
48 | 292 | self.archive.close() |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
293 | os.chdir(old_path) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
294 | |
108
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
295 | def get_filenames(self, internal=False): |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
296 | if not internal: |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
297 | self.pipe(self.list_pipe, "listing") |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
298 | processes = [] |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
299 | stdin = self.archive |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
300 | for command in [pipe[0] for pipe in self.pipes]: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
301 | self.add_process(processes, command, stdin, subprocess.PIPE) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
302 | stdin = processes[-1].stdout |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
303 | get_output_line = processes[-1].stdout.readline |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
304 | while True: |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
305 | line = get_output_line() |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
306 | if not line: |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
307 | break |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
308 | yield line.rstrip('\n') |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
309 | self.exit_codes = [pipe.wait() for pipe in processes] |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
310 | self.archive.close() |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
311 | for process in processes: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
312 | process.stdout.close() |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
313 | self.check_success(False) |
1 | 314 | |
315 | ||
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
316 | class CompressionExtractor(BaseExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
317 | file_type = 'compressed file' |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
318 | name_checker = FilenameChecker |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
319 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
320 | def basename(self): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
321 | pieces = os.path.basename(self.filename).split('.') |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
322 | extension = '.' + pieces[-1] |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
323 | if mimetypes.encodings_map.has_key(extension): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
324 | pieces.pop() |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
325 | return '.'.join(pieces) |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
326 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
327 | def get_filenames(self): |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
328 | # This code used to just immediately yield the basename, under the |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
329 | # assumption that that would be the filename. However, if that |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
330 | # happens, dtrx -l will report this as a valid result for files with |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
331 | # compression extensions, even if those files shouldn't actually be |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
332 | # handled this way. So, we call out to the file command to do a quick |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
333 | # check and make sure this actually looks like a compressed file. |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
334 | if 'compress' not in [match[0] for match in |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
335 | ExtractorBuilder.try_by_magic(self.filename)]: |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
336 | raise ExtractorError("doesn't look like a compressed file") |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
337 | yield self.basename() |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
338 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
339 | def extract(self): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
340 | self.content_type = ONE_ENTRY_KNOWN |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
341 | self.content_name = self.basename() |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
342 | self.contents = None |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
343 | self.included_root = './' |
40
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
344 | try: |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
345 | output_fd, self.target = tempfile.mkstemp(prefix='.dtrx-', dir='.') |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
346 | except (OSError, IOError), error: |
ee6a869f8da1
[svn] Be a little nicer about explaining that we can't extract to the current
brett
parents:
39
diff
changeset
|
347 | raise ExtractorError("cannot extract here: %s" % (error.strerror,)) |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
348 | self.run_pipes(output_fd) |
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
349 | os.close(output_fd) |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
350 | try: |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
351 | self.check_success(os.stat(self.target)[stat.ST_SIZE] > 0) |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
352 | except EXTRACTION_ERRORS: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
353 | os.unlink(self.target) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
354 | raise |
62
17d845dacff5
Deal with partially extracted tarballs.
Brett Smith <brett@brettcsmith.org>
parents:
59
diff
changeset
|
355 | |
1 | 356 | class TarExtractor(BaseExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
357 | file_type = 'tar file' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
358 | extract_pipe = ['tar', '-x'] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
359 | list_pipe = ['tar', '-t'] |
1 | 360 | |
361 | ||
362 | class CpioExtractor(BaseExtractor): | |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
363 | file_type = 'cpio file' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
364 | extract_pipe = ['cpio', '-i', '--make-directories', '--quiet', |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
365 | '--no-absolute-filenames'] |
83
cb56c72f3d42
Use the --quiet option for cpio -t too.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
82
diff
changeset
|
366 | list_pipe = ['cpio', '-t', '--quiet'] |
1 | 367 | |
368 | ||
369 | class RPMExtractor(CpioExtractor): | |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
370 | file_type = 'RPM' |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
371 | |
1 | 372 | def prepare(self): |
373 | self.pipe(['rpm2cpio', '-'], "rpm2cpio") | |
374 | ||
375 | def basename(self): | |
9
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
376 | pieces = os.path.basename(self.filename).split('.') |
2
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
377 | if len(pieces) == 1: |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
378 | return pieces[0] |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
379 | elif pieces[-1] != 'rpm': |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
380 | return BaseExtractor.basename(self) |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
381 | pieces.pop() |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
382 | if len(pieces) == 1: |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
383 | return pieces[0] |
9
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
384 | elif len(pieces[-1]) < 8: |
2
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
385 | pieces.pop() |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
386 | return '.'.join(pieces) |
1 | 387 | |
388 | def check_contents(self): | |
47 | 389 | self.check_included_archives() |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
390 | self.content_type = BOMB |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
391 | |
1 | 392 | |
393 | class DebExtractor(TarExtractor): | |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
394 | file_type = 'Debian package' |
108
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
395 | data_re = re.compile(r'^data\.tar\.[a-z0-9]+$') |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
396 | |
1 | 397 | def prepare(self): |
108
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
398 | self.pipe(['ar', 't', self.filename], "finding package data file") |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
399 | for filename in self.get_filenames(internal=True): |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
400 | if self.data_re.match(filename): |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
401 | data_filename = filename |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
402 | break |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
403 | else: |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
404 | raise ExtractorError(".deb contains no data.tar file") |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
405 | self.archive.seek(0, 0) |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
406 | self.pipes.pop() |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
407 | # self.pipes = start_pipes |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
408 | encoding = mimetypes.guess_type(data_filename)[1] |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
409 | if not encoding: |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
410 | raise ExtractorError("data.tar file has unrecognized encoding") |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
411 | self.pipe(['ar', 'p', self.filename, data_filename], |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
412 | "extracting data.tar from .deb") |
b8316c2b36df
Add support for new .deb archives with data.tar.{bz2,lzma}.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
106
diff
changeset
|
413 | self.pipe([self.decoders[encoding]], "decoding data.tar") |
1 | 414 | |
415 | def basename(self): | |
9
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
416 | pieces = os.path.basename(self.filename).split('_') |
2
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
417 | if len(pieces) == 1: |
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
418 | return pieces[0] |
9
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
419 | last_piece = pieces.pop() |
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
420 | if (len(last_piece) > 10) or (not last_piece.endswith('.deb')): |
2
1570351bf863
[svn] Fix a small bug that would crash the program if an archive was empty.
brett
parents:
1
diff
changeset
|
421 | return BaseExtractor.basename(self) |
9
920417b8acc9
[svn] Fix issues with basename methods. First, string's rsplit method only
brett
parents:
8
diff
changeset
|
422 | return '_'.join(pieces) |
1 | 423 | |
424 | def check_contents(self): | |
47 | 425 | self.check_included_archives() |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
426 | self.content_type = BOMB |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
427 | |
1 | 428 | |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
429 | class DebMetadataExtractor(DebExtractor): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
430 | def prepare(self): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
431 | self.pipe(['ar', 'p', self.filename, 'control.tar.gz'], |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
432 | "control.tar.gz extraction") |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
433 | self.pipe(['zcat'], "control.tar.gz decompression") |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
434 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
435 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
436 | class GemExtractor(TarExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
437 | file_type = 'Ruby gem' |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
438 | |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
439 | def prepare(self): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
440 | self.pipe(['tar', '-xO', 'data.tar.gz'], "data.tar.gz extraction") |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
441 | self.pipe(['zcat'], "data.tar.gz decompression") |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
442 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
443 | def check_contents(self): |
47 | 444 | self.check_included_archives() |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
445 | self.content_type = BOMB |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
446 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
447 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
448 | class GemMetadataExtractor(CompressionExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
449 | file_type = 'Ruby gem' |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
450 | |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
451 | def prepare(self): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
452 | self.pipe(['tar', '-xO', 'metadata.gz'], "metadata.gz extraction") |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
453 | self.pipe(['zcat'], "metadata.gz decompression") |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
454 | |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
455 | def basename(self): |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
456 | return os.path.basename(self.filename) + '-metadata.txt' |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
457 | |
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
458 | |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
459 | class NoPipeExtractor(BaseExtractor): |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
460 | # Some extraction tools won't accept the archive from stdin. With |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
461 | # these, the piping infrastructure we normally set up generally doesn't |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
462 | # work, at least at first. We can still use most of it; we just don't |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
463 | # want to seed self.archive with the archive file, since that sucks up |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
464 | # memory. So instead we seed it with /dev/null, and specify the |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
465 | # filename on the command line as necessary. We also open the actual |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
466 | # file with os.open, to make sure we can actually do it (permissions |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
467 | # are good, etc.). This class doesn't do anything by itself; it's just |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
468 | # meant to be a base class for extractors that rely on these dumb |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
469 | # tools. |
32 | 470 | def __init__(self, filename, encoding): |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
471 | os.close(os.open(filename, os.O_RDONLY)) |
32 | 472 | BaseExtractor.__init__(self, '/dev/null', None) |
473 | self.filename = os.path.realpath(filename) | |
474 | ||
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
475 | def extract_archive(self): |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
476 | self.extract_pipe = self.extract_command + [self.filename] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
477 | BaseExtractor.extract_archive(self) |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
478 | |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
479 | def get_filenames(self): |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
480 | self.list_pipe = self.list_command + [self.filename] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
481 | return BaseExtractor.get_filenames(self) |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
482 | |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
483 | |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
484 | class ZipExtractor(NoPipeExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
485 | file_type = 'Zip file' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
486 | extract_command = ['unzip', '-q'] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
487 | list_command = ['zipinfo', '-1'] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
488 | |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
489 | |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
490 | class SevenExtractor(NoPipeExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
491 | file_type = '7z file' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
492 | extract_command = ['7z', 'x'] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
493 | list_command = ['7z', 'l'] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
494 | border_re = re.compile('^[- ]+$') |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
495 | |
32 | 496 | def get_filenames(self): |
497 | fn_index = None | |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
498 | for line in NoPipeExtractor.get_filenames(self): |
32 | 499 | if self.border_re.match(line): |
500 | if fn_index is not None: | |
501 | break | |
502 | else: | |
110
6cbe6cb5a903
Use string.rindex (which is in Python 2.3) instead of my own version.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
109
diff
changeset
|
503 | fn_index = string.rindex(line, ' ') + 1 |
32 | 504 | elif fn_index is not None: |
82
6db35db38795
Stop worrying about trailing newlines in get_filenames() overrides.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
81
diff
changeset
|
505 | yield line[fn_index:] |
32 | 506 | self.archive.close() |
507 | ||
508 | ||
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
509 | class CABExtractor(NoPipeExtractor): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
510 | file_type = 'CAB archive' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
511 | extract_command = ['cabextract', '-q'] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
512 | list_command = ['cabextract', '-l'] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
513 | border_re = re.compile(r'^[-\+]+$') |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
514 | |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
515 | def get_filenames(self): |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
516 | fn_index = None |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
517 | filenames = NoPipeExtractor.get_filenames(self) |
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
518 | for line in filenames: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
519 | if self.border_re.match(line): |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
520 | break |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
521 | for line in filenames: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
522 | try: |
82
6db35db38795
Stop worrying about trailing newlines in get_filenames() overrides.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
81
diff
changeset
|
523 | yield line.split(' | ', 2)[2] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
524 | except IndexError: |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
525 | break |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
526 | self.archive.close() |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
527 | |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
528 | |
72
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
529 | class ShieldExtractor(NoPipeExtractor): |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
530 | file_type = 'InstallShield archive' |
80
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
531 | extract_command = ['unshield', 'x'] |
df9b3428e28f
Move more common extraction/listing functionality into BaseExtractor.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
79
diff
changeset
|
532 | list_command = ['unshield', 'l'] |
72
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
533 | prefix_re = re.compile(r'^\s+\d+\s+') |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
534 | end_re = re.compile(r'^\s+-+\s+-+\s*$') |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
535 | |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
536 | def get_filenames(self): |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
537 | for line in NoPipeExtractor.get_filenames(self): |
72
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
538 | if self.end_re.match(line): |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
539 | break |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
540 | else: |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
541 | match = self.prefix_re.match(line) |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
542 | if match: |
82
6db35db38795
Stop worrying about trailing newlines in get_filenames() overrides.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
81
diff
changeset
|
543 | yield line[match.end():] |
72
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
544 | self.archive.close() |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
545 | |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
546 | def basename(self): |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
547 | result = NoPipeExtractor.basename(self) |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
548 | if result.endswith('.hdr'): |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
549 | result = result[:-4] |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
550 | return result |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
551 | |
c4cfaf634bb9
Add support for InstallShield archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
71
diff
changeset
|
552 | |
92
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
553 | class RarExtractor(NoPipeExtractor): |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
554 | file_type = 'RAR archive' |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
555 | extract_command = ['unrar', 'x'] |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
556 | list_command = ['unrar', 'l'] |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
557 | border_re = re.compile('^-+$') |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
558 | |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
559 | def get_filenames(self): |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
560 | inside = False |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
561 | for line in NoPipeExtractor.get_filenames(self): |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
562 | if self.border_re.match(line): |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
563 | if inside: |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
564 | break |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
565 | else: |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
566 | inside = True |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
567 | elif inside: |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
568 | yield line.split(' ')[1] |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
569 | self.archive.close() |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
570 | |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
571 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
572 | class BaseHandler(object): |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
573 | def __init__(self, extractor, options): |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
574 | self.extractor = extractor |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
575 | self.options = options |
17
481a2b4be471
[svn] Lots of tests for various boundary cases, and slightly better handling for
brett
parents:
16
diff
changeset
|
576 | self.target = None |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
577 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
578 | def handle(self): |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
579 | command = 'find' |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
580 | status = subprocess.call(['find', self.extractor.target, '-type', 'd', |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
581 | '-exec', 'chmod', 'u+rwx', '{}', ';']) |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
582 | if status == 0: |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
583 | command = 'chmod' |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
584 | status = subprocess.call(['chmod', '-R', 'u+rwX', |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
585 | self.extractor.target]) |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
586 | if status != 0: |
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
587 | return "%s returned with exit status %s" % (command, status) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
588 | return self.organize() |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
589 | |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
590 | def set_target(self, target, checker): |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
591 | self.target = checker(target).check() |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
592 | if self.target != target: |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
593 | logger.warning("extracting %s to %s" % |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
594 | (self.extractor.filename, self.target)) |
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
595 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
596 | |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
597 | # The "where to extract" table, with options and archive types. |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
598 | # This dictates the contents of each can_handle method. |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
599 | # |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
600 | # Flat Overwrite None |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
601 | # File basename basename FilenameChecked |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
602 | # Match . . tempdir + checked |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
603 | # Bomb . basename DirectoryChecked |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
604 | |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
605 | class FlatHandler(BaseHandler): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
606 | def can_handle(contents, options): |
22
b240777ae53e
[svn] Improve the way we check archive contents. If all the entries look like
brett
parents:
20
diff
changeset
|
607 | return ((options.flat and (contents != ONE_ENTRY_KNOWN)) or |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
608 | (options.overwrite and (contents == MATCHING_DIRECTORY))) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
609 | can_handle = staticmethod(can_handle) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
610 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
611 | def organize(self): |
17
481a2b4be471
[svn] Lots of tests for various boundary cases, and slightly better handling for
brett
parents:
16
diff
changeset
|
612 | self.target = '.' |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
613 | for curdir, dirs, filenames in os.walk(self.extractor.target, |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
614 | topdown=False): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
615 | path_parts = curdir.split(os.sep) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
616 | if path_parts[0] == '.': |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
617 | del path_parts[1] |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
618 | else: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
619 | del path_parts[0] |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
620 | newdir = os.path.join(*path_parts) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
621 | if not os.path.isdir(newdir): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
622 | os.makedirs(newdir) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
623 | for filename in filenames: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
624 | os.rename(os.path.join(curdir, filename), |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
625 | os.path.join(newdir, filename)) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
626 | os.rmdir(curdir) |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
627 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
628 | |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
629 | class OverwriteHandler(BaseHandler): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
630 | def can_handle(contents, options): |
22
b240777ae53e
[svn] Improve the way we check archive contents. If all the entries look like
brett
parents:
20
diff
changeset
|
631 | return ((options.flat and (contents == ONE_ENTRY_KNOWN)) or |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
632 | (options.overwrite and (contents != MATCHING_DIRECTORY))) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
633 | can_handle = staticmethod(can_handle) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
634 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
635 | def organize(self): |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
636 | self.target = self.extractor.basename() |
51
f1789e6586d8
[svn] Don't try to rmtree when overwriting just a file.
brett
parents:
49
diff
changeset
|
637 | if os.path.isdir(self.target): |
f1789e6586d8
[svn] Don't try to rmtree when overwriting just a file.
brett
parents:
49
diff
changeset
|
638 | shutil.rmtree(self.target) |
48 | 639 | os.rename(self.extractor.target, self.target) |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
640 | |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
641 | |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
642 | class MatchHandler(BaseHandler): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
643 | def can_handle(contents, options): |
20
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
644 | return ((contents == MATCHING_DIRECTORY) or |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
645 | ((contents in ONE_ENTRY_UNKNOWN) and |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
646 | options.one_entry_policy.ok_for_match())) |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
647 | can_handle = staticmethod(can_handle) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
648 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
649 | def organize(self): |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
650 | source = os.path.join(self.extractor.target, |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
651 | os.listdir(self.extractor.target)[0]) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
652 | if os.path.isdir(source): |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
653 | checker = DirectoryChecker |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
654 | else: |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
655 | checker = FilenameChecker |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
656 | if self.options.one_entry_policy == EXTRACT_HERE: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
657 | destination = self.extractor.content_name.rstrip('/') |
20
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
658 | else: |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
659 | destination = self.extractor.basename() |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
660 | self.set_target(destination, checker) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
661 | if os.path.isdir(self.extractor.target): |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
662 | os.rename(source, self.target) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
663 | os.rmdir(self.extractor.target) |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
664 | else: |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
665 | os.rename(self.extractor.target, self.target) |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
666 | self.extractor.included_root = './' |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
667 | |
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
668 | |
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
669 | class EmptyHandler(object): |
100
7353b443dc98
Fix crasher bug when extracting empty archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
99
diff
changeset
|
670 | target = '' |
7353b443dc98
Fix crasher bug when extracting empty archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
99
diff
changeset
|
671 | |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
672 | def can_handle(contents, options): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
673 | return contents == EMPTY |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
674 | can_handle = staticmethod(can_handle) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
675 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
676 | def __init__(self, extractor, options): pass |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
677 | def handle(self): pass |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
678 | |
14
6f9e1bb59719
[svn] Add support for just decompressing files that are compressed. So, if you
brett
parents:
13
diff
changeset
|
679 | |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
680 | class BombHandler(BaseHandler): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
681 | def can_handle(contents, options): |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
682 | return True |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
683 | can_handle = staticmethod(can_handle) |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
684 | |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
685 | def organize(self): |
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
686 | basename = self.extractor.basename() |
41
e3675644bbb6
[svn] Minor clean-ups. The most important of these is that we now have a better
brett
parents:
40
diff
changeset
|
687 | self.set_target(basename, self.extractor.name_checker) |
28
4d88f2231d33
[svn] Change all the license notices from GPLv2 to GPLv3.
brett
parents:
27
diff
changeset
|
688 | os.rename(self.extractor.target, self.target) |
16
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
689 | |
29794d4d41aa
[svn] There's now an entirely new object hierarchy for handlers, because the
brett
parents:
15
diff
changeset
|
690 | |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
691 | class BasePolicy(object): |
99
1ae3722ca219
Improve wrapping of interactive prompts.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
98
diff
changeset
|
692 | try: |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
693 | size = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
694 | struct.pack("HHHH", 0, 0, 0, 0)) |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
695 | width = struct.unpack("HHHH", size)[1] |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
696 | except IOError: |
99
1ae3722ca219
Improve wrapping of interactive prompts.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
98
diff
changeset
|
697 | width = 80 |
105
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
698 | width = width - 1 |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
699 | choice_wrapper = textwrap.TextWrapper(width=width, initial_indent=' * ', |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
700 | subsequent_indent=' ', |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
701 | break_long_words=False) |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
702 | |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
703 | def __init__(self, options): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
704 | self.current_policy = None |
26 | 705 | if options.batch: |
706 | self.permanent_policy = self.answers[''] | |
707 | else: | |
708 | self.permanent_policy = None | |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
709 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
710 | def ask_question(self, question): |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
711 | question = question + ["You can:"] |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
712 | for choice in self.choices: |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
713 | question.extend(self.choice_wrapper.wrap(choice)) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
714 | while True: |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
715 | print "\n".join(question) |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
716 | try: |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
717 | answer = raw_input(self.prompt) |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
718 | except EOFError: |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
719 | return self.answers[''] |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
720 | try: |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
721 | return self.answers[answer.lower()] |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
722 | except KeyError: |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
723 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
724 | |
105
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
725 | def wrap(self, question, *args): |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
726 | words = question.split() |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
727 | for arg in args: |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
728 | words[words.index('%s')] = arg |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
729 | result = [words.pop(0)] |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
730 | for word in words: |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
731 | extend = '%s %s' % (result[-1], word) |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
732 | if len(extend) > self.width: |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
733 | result.append(word) |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
734 | else: |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
735 | result[-1] = extend |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
736 | return result |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
737 | |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
738 | def __cmp__(self, other): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
739 | return cmp(self.current_policy, other) |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
740 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
741 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
742 | class OneEntryPolicy(BasePolicy): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
743 | answers = {'h': EXTRACT_HERE, 'i': EXTRACT_WRAP, 'r': EXTRACT_RENAME, |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
744 | '': EXTRACT_WRAP} |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
745 | choice_template = ["extract the %s _I_nside a new directory named %s", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
746 | "extract the %s and _R_ename it %s", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
747 | "extract the %s _H_ere"] |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
748 | prompt = "What do you want to do? (I/r/h) " |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
749 | |
66
af0b822b012e
Don't prompt for one entry handling with -f.
Brett Smith <brett@brettcsmith.org>
parents:
65
diff
changeset
|
750 | def __init__(self, options): |
af0b822b012e
Don't prompt for one entry handling with -f.
Brett Smith <brett@brettcsmith.org>
parents:
65
diff
changeset
|
751 | BasePolicy.__init__(self, options) |
af0b822b012e
Don't prompt for one entry handling with -f.
Brett Smith <brett@brettcsmith.org>
parents:
65
diff
changeset
|
752 | if options.flat: |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
753 | default = 'h' |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
754 | elif options.one_entry_default is not None: |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
755 | default = options.one_entry_default.lower() |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
756 | else: |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
757 | return |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
758 | if 'here'.startswith(default): |
66
af0b822b012e
Don't prompt for one entry handling with -f.
Brett Smith <brett@brettcsmith.org>
parents:
65
diff
changeset
|
759 | self.permanent_policy = EXTRACT_HERE |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
760 | elif 'rename'.startswith(default): |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
761 | self.permanent_policy = EXTRACT_RENAME |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
762 | elif 'inside'.startswith(default): |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
763 | self.permanent_policy = EXTRACT_WRAP |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
764 | elif default is not None: |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
765 | raise ValueError("bad value %s for default policy" % (default,)) |
66
af0b822b012e
Don't prompt for one entry handling with -f.
Brett Smith <brett@brettcsmith.org>
parents:
65
diff
changeset
|
766 | |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
767 | def prep(self, archive_filename, extractor): |
105
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
768 | question = self.wrap( |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
769 | "%s contains one %s but its name doesn't match.", |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
770 | archive_filename, extractor.content_type) |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
771 | question.append(" Expected: " + extractor.basename()) |
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
772 | question.append(" Actual: " + extractor.content_name) |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
773 | choice_vars = (extractor.content_type, extractor.basename()) |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
774 | self.choices = [text % choice_vars[:text.count('%s')] |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
775 | for text in self.choice_template] |
26 | 776 | self.current_policy = (self.permanent_policy or |
777 | self.ask_question(question)) | |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
778 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
779 | def ok_for_match(self): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
780 | return self.current_policy in (EXTRACT_RENAME, EXTRACT_HERE) |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
781 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
782 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
783 | class RecursionPolicy(BasePolicy): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
784 | answers = {'o': RECURSE_ONCE, 'a': RECURSE_ALWAYS, 'n': RECURSE_NOT_NOW, |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
785 | 'v': RECURSE_NEVER, 'l': RECURSE_LIST, '': RECURSE_NOT_NOW} |
103
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
786 | choices = ["_A_lways extract included archives during this session", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
787 | "extract included archives this _O_nce", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
788 | "choose _N_ot to extract included archives this once", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
789 | "ne_V_er extract included archives during this session", |
f68a0ca870b0
Reword one entry prompt; wrap prompt choices; better term size detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
101
diff
changeset
|
790 | "_L_ist included archives"] |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
791 | prompt = "What do you want to do? (a/o/N/v/l) " |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
792 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
793 | def __init__(self, options): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
794 | BasePolicy.__init__(self, options) |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
795 | if options.show_list: |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
796 | self.permanent_policy = RECURSE_NEVER |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
797 | elif options.recursive: |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
798 | self.permanent_policy = RECURSE_ALWAYS |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
799 | |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
800 | def prep(self, current_filename, target, extractor): |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
801 | archive_count = len(extractor.included_archives) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
802 | if (self.permanent_policy is not None) or (archive_count == 0): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
803 | self.current_policy = self.permanent_policy or RECURSE_NOT_NOW |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
804 | return |
105
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
805 | question = self.wrap( |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
806 | "%s contains %s other archive file(s), out of %s file(s) total.", |
f76ac41fe061
Make sure prompts with filenames don't break mid-filename.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
103
diff
changeset
|
807 | current_filename, archive_count, extractor.file_count) |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
808 | if target == '.': |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
809 | target = '' |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
810 | included_root = extractor.included_root |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
811 | if included_root == './': |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
812 | included_root = '' |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
813 | while True: |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
814 | self.current_policy = self.ask_question(question) |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
815 | if self.current_policy != RECURSE_LIST: |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
816 | break |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
817 | print ("\n%s\n" % |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
818 | '\n'.join([os.path.join(target, included_root, filename) |
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
819 | for filename in extractor.included_archives])) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
820 | if self.current_policy in (RECURSE_ALWAYS, RECURSE_NEVER): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
821 | self.permanent_policy = self.current_policy |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
822 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
823 | def ok_to_recurse(self): |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
824 | return self.current_policy in (RECURSE_ALWAYS, RECURSE_ONCE) |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
825 | |
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
826 | |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
827 | class ExtractorBuilder(object): |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
828 | extractor_map = {'tar': {'extractor': TarExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
829 | 'mimetypes': ('x-tar',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
830 | 'extensions': ('tar',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
831 | 'magic': ('POSIX tar archive',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
832 | 'zip': {'extractor': ZipExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
833 | 'mimetypes': ('zip',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
834 | 'extensions': ('zip',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
835 | 'magic': ('(Zip|ZIP self-extracting) archive',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
836 | 'rpm': {'extractor': RPMExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
837 | 'mimetypes': ('x-redhat-package-manager', 'x-rpm'), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
838 | 'extensions': ('rpm',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
839 | 'magic': ('RPM',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
840 | 'deb': {'extractor': DebExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
841 | 'metadata': DebMetadataExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
842 | 'mimetypes': ('x-debian-package',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
843 | 'extensions': ('deb',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
844 | 'magic': ('Debian binary package',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
845 | 'cpio': {'extractor': CpioExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
846 | 'mimetypes': ('x-cpio',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
847 | 'extensions': ('cpio',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
848 | 'magic': ('cpio archive',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
849 | 'gem': {'extractor': GemExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
850 | 'metadata': GemMetadataExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
851 | 'mimetypes': ('x-ruby-gem',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
852 | 'extensions': ('gem',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
853 | '7z': {'extractor': SevenExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
854 | 'mimetypes': ('x-7z-compressed',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
855 | 'extensions': ('7z',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
856 | 'magic': ('7-zip archive',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
857 | 'cab': {'extractor': CABExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
858 | 'mimetypes': ('x-cab',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
859 | 'extensions': ('cab',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
860 | 'magic': ('Microsoft Cabinet Archive',)}, |
92
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
861 | 'rar': {'extractor': RarExtractor, |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
862 | 'mimetypes': ('rar',), |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
863 | 'extensions': ('rar',), |
d9319958bb5a
Add RAR support. Thanks to Peter Kelemen for the patch.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
89
diff
changeset
|
864 | 'magic': ('RAR archive',)}, |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
865 | 'shield': {'extractor': ShieldExtractor, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
866 | 'mimetypes': ('x-cab',), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
867 | 'extensions': ('cab', 'hdr'), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
868 | 'magic': ('InstallShield CAB',)}, |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
869 | 'compress': {'extractor': CompressionExtractor} |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
870 | } |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
871 | |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
872 | mimetype_map = {} |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
873 | magic_mime_map = {} |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
874 | extension_map = {} |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
875 | for ext_name, ext_info in extractor_map.items(): |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
876 | for mimetype in ext_info.get('mimetypes', ()): |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
877 | if '/' not in mimetype: |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
878 | mimetype = 'application/' + mimetype |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
879 | mimetype_map[mimetype] = ext_name |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
880 | for magic_re in ext_info.get('magic', ()): |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
881 | magic_mime_map[re.compile(magic_re)] = ext_name |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
882 | for extension in ext_info.get('extensions', ()): |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
883 | extension_map.setdefault(extension, []).append((ext_name, None)) |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
884 | |
115
d670445a0a9b
Support more .tar.whatever extensions.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
114
diff
changeset
|
885 | for mapping in (('tar', 'bzip2', 'tar.bz2', 'tbz2', 'tb2', 'tbz'), |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
886 | ('tar', 'gzip', 'tar.gz', 'tgz'), |
111
09be2149c500
add support for LZMA-compressed tar file extensions
Brett Smith <brettcsmith@brettcsmith.org>
parents:
110
diff
changeset
|
887 | ('tar', 'lzma', 'tar.lzma', 'tlz'), |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
888 | ('tar', 'xz', 'tar.xz'), |
115
d670445a0a9b
Support more .tar.whatever extensions.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
114
diff
changeset
|
889 | ('tar', 'compress', 'tar.Z', 'taz'), |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
890 | ('compress', 'gzip', 'Z', 'gz'), |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
891 | ('compress', 'bzip2', 'bz2'), |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
892 | ('compress', 'lzma', 'lzma'), |
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
893 | ('compress', 'xz', 'xz')): |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
894 | for extension in mapping[2:]: |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
895 | extension_map.setdefault(extension, []).append(mapping[:2]) |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
896 | |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
897 | magic_encoding_map = {} |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
898 | for mapping in (('bzip2', 'bzip2 compressed'), |
98
6b7860fca221
Add support for LZMA magic detection.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
96
diff
changeset
|
899 | ('gzip', 'gzip compressed'), |
123
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
900 | ('lzma', 'LZMA compressed'), |
8570c14304bb
add support for xz compression
Brett Smith <brettcsmith@brettcsmith.org>
parents:
121
diff
changeset
|
901 | ('xz', 'xz compressed')): |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
902 | for pattern in mapping[1:]: |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
903 | magic_encoding_map[re.compile(pattern)] = mapping[0] |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
904 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
905 | def __init__(self, filename, options): |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
906 | self.filename = filename |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
907 | self.options = options |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
908 | |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
909 | def build_extractor(self, archive_type, encoding): |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
910 | extractors = self.extractor_map[archive_type] |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
911 | if self.options.metadata and extractors.has_key('metadata'): |
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
912 | extractor = extractors['metadata'] |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
913 | else: |
81
18f4fe62eff2
Move most ExtractorBuilder constants to the top.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
80
diff
changeset
|
914 | extractor = extractors['extractor'] |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
915 | return extractor(self.filename, encoding) |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
916 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
917 | def get_extractor(self): |
48 | 918 | tried_types = set() |
36
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
919 | # As smart as it is, the magic test can't go first, because at least |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
920 | # on my system it just recognizes gem files as tar files. I guess |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
921 | # it's possible for the opposite problem to occur -- where the mimetype |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
922 | # or extension suggests something less than ideal -- but it seems less |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
923 | # likely so I'm sticking with this. |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
924 | for func_name in ('mimetype', 'extension', 'magic'): |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
925 | logger.debug("getting extractors by %s" % (func_name,)) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
926 | extractor_types = \ |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
927 | getattr(self, 'try_by_' + func_name)(self.filename) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
928 | logger.debug("done getting extractors") |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
929 | for ext_args in extractor_types: |
36
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
930 | if ext_args in tried_types: |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
931 | continue |
4bf2508d9b9e
[svn] Small optimization to be nice to the system: don't try a given extractor
brett
parents:
35
diff
changeset
|
932 | tried_types.add(ext_args) |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
933 | logger.debug("trying %s extractor from %s" % |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
934 | (ext_args, func_name)) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
935 | yield self.build_extractor(*ext_args) |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
936 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
937 | def try_by_mimetype(cls, filename): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
938 | mimetype, encoding = mimetypes.guess_type(filename) |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
939 | try: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
940 | return [(cls.mimetype_map[mimetype], encoding)] |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
941 | except KeyError: |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
942 | if encoding: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
943 | return [('compress', encoding)] |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
944 | return [] |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
945 | try_by_mimetype = classmethod(try_by_mimetype) |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
946 | |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
947 | def magic_map_matches(cls, output, magic_map): |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
948 | return [result for regexp, result in magic_map.items() |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
949 | if regexp.search(output)] |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
950 | magic_map_matches = classmethod(magic_map_matches) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
951 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
952 | def try_by_magic(cls, filename): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
953 | process = subprocess.Popen(['file', '-z', filename], |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
954 | stdout=subprocess.PIPE) |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
955 | status = process.wait() |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
956 | if status != 0: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
957 | return [] |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
958 | output = process.stdout.readline() |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
959 | process.stdout.close() |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
960 | if output.startswith('%s: ' % filename): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
961 | output = output[len(filename) + 2:] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
962 | mimes = cls.magic_map_matches(output, cls.magic_mime_map) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
963 | encodings = cls.magic_map_matches(output, cls.magic_encoding_map) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
964 | if mimes and not encodings: |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
965 | encodings = [None] |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
966 | elif encodings and not mimes: |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
967 | mimes = ['compress'] |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
968 | return [(m, e) for m in mimes for e in encodings] |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
969 | try_by_magic = classmethod(try_by_magic) |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
970 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
971 | def try_by_extension(cls, filename): |
43
4591a32eedc8
[svn] Sadly Python 2.3 does not have an rsplit method on strings.
brett
parents:
42
diff
changeset
|
972 | parts = filename.split('.')[-2:] |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
973 | results = [] |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
974 | while parts: |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
975 | results.extend(cls.extension_map.get('.'.join(parts), [])) |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
976 | del parts[0] |
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
977 | return results |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
978 | try_by_extension = classmethod(try_by_extension) |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
979 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
980 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
981 | class BaseAction(object): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
982 | def __init__(self, options, filenames): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
983 | self.options = options |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
984 | self.filenames = filenames |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
985 | self.target = None |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
986 | self.do_print = False |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
987 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
988 | def report(self, function, *args): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
989 | try: |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
990 | error = function(*args) |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
991 | except EXTRACTION_ERRORS, exception: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
992 | error = str(exception) |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
993 | logger.debug(''.join(traceback.format_exception(*sys.exc_info()))) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
994 | return error |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
995 | |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
996 | def show_filename(self, filename): |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
997 | if len(self.filenames) < 2: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
998 | return |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
999 | elif self.do_print: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1000 | |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1001 | else: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1002 | self.do_print = True |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1003 | print "%s:" % (filename,) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1004 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1005 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1006 | class ExtractionAction(BaseAction): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1007 | handlers = [FlatHandler, OverwriteHandler, MatchHandler, EmptyHandler, |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1008 | BombHandler] |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1009 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1010 | def get_handler(self, extractor): |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
1011 | if extractor.content_type in ONE_ENTRY_UNKNOWN: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1012 | self.options.one_entry_policy.prep(self.current_filename, |
65
0aea49161478
Make the wording on the One Entry question a little clearer.
Brett Smith <brett@brettcsmith.org>
parents:
62
diff
changeset
|
1013 | extractor) |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1014 | for handler in self.handlers: |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1015 | if handler.can_handle(extractor.content_type, self.options): |
35
957b402d4b90
[svn] Add support for extracting CAB archives. Because the CAB archive I was
brett
parents:
34
diff
changeset
|
1016 | logger.debug("using %s handler" % (handler.__name__,)) |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1017 | self.current_handler = handler(extractor, self.options) |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1018 | break |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1019 | |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1020 | def show_extraction(self, extractor): |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1021 | if self.options.log_level > logging.INFO: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1022 | return |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1023 | self.show_filename(self.current_filename) |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1024 | if extractor.contents is None: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1025 | print self.current_handler.target |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1026 | return |
55
494516c027c4
[svn] Stupid Python 2.3 doesn't support [].sort(reverse=True).
brett
parents:
54
diff
changeset
|
1027 | def reverser(x, y): |
494516c027c4
[svn] Stupid Python 2.3 doesn't support [].sort(reverse=True).
brett
parents:
54
diff
changeset
|
1028 | return cmp(y, x) |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1029 | if self.current_handler.target == '.': |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1030 | filenames = extractor.contents |
55
494516c027c4
[svn] Stupid Python 2.3 doesn't support [].sort(reverse=True).
brett
parents:
54
diff
changeset
|
1031 | filenames.sort(reverser) |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1032 | else: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1033 | filenames = [self.current_handler.target] |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1034 | pathjoin = os.path.join |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1035 | isdir = os.path.isdir |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1036 | while filenames: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1037 | filename = filenames.pop() |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1038 | if isdir(filename): |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1039 | print "%s/" % (filename,) |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1040 | new_filenames = os.listdir(filename) |
55
494516c027c4
[svn] Stupid Python 2.3 doesn't support [].sort(reverse=True).
brett
parents:
54
diff
changeset
|
1041 | new_filenames.sort(reverser) |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1042 | filenames.extend([pathjoin(filename, new_filename) |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1043 | for new_filename in new_filenames]) |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1044 | else: |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1045 | print filename |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1046 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1047 | def run(self, filename, extractor): |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1048 | self.current_filename = filename |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1049 | error = (self.report(extractor.extract) or |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1050 | self.report(self.get_handler, extractor) or |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1051 | self.report(self.current_handler.handle) or |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1052 | self.report(self.show_extraction, extractor)) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1053 | if not error: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1054 | self.target = self.current_handler.target |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1055 | return error |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1056 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1057 | |
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1058 | class ListAction(BaseAction): |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1059 | def list_filenames(self, extractor, filename): |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1060 | # We get a line first to make sure there's not going to be some |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1061 | # basic error before we show what filename we're listing. |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1062 | filename_lister = extractor.get_filenames() |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1063 | try: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1064 | first_line = filename_lister.next() |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1065 | except StopIteration: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1066 | self.show_filename(filename) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1067 | else: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1068 | self.did_list = True |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1069 | self.show_filename(filename) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1070 | print first_line |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1071 | for line in filename_lister: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1072 | print line |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1073 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1074 | def run(self, filename, extractor): |
106
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1075 | self.did_list = False |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1076 | error = self.report(self.list_filenames, extractor, filename) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1077 | if error and self.did_list: |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1078 | logger.error("lister failed: ignore above listing for %s" % |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1079 | (filename,)) |
dcf005ef7070
Start printing results ASAP with -l or -t.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
105
diff
changeset
|
1080 | return error |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
1081 | |
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
1082 | |
5 | 1083 | class ExtractorApplication(object): |
1084 | def __init__(self, arguments): | |
48 | 1085 | for signal_num in (signal.SIGINT, signal.SIGTERM): |
1086 | signal.signal(signal_num, self.abort) | |
85
ad73f75c9046
Use the default action for SIGPIPE.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
84
diff
changeset
|
1087 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1088 | self.parse_options(arguments) |
12
5d202467c589
[svn] Introduce a real logging system. Right now all this really gets us is the
brett
parents:
11
diff
changeset
|
1089 | self.setup_logger() |
5 | 1090 | self.successes = [] |
1091 | self.failures = [] | |
1092 | ||
77
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1093 | def clean_destination(self, dest_name): |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1094 | try: |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1095 | os.unlink(dest_name) |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1096 | except OSError, error: |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1097 | if error.errno == errno.EISDIR: |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1098 | shutil.rmtree(dest_name, ignore_errors=True) |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1099 | |
48 | 1100 | def abort(self, signal_num, frame): |
1101 | signal.signal(signal_num, signal.SIG_IGN) | |
1102 | ||
49 | 1103 | logger.debug("traceback:\n" + |
1104 | ''.join(traceback.format_stack(frame)).rstrip()) | |
86
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1105 | logger.debug("got signal %s" % (signal_num,)) |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1106 | try: |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1107 | basename = self.current_extractor.target |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1108 | except AttributeError: |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1109 | basename = None |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1110 | if basename is not None: |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1111 | logger.debug("cleaning up %s" % (basename,)) |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1112 | clean_targets = set([os.path.realpath('.')]) |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1113 | if hasattr(self, 'current_directory'): |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1114 | clean_targets.add(os.path.realpath(self.current_directory)) |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1115 | for directory in clean_targets: |
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1116 | self.clean_destination(os.path.join(directory, basename)) |
48 | 1117 | sys.exit(1) |
1118 | ||
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1119 | def parse_options(self, arguments): |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1120 | parser = optparse.OptionParser( |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1121 | usage="%prog [options] archive [archive2 ...]", |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1122 | description="Intelligent archive extractor", |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1123 | version=VERSION_BANNER |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1124 | ) |
19 | 1125 | parser.add_option('-l', '-t', '--list', '--table', dest='show_list', |
1126 | action='store_true', default=False, | |
1127 | help="list contents of archives on standard output") | |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1128 | parser.add_option('-m', '--metadata', dest='metadata', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1129 | action='store_true', default=False, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1130 | help="extract metadata from a .deb/.gem") |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1131 | parser.add_option('-r', '--recursive', dest='recursive', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1132 | action='store_true', default=False, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1133 | help="extract archives contained in the ones listed") |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1134 | parser.add_option('--one', '--one-entry', dest='one_entry_default', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1135 | default=None, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1136 | help=("specify extraction policy for one-entry " + |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1137 | "archives: inside/rename/here")) |
20
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
1138 | parser.add_option('-n', '--noninteractive', dest='batch', |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
1139 | action='store_true', default=False, |
69c93c3e6972
[svn] If the archive contains one directory with the "wrong" name, ask the user
brett
parents:
19
diff
changeset
|
1140 | help="don't ask how to handle special cases") |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1141 | parser.add_option('-o', '--overwrite', dest='overwrite', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1142 | action='store_true', default=False, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1143 | help="overwrite any existing target output") |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1144 | parser.add_option('-f', '--flat', '--no-directory', dest='flat', |
29
5fad99c17221
[svn] Add support for Ruby Gems, and extracting metadata from .deb/.gem files.
brett
parents:
28
diff
changeset
|
1145 | action='store_true', default=False, |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1146 | help="extract everything to the current directory") |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1147 | parser.add_option('-v', '--verbose', dest='verbose', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1148 | action='count', default=0, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1149 | help="be verbose/print debugging information") |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1150 | parser.add_option('-q', '--quiet', dest='quiet', |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1151 | action='count', default=3, |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1152 | help="suppress warning/error messages") |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1153 | self.options, filenames = parser.parse_args(arguments) |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1154 | if not filenames: |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1155 | parser.error("you did not list any archives") |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1156 | # This makes WARNING is the default. |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1157 | self.options.log_level = (10 * (self.options.quiet - |
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1158 | self.options.verbose)) |
84
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1159 | try: |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1160 | self.options.one_entry_policy = OneEntryPolicy(self.options) |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1161 | except ValueError: |
d78d63cb4c4e
Add --one-entry option to specify default handling for one-entry archives.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
83
diff
changeset
|
1162 | parser.error("invalid value for --one-entry option") |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
1163 | self.options.recursion_policy = RecursionPolicy(self.options) |
6
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1164 | self.archives = {os.path.realpath(os.curdir): filenames} |
77043f4e6a9f
[svn] The big thing here is recursive extraction. Find archive files in the
brett
parents:
5
diff
changeset
|
1165 | |
12
5d202467c589
[svn] Introduce a real logging system. Right now all this really gets us is the
brett
parents:
11
diff
changeset
|
1166 | def setup_logger(self): |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1167 | logging.getLogger().setLevel(self.options.log_level) |
12
5d202467c589
[svn] Introduce a real logging system. Right now all this really gets us is the
brett
parents:
11
diff
changeset
|
1168 | handler = logging.StreamHandler() |
52
cf191f957fd0
[svn] Make just one -v print a list of filenames, a la tar.
brett
parents:
51
diff
changeset
|
1169 | handler.setLevel(self.options.log_level) |
19 | 1170 | formatter = logging.Formatter("dtrx: %(levelname)s: %(message)s") |
12
5d202467c589
[svn] Introduce a real logging system. Right now all this really gets us is the
brett
parents:
11
diff
changeset
|
1171 | handler.setFormatter(formatter) |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1172 | logger.addHandler(handler) |
33
3547e3124729
[svn] Fix some bugs and make things a little more user-friendly now that we can
brett
parents:
32
diff
changeset
|
1173 | logger.debug("logger is set up") |
1 | 1174 | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1175 | def recurse(self, filename, extractor, action): |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
1176 | self.options.recursion_policy.prep(filename, action.target, extractor) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
1177 | if self.options.recursion_policy.ok_to_recurse(): |
53
cd853ddb224c
[svn] Add interactive option to list recursive archives when found.
brett
parents:
52
diff
changeset
|
1178 | for filename in extractor.included_archives: |
71
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1179 | logger.debug("recursing with %s archive" % |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1180 | (extractor.content_type,)) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
1181 | tail_path, basename = os.path.split(filename) |
71
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1182 | path_args = [self.current_directory, extractor.included_root, |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1183 | tail_path] |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1184 | logger.debug("included root: %s" % (extractor.included_root,)) |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1185 | logger.debug("tail path: %s" % (tail_path,)) |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1186 | if os.path.isdir(action.target): |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1187 | logger.debug("action target: %s" % (action.target,)) |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1188 | path_args.insert(1, action.target) |
b0290eeb3b7a
Recurse better when the contents were just one file.
Brett Smith <brett@brettcsmith.org>
parents:
70
diff
changeset
|
1189 | directory = os.path.join(*path_args) |
25
ef62f2f55eb8
[svn] Move policy-handling code into a dedicated set of classes. This makes
brett
parents:
23
diff
changeset
|
1190 | self.archives.setdefault(directory, []).append(basename) |
8
97388f5ff770
[svn] Make ExtractorApplication suck less. Now the strategies for handling
brett
parents:
7
diff
changeset
|
1191 | |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1192 | def check_file(self, filename): |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1193 | try: |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1194 | result = os.stat(filename) |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1195 | except OSError, error: |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1196 | return error.strerror |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1197 | if stat.S_ISDIR(result.st_mode): |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
1198 | return "cannot work with a directory" |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1199 | |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1200 | def show_stderr(self, logger_func, stderr): |
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1201 | if stderr: |
79
9c0cc7aef510
Improve dtrx -l performance on misnamed files, and clean other error messages.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
78
diff
changeset
|
1202 | logger_func("Error output from this process:\n" + |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1203 | stderr.rstrip('\n')) |
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1204 | |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1205 | def try_extractors(self, filename, builder): |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1206 | errors = [] |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1207 | for extractor in builder: |
86
e02ca4e9bf42
Be more careful on SIGINT/SIGKILL cleanup.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
85
diff
changeset
|
1208 | self.current_extractor = extractor # For the abort() method. |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1209 | error = self.action.run(filename, extractor) |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1210 | if error: |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1211 | errors.append((extractor.file_type, extractor.encoding, error, |
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1212 | extractor.get_stderr())) |
77
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1213 | if extractor.target is not None: |
3a1f49be7667
Clean the target directory if an extraction attempt failed.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
76
diff
changeset
|
1214 | self.clean_destination(extractor.target) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1215 | else: |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1216 | self.show_stderr(logger.warn, extractor.get_stderr()) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1217 | self.recurse(filename, extractor, self.action) |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1218 | return |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1219 | logger.error("could not handle %s" % (filename,)) |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1220 | if not errors: |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1221 | logger.error("not a known archive type") |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1222 | return True |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1223 | for file_type, encoding, error, stderr in errors: |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1224 | message = ["treating as", file_type, "failed:", error] |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1225 | if encoding: |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1226 | message.insert(1, "%s-encoded" % (encoding,)) |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1227 | logger.error(' '.join(message)) |
78
978307ec7d11
Don't show errors from failed extractors unless they all fail.
Brett Smith <brettcsmith@brettcsmith.org>
parents:
77
diff
changeset
|
1228 | self.show_stderr(logger.error, stderr) |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1229 | return True |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1230 | |
19 | 1231 | def run(self): |
1232 | if self.options.show_list: | |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1233 | action = ListAction |
19 | 1234 | else: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1235 | action = ExtractionAction |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1236 | self.action = action(self.options, self.archives.values()[0]) |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1237 | while self.archives: |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1238 | self.current_directory, self.filenames = self.archives.popitem() |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1239 | os.chdir(self.current_directory) |
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1240 | for filename in self.filenames: |
31
c3a2760d1c3a
[svn] Refactor actions (extract the archive, vs. list the contents) into their
brett
parents:
30
diff
changeset
|
1241 | builder = ExtractorBuilder(filename, self.options) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1242 | error = (self.check_file(filename) or |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1243 | self.try_extractors(filename, builder.get_extractor())) |
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1244 | if error: |
45
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1245 | if error != True: |
37d555407334
[svn] At work I was getting an unhelpful "No such file or directory" error when I
brett
parents:
43
diff
changeset
|
1246 | logger.error("%s: %s" % (filename, error)) |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1247 | self.failures.append(filename) |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1248 | else: |
39
027fcd7ae002
[svn] Improve the error reporting to be more user-friendly, at least in many of
brett
parents:
36
diff
changeset
|
1249 | self.successes.append(filename) |
30
1015bbd6dc5e
[svn] If we can't figure out what the file is by mimetype, try using the file
brett
parents:
29
diff
changeset
|
1250 | self.options.one_entry_policy.permanent_policy = EXTRACT_WRAP |
5 | 1251 | if self.failures: |
1252 | return 1 | |
1253 | return 0 | |
1254 | ||
1 | 1255 | |
1256 | if __name__ == '__main__': | |
5 | 1257 | app = ExtractorApplication(sys.argv[1:]) |
1258 | sys.exit(app.run()) |