4 import sys
, os
, formats
7 from rox
import g
, TRUE
, FALSE
, saving
10 rox
.info("Drag a file or directory onto Archive to archive it. "
11 "Drag an archive onto it to extract.")
14 from support
import escape
, Tmp
, pipe_through_command
16 # Show the savebox, so at least the user knows something is happening..
17 class FileData(saving
.Saveable
):
18 "A file on the local filesystem."
19 def __init__(self
, path
, stream
):
21 self
.start
= stream
.read(300)
27 # Input is not a regular, local, seekable file, so copy it
28 # to a local temp file.
32 shutil
.copyfileobj(stream
, tmp
)
38 ('test', "wibble", 'application/x-gzip'),
39 ('gz', "gzip -c -", 'application/x-gzip'),
40 ('bz2', "bzip2 -c -", 'application/x-bzip')
44 # Archives. Executed from new directory.
45 ('tgz', "gunzip -c - | tar xf -", 'inode/directory'),
46 ('tar.gz', "gunzip -c - | tar xf -", 'inode/directory'),
47 ('tar.bz', "bunzip2 -c - | tar xf -", 'inode/directory'),
48 ('tar.bz2', "bunzip2 -c - | tar xf -", 'inode/directory'),
49 ('zip', "unzip -", None),
50 ('rar', "rar x -", None),
51 ('tar', "tar xf -", None)
56 ('gz', "gunzip -c -", None),
57 ('bz', "bunzip2 -ck -", None),
58 ('bz2', "bunzip2 -ck -", None)
61 def need_dir(self
, command
):
62 return command
in [c
for e
,c
,t
in self
.extract_arc
]
64 def save_to_file(self
, file):
66 if self
.need_dir(command
):
69 pipe_through_command(command
, self
.stream
, None)
71 saving
.Saveable
.save_to_file(self
, file)
73 def save_to_stream(self
, stream
):
75 if self
.need_dir(command
):
76 raise Exception('Sorry, archives can only be extracted into '
79 pipe_through_command(command
, self
.stream
, stream
)
84 class DirData(saving
.Saveable
):
85 def __init__(self
, source
):
90 ('tgz', "tar cf - '%s' | gzip", 'application/x-compressed-tar'),
91 ('tar.gz', "tar cf - '%s' | gzip", 'application/x-compressed-tar'),
92 ('tar.bz', "tar cf - '%s' | bzip2", 'application/x-bzip-compressed-tar'),
93 ('tar.bz2', "tar cf - '%s' | bzip2", 'application/x-bzip-compressed-tar'),
94 ('zip', "zip -r - '%s'", 'application/zip'),
95 ('rar', "rar a - '%s'", 'application/x-rar'),
96 ('tar', "tar cf - '%s'", 'application/x-tar')
103 def save_to_stream(self
, stream
):
104 command
= self
.op
% escape(self
.path
)
105 pipe_through_command(command
, None, stream
)
107 def set_op(self
, op
):
110 class ArchiveBox(saving
.SaveBox
):
111 def build_main_area(self
):
112 self
.vbox
.add(self
.save_area
)
114 self
.operation
= g
.OptionMenu()
115 self
.vbox
.pack_start(self
.operation
, FALSE
, TRUE
, 0)
116 self
.operation
.show()
117 self
.operation
.set_border_width(5)
120 self
.ops_menu
= g
.Menu()
121 self
.operation
.set_menu(self
.ops_menu
)
124 doc
= self
.save_area
.document
126 for op
, command
, type in doc
.create_arc
:
127 item
= g
.MenuItem('Create .%s archive' % op
)
129 self
.ops_menu
.append(item
)
130 self
.i_to_op
.append((op
, command
, type))
131 for op
, command
, type in doc
.create_stream
:
132 item
= g
.MenuItem('Compress as .%s' % op
)
134 self
.ops_menu
.append(item
)
135 self
.i_to_op
.append((op
, command
, type))
138 guess
= formats
.guess_format(doc
.start
)
142 if guess
in ['gz', 'bz2', 'bz']:
143 if doc
.path
.endswith('.tar.' + guess
):
144 guess
= 'tar.' + guess
147 for op
, command
, type in doc
.extract_arc
:
148 item
= g
.MenuItem('Extract from a .%s' % op
)
150 self
.ops_menu
.append(item
)
152 init
= len(self
.i_to_op
)
153 self
.i_to_op
.append((op
, command
, type))
154 for op
, command
, type in doc
.extract_stream
:
155 item
= g
.MenuItem('Uncompress .%s' % op
)
157 self
.ops_menu
.append(item
)
159 init
= len(self
.i_to_op
)
160 self
.i_to_op
.append((op
, command
, type))
163 if guess
and name
.endswith('.' + guess
):
164 name
= name
[:-len(guess
)-1]
165 self
.save_area
.entry
.set_text(name
)
167 self
.operation
.connect('changed', self
.op_changed
)
168 self
.save_area
.entry
.connect('changed', self
.name_changed
)
169 self
.operation
.set_history(init
)
171 def name_changed(self
, entry
):
176 name
= entry
.get_text()
177 doc
= self
.save_area
.document
179 for o
, command
, type in doc
.create_arc
+ doc
.create_stream
:
180 if name
.endswith('.' + o
):
181 self
.operation
.set_history(i
)
187 def op_changed(self
, operation
):
188 i
= operation
.get_history()
189 doc
= self
.save_area
.document
196 self
.set_type('text/plain')
202 name
= self
.save_area
.entry
.get_text()
205 for o
, command
, type in doc
.create_arc
+ doc
.create_stream
:
206 if name
.endswith('.' + o
):
207 name
= name
[:-len(o
)-1]
209 if i
< len(doc
.create_arc
):
210 name
+= '.' + doc
.create_arc
[i
][0]
212 i
-= len(doc
.create_arc
)
213 if i
< len(doc
.create_stream
):
214 name
+= '.' + doc
.create_stream
[i
][0]
215 self
.save_area
.entry
.set_text(name
)
219 # Check that our input is a regular local file.
220 # If not, fetch the data and put it in /tmp.
229 path
= rox
.get_local_path(path
)
231 rox
.croak('Sorry, I can only extract/archive local files.')
232 if not os
.path
.isdir(path
):
236 rox
.report_exception()
240 data
= FileData(path
, source
)
244 savebox
= ArchiveBox(data
, '', 'text/plain')