11 from rox
.SaveBox
import SaveBox
13 from rox
import choices
19 # Extension, extract, create
20 ('.tar', "tar xf '%s'", "tar cf '%(dst)s' '%(src)s'"),
21 ('.zip', "unzip '%s'", "zip -r '%(dst)s' '%(src)s'"),
22 ('.deb', "ar x '%s'", None),
23 ('.rar', "rar x '%s'", "rar a '%(dst)s' '%(src)s'"),
25 ('.tgz', "gunzip -c '%s' | tar xf -",
26 "tar cf - '%(src)s' | gzip > '%(dst)s'"),
27 ('.tar.gz', "gunzip -c '%s' | tar xf -",
28 "tar cf - '%(src)s' | gzip > '%(dst)s'"),
30 ('.tbz', "bunzip2 -c '%s' | tar xf -",
31 "tar cf - '%(src)s' | bzip2 > '%(dst)s'"),
32 ('.tar.bz', "bunzip2 -c '%s' | tar xf -",
33 "tar cf - '%(src)s' | bzip2 > '%(dst)s'"),
34 ('.tbz2', "bunzip2 -c '%s' | tar xf -",
35 "tar cf - '%(src)s' | bzip2 > '%(dst)s'"),
36 ('.tar.bz2', "bunzip2 -c '%s' | tar xf -",
37 "tar cf - '%(src)s' | bzip2 > '%(dst)s'")
40 compressed_formats
= [
41 # Ext, extract, compress, type
42 ('.gz', "gunzip -c '%s'", "gzip -c '%s'", 'x-gzip'),
43 ('.bz', "bunzip2 -ck '%s'", "bzip2 -c '%s'", 'x-bzip'),
44 ('.bz2', "bunzip2 -ck '%s'", "bzip2 -c '%s'", 'x-bzip')
47 def get_format(path
, formats
):
50 if ext
== string
.lower(path
[-len(ext
):]):
55 """Return text with \ and ' escaped"""
56 return re
.sub("'", "'\"'\"'", text
)
58 def bg_system(command
, out
= None):
59 "system(command), but still process GUI events while waiting..."
60 "If 'out' is set then the child's stdout goes to that FD. 'out' is "
61 "closed in the parent process."
72 report_error("fork() failed!")
85 os
.setpgid(0, 0) # Start a new process group
89 error
= os
.system(command
) != 0
100 def cb(src
, cond
, done
= done
):
101 data
= os
.read(src
, 100)
103 done
[0] = done
[0] + data
106 tag
= input_add(r
, INPUT_READ
, cb
)
114 (pid
, status
) = waitpid(child_pid
, 0)
117 str = string
.strip(done
[0])
120 report_error("Error: " + str)
122 report_error("Operation failed")
126 def make_archiver(path
):
127 while path
[-1:] == '/':
129 if os
.path
.isdir(path
):
130 window
= ArchiveDir(path
)
133 f
= get_format(path
, archive_formats
)
135 window
= ExtractDir(path
, f
)
137 f
= get_format(path
, compressed_formats
)
139 window
= ExtractFile(path
, f
)
141 window
= ArchiveFile(path
)
143 window
.connect('destroy', lambda w
: rox_toplevel_unref())
148 "If dir contains only one subdir, move its contents into dir."
149 list = os
.listdir(dir)
153 subdir
= os
.path
.join(dir, list[0])
154 if not os
.path
.isdir(subdir
):
159 tmp
= os
.tempnam(dir)
160 os
.rename(subdir
, tmp
)
163 print "Warning: failed to rename(%s, %s)\n" % (subdir
, tmp
)
165 for file in os
.listdir(subdir
):
166 bg_system("mv '%s' ." % esc(os
.path
.join(subdir
, file)))
169 def report_known(formats
):
170 txt
= "Allowed extensions are:\n"
173 txt
= txt
+ f
[0] + '\n'
176 class Archive(SaveBox
):
177 def __init__(self
, win
, type):
178 SaveBox
.__init
__(self
, self
, self
.uri
, type);
179 self
.connect('destroy', self
.destroyed
)
181 def destroyed(self
, widget
):
185 os
.kill(-child_pid
, signal
.SIGTERM
)
187 def save_as_file(self
, path
):
188 self
.set_sensitive(FALSE
)
191 success
= self
.do_save(path
)
195 self
.set_sensitive(TRUE
);
198 def set_uri(self
, uri
):
199 path
= get_local_path(uri
)
201 child('rox', '-x', path
)
204 # save_as(path) - write data to file, TRUE on success
205 # set_uri(uri) - data is safely saved to this location
207 class ExtractDir(Archive
):
208 def __init__(self
, path
, format
):
211 self
.extract
= format
[1]
212 uri
= path
[:-len(ext
)]
214 found
= re
.match(r
'^(.*)-(\d+\.)*\d+$', uri
)
216 self
.uri
= found
.group(1)
219 Archive
.__init
__(self
, self
, 'special/directory')
221 def do_save(self
, path
):
224 if bg_system(self
.extract
% esc(self
.path
)):
230 class ExtractFile(Archive
):
231 def __init__(self
, path
, format
):
234 self
.extract
= format
[1]
235 self
.uri
= path
[:-len(ext
)]
236 Archive
.__init
__(self
, self
, 'text/plain')
238 def do_save(self
, path
):
239 if os
.path
.exists(path
):
240 report_error("File `%s' already exists!" % path
)
242 stats
= os
.stat(self
.path
)
243 mode
= stat
.S_IMODE(stats
[stat
.ST_MODE
]) & 0x1ff;
244 out
= os
.open(path
, os
.O_WRONLY | os
.O_CREAT
, mode
)
245 return bg_system(self
.extract
% esc(self
.path
), out
= out
) == 0
247 def save_as_selection(self
, selection_data
):
251 def cb(src
, cond
, self
= self
):
252 self
.data
= self
.data
+ os
.read(src
, 1024)
253 input_add(r
, INPUT_READ
, cb
)
255 bg_system(self
.extract
% esc(self
.path
), out
= w
)
258 new
= os
.read(r
, 1024)
261 self
.data
= self
.data
+ new
263 selection_data
.set(selection_data
.target
, 8, self
.data
)
266 class ArchiveFile(Archive
):
267 def __init__(self
, path
):
269 self
.uri
= path
+ '.gz'
270 Archive
.__init
__(self
, self
, 'application/x-gzip')
272 def do_save(self
, path
):
273 format
= get_format(path
, compressed_formats
)
274 if not format
or not format
[2]:
275 report_known(compressed_formats
)
278 if os
.path
.exists(path
):
279 report_error("File `%s' already exists!" % path
)
281 stats
= os
.stat(self
.path
)
282 mode
= stat
.S_IMODE(stats
[stat
.ST_MODE
]) & 0x1ff;
283 out
= os
.open(path
, os
.O_WRONLY | os
.O_CREAT
, mode
)
284 return bg_system(format
[2] % esc(self
.path
), out
= out
) == 0
286 class ArchiveDir(Archive
):
287 def __init__(self
, path
):
289 self
.uri
= path
+ '.tgz'
290 Archive
.__init
__(self
, self
, 'application/x-compressed-tar')
292 def do_save(self
, path
):
293 format
= get_format(path
, archive_formats
)
294 if not format
or not format
[2]:
295 report_known(archive_formats
)
298 os
.chdir(os
.path
.dirname(self
.uri
))
299 retval
= bg_system(format
[2] % {
300 'src' : esc(os
.path
.basename(self
.path
)),