2 from support
import pipe_through_command
8 def __init__(self
, extension
):
9 operations
.append(self
)
10 self
.extension
= extension
12 def can_handle(self
, data
):
13 return isinstance(data
, FileData
)
15 def save_to_stream(self
, data
, stream
):
16 pipe_through_command(self
.command
, data
.source
, stream
)
18 class Compress(Operation
):
19 "Compress a stream into another stream."
22 def __init__(self
, extension
, command
, type):
23 Operation
.__init
__(self
, extension
)
24 self
.command
= command
28 return 'Compress as .%s' % self
.extension
30 class Decompress(Operation
):
31 "Decompress a stream into another stream."
34 def __init__(self
, extension
, command
):
35 Operation
.__init
__(self
, extension
)
36 self
.command
= command
39 return 'Decompress .%s' % self
.extension
41 class Extract(Operation
):
42 "Extract an archive to a directory."
43 type = 'inode/directory'
45 def __init__(self
, extension
, command
):
46 Operation
.__init
__(self
, extension
)
47 self
.command
= command
50 return 'Extract from a .%s' % self
.extension
52 def save_to_stream(self
, data
, stream
):
53 raise Exception('This operation creates a directory, so you have '
54 'to drag to a filer window on the local machine')
56 def save_to_file(self
, data
, path
):
57 if os
.path
.exists(path
):
58 if not os
.path
.isdir(path
):
59 raise Exception("'%s' already exists and is not a directory!" %
61 if not rox
.confirm('Directory already exists; extract into it?',
63 raise Exception('Extraction aborted... try somewhere else')
64 if not os
.path
.exists(path
):
67 pipe_through_command(self
.command
, data
.source
, None)
69 class ExtractPath(Extract
):
70 "Extract an archive (which must be a file) to a directory."
71 def save_to_file(self
, data
, path
):
72 raise Exception('Not implemented yet')
74 class Archive(Operation
):
75 "Create an archive from a directory."
78 def __init__(self
, extension
, command
, type):
79 Operation
.__init
__(self
, extension
)
80 self
.command
= command
84 return 'Create .%s archive' % self
.extension
86 def can_handle(self
, data
):
87 return isinstance(data
, DirData
)
89 tgz
= Extract('tgz', "gunzip -c - | tar xf -")
90 tbz
= Extract('tar.bz2', "bunzip2 -c - | tar xf -")
91 zip = Extract('zip', "unzip -")
92 jar
= Extract('jar', "unzip -")
93 rar
= Extract('rar', "rar x -")
94 tar
= Extract('tar', "tar xf -")
95 rpm
= Extract('rpm', "rpm2cpio - | cpio -id --quiet")
96 cpio
= Extract('cpio', "cpio -id --quiet")
97 deb
= ExtractPath('deb', "ar x '%s'")
99 make_tgz
= Archive('tgz', "tar cf - '%s' | gzip", 'application/x-compressed-tar')
100 Archive('tar.gz', "tar cf - '%s' | gzip", 'application/x-compressed-tar')
101 Archive('tar.bz', "tar cf - '%s' | bzip2", 'application/x-bzip-compressed-tar')
102 Archive('tar.bz2', "tar cf - '%s' | bzip2", 'application/x-bzip-compressed-tar')
103 Archive('zip', "zip -r - '%s'", 'application/zip'),
104 Archive('jar', "zip -r - '%s'", 'application/x-jar')
105 Archive('rar', "rar a - '%s'", 'application/x-rar'),
106 Archive('tar', "tar cf - '%s'", 'application/x-tar')
108 # Note: these go afterwards so that .tar.gz matches before .gz
109 make_gz
= Compress('gz', "gzip -c -", 'application/x-gzip')
110 Compress('bz2', "bzip2 -c -", 'application/x-bzip')
112 gz
= Decompress('gz', "gunzip -c -")
113 bz2
= Decompress('bz2', "bunzip2 -ck -")
116 # Can bzip2 read bzip files?
124 known_extensions
= {}
127 known_extensions
[x
.extension
] = None
128 except AttributeError:
131 def guess_format(data
):
132 "Return a good default Operation, judging by the first 300 bytes or so."
134 def string(offset
, match
):
135 return data
[offset
:offset
+ len(match
)] == match
136 def short(offset
, match
):
140 return ((a
== match
& 0xff) and (b
== (match
>> 8))) or \
141 (b
== match
& 0xff) and (a
== (match
>> 8))
145 if string(257, 'ustar\0') or string(257, 'ustar\040\040\0'):
147 if short(0, 070707) or short(0, 0143561) or string(0, '070707') or \
148 string(0, '070701') or string(0, '070702'):
150 if string(0, '!<arch>') or string(0, '\\<ar>') or string(0, '<ar>'):
151 if string(7, '\ndebian'):
153 if string(0, 'Rar!'): return rar
154 if string(0, 'PK\003\004'): return zip
157 if string(0, '\037\213'): return gz
158 if string(0, 'BZh'): return bz2
159 if string(0, 'BZ'): return bz2
# bzip, but maybe bzip2 can cope?
164 "A file on the local filesystem."
165 def __init__(self
, path
):
174 rox
.report_exception()
178 start
= source
.read(300)
184 # Input is not a regular, local, seekable file, so copy it
185 # to a local temp file.
189 shutil
.copyfileobj(source
, tmp
)
191 self
.default
= guess_format(start
)
197 for ext
in known_extensions
:
198 if path
.endswith('.' + ext
):
199 new
= path
[:-len(ext
)-1]
200 if len(new
) < len(name
):
202 self
.default_name
= name
205 def __init__(self
, path
):
207 self
.default
= make_tgz
208 self
.default_name
= path
+ self
.default
.extension