9 from gtk
import TRUE
, FALSE
11 from rox2
.SaveBox
import SaveBox
12 from rox2
import support
13 from rox2
import choices
21 """Return text with \ and ' escaped"""
22 return re
.sub("'", "'\"'\"'", text
)
24 def bg_system(command
, out
= None):
25 "system(command), but still process GUI events while waiting..."
26 "If 'out' is set then the child's stdout goes to that FD. 'out' is "
27 "closed in the parent process."
38 support
.report_error("fork() failed!")
51 os
.setpgid(0, 0) # Start a new process group
55 error
= os
.system(command
) != 0
66 def cb(src
, cond
, done
= done
):
67 data
= os
.read(src
, 100)
69 done
[0] = done
[0] + data
72 tag
= gtk
.input_add_full(r
, gtk
.gdk
.INPUT_READ
, cb
)
80 (pid
, status
) = os
.waitpid(child_pid
, 0)
83 str = string
.strip(done
[0])
86 support
.report_error("Error: " + str)
88 support
.report_error("Operation failed")
92 def make_archiver(path
):
93 while path
[-1:] == '/':
95 if os
.path
.isdir(path
):
96 window
= ArchiveDir(path
)
99 f
= get_format(path
, archive_formats
)
101 window
= ExtractDir(path
, f
)
103 f
= get_format(path
, compressed_formats
)
105 window
= ExtractFile(path
, f
)
107 window
= ArchiveFile(path
)
112 "If dir contains only one subdir, move its contents into dir."
113 list = os
.listdir(dir)
117 subdir
= os
.path
.join(dir, list[0])
118 if not os
.path
.isdir(subdir
):
123 tmp
= os
.tempnam(dir)
124 os
.rename(subdir
, tmp
)
127 print "Warning: failed to rename(%s, %s)\n" % (subdir
, tmp
)
129 for file in os
.listdir(subdir
):
130 bg_system("mv '%s' ." % esc(os
.path
.join(subdir
, file)))
133 def report_known(formats
):
134 txt
= "Allowed extensions are:\n"
137 txt
= txt
+ f
[0] + '\n'
138 support
.report_error(txt
)
140 from os
import _exit
, fork
, execvp
, dup2
143 """Spawn a new process. Connect stderr to stdout."""
149 execvp(argv
[0], argv
)
152 print "Warning: exec('%s') failed!" % argv
[0]
155 print "Error: fork() failed!"
157 class Archive(SaveBox
):
158 def __init__(self
, win
, type):
159 SaveBox
.__init
__(self
, self
, self
.uri
, type);
160 self
.connect('destroy', self
.destroyed
)
162 if not hasattr(self
, 'changed'):
164 self
.save_area
.entry
.connect('changed', self
.changed
)
166 def destroyed(self
, widget
):
170 os
.kill(-child_pid
, signal
.SIGTERM
)
172 def save_as_file(self
, path
):
173 self
.set_sensitive(FALSE
)
176 success
= self
.do_save(path
)
179 support
.report_exception()
180 self
.set_sensitive(TRUE
);
183 def set_uri(self
, uri
):
184 path
= support
.get_local_path(uri
)
186 child('rox', '-x', path
)
189 # save_as(path) - write data to file, TRUE on success
190 # set_uri(uri) - data is safely saved to this location
192 class ExtractDir(Archive
):
193 def __init__(self
, path
, format
):
196 self
.extract
= format
[1]
197 uri
= path
[:-len(ext
)]
199 found
= re
.match(r
'^(.*)-(\d+\.)*\d+$', uri
)
201 self
.uri
= found
.group(1)
204 Archive
.__init
__(self
, self
, 'special/directory')
206 def do_save(self
, path
):
209 if bg_system(self
.extract
% esc(self
.path
)):
215 class ExtractFile(Archive
):
216 def __init__(self
, path
, format
):
219 self
.extract
= format
[1]
220 self
.uri
= path
[:-len(ext
)]
221 Archive
.__init
__(self
, self
, 'text/plain')
223 def do_save(self
, path
):
224 if os
.path
.exists(path
):
225 support
.report_error("File `%s' already exists!" % path
)
227 stats
= os
.stat(self
.path
)
228 mode
= stat
.S_IMODE(stats
[stat
.ST_MODE
]) & 0x1ff;
229 out
= os
.open(path
, os
.O_WRONLY | os
.O_CREAT
, mode
)
230 return bg_system(self
.extract
% esc(self
.path
), out
= out
) == 0
232 def save_as_selection(self
, selection_data
):
236 def cb(src
, cond
, self
= self
):
237 self
.data
= self
.data
+ os
.read(src
, 1024)
238 gtk
.input_add_full(r
, gtk
.gdk
.INPUT_READ
, cb
)
240 bg_system(self
.extract
% esc(self
.path
), out
= w
)
243 new
= os
.read(r
, 1024)
246 self
.data
= self
.data
+ new
248 selection_data
.set(selection_data
.target
, 8, self
.data
)
251 class ArchiveFile(Archive
):
252 def __init__(self
, path
):
254 self
.uri
= path
+ '.gz'
255 Archive
.__init
__(self
, self
, 'application/x-gzip')
257 def do_save(self
, path
):
258 format
= get_format(path
, compressed_formats
)
259 if not format
or not format
[2]:
260 report_known(compressed_formats
)
263 if os
.path
.exists(path
):
264 support
.report_error("File `%s' already exists!" % path
)
266 stats
= os
.stat(self
.path
)
267 mode
= stat
.S_IMODE(stats
[stat
.ST_MODE
]) & 0x1ff;
268 out
= os
.open(path
, os
.O_WRONLY | os
.O_CREAT
, mode
)
269 return bg_system(format
[2] % esc(self
.path
), out
= out
) == 0
271 def changed(self
, entry
):
272 path
= entry
.get_text()
273 format
= get_format(path
, compressed_formats
)
275 self
.set_type('error/unknown')
277 self
.set_type(format
[3])
279 class ArchiveDir(Archive
):
280 def __init__(self
, path
):
282 self
.uri
= path
+ '.tgz'
283 Archive
.__init
__(self
, self
, 'application/x-compressed-tar')
285 def do_save(self
, path
):
286 format
= get_format(path
, archive_formats
)
287 if not format
or not format
[2]:
288 report_known(archive_formats
)
291 os
.chdir(os
.path
.dirname(self
.uri
))
292 retval
= bg_system(format
[2] % {
293 'src' : esc(os
.path
.basename(self
.path
)),
298 def changed(self
, entry
):
299 path
= entry
.get_text()
300 format
= get_format(path
, archive_formats
)
301 if (not format
) or not format
[2]:
302 self
.set_type('error/unknown')
304 self
.set_type(format
[3])