Mercurial > gcp
comparison gcp @ 3:6a24b5928980
Basic file copying
- missing dir are created (without permission check yet)
- new options to deactivate progress bar
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 26 Sep 2010 12:00:05 +0800 |
parents | 1b91aa4f3c85 |
children | 9feb82bd91aa |
comparison
equal
deleted
inserted
replaced
2:1b91aa4f3c85 | 3:6a24b5928980 |
---|---|
63 This software is an advanced file copier | 63 This software is an advanced file copier |
64 Get the latest version at http://www.goffi.org | 64 Get the latest version at http://www.goffi.org |
65 """ | 65 """ |
66 | 66 |
67 const_DBUS_INTERFACE = "org.goffi.gcp" | 67 const_DBUS_INTERFACE = "org.goffi.gcp" |
68 const_DBUS_PATH = "/org/goffi/gcp" | 68 const_DBUS_PATH = "/org/goffi/gcp" |
69 const_BUFF_SIZE = 4096 | |
69 | 70 |
70 | 71 |
71 class DbusObject(dbus.service.Object): | 72 class DbusObject(dbus.service.Object): |
72 | 73 |
73 def __init__(self, gcp, bus, path): | 74 def __init__(self, gcp, bus, path): |
110 except dbus.exceptions.DBusException,e: | 111 except dbus.exceptions.DBusException,e: |
111 if e._dbus_error_name=='org.freedesktop.DBus.Error.ServiceUnknown': | 112 if e._dbus_error_name=='org.freedesktop.DBus.Error.ServiceUnknown': |
112 self.launchDbusMainInstance() | 113 self.launchDbusMainInstance() |
113 debug ("gcp launched") | 114 debug ("gcp launched") |
114 self._main_instance = True | 115 self._main_instance = True |
116 self.buffer_size = const_BUFF_SIZE | |
115 else: | 117 else: |
116 raise e | 118 raise e |
117 | 119 |
118 def launchDbusMainInstance(self): | 120 def launchDbusMainInstance(self): |
119 debug ("Init DBus...") | 121 debug ("Init DBus...") |
145 ret[fs_file] = fs_vfstype | 147 ret[fs_file] = fs_vfstype |
146 except: | 148 except: |
147 error ("Can't read mounts table") | 149 error ("Can't read mounts table") |
148 return ret | 150 return ret |
149 | 151 |
150 def __appendToList(self, path, destpath, options): | 152 def __appendToList(self, path, dest_path, options): |
151 """Add a file to the copy list | 153 """Add a file to the copy list |
152 @param path: absolute path of file | 154 @param path: absolute path of file |
153 @param options: options as return by optparse""" | 155 @param options: options as return by optparse""" |
154 debug ("Adding to copy list: %s ==> %s (%s)", path, destpath, self.getFsType(destpath)) | 156 debug ("Adding to copy list: %s ==> %s (%s)", path, dest_path, self.getFsType(dest_path)) |
155 try: | 157 try: |
156 self.bytes_left+=os.path.getsize(path) | 158 self.bytes_left+=os.path.getsize(path) |
157 self.files_left+=1 | 159 self.files_left+=1 |
158 self.copy_list.append((path, destpath, options)) | 160 self.copy_list.append((path, dest_path, options)) |
159 print "total size:", float(self.bytes_left/1024/1024), "Mb (%i)" % self.files_left | 161 print "total size:", float(self.bytes_left/1024/1024), "Mb (%i)" % self.files_left |
160 except OSError,e: | 162 except OSError,e: |
161 error("Can't copy %(path)s: %(exception)s" % {'path':path, 'exception':e.strerror}) | 163 error("Can't copy %(path)s: %(exception)s" % {'path':path, 'exception':e.strerror}) |
162 | 164 |
163 | 165 |
164 def __appendDirToList(self, dirpath, destpath, options): | 166 def __appendDirToList(self, dirpath, dest_path, options): |
165 """Add recursively directory to the copy list | 167 """Add recursively directory to the copy list |
166 @param path: absolute path of dir | 168 @param path: absolute path of dir |
167 @param options: options as return by optparse""" | 169 @param options: options as return by optparse""" |
170 #We first check that the dest path exists, and create it if needed | |
171 if not os.path.exists(dest_path): | |
172 debug ("Creating directory %s" % dest_path) | |
173 os.makedirs(dest_path) #TODO: check permissions | |
174 #TODO: check that dest_path is an accessible dir, | |
175 # and skip file/write error in log if needed | |
168 try: | 176 try: |
169 for filename in os.listdir(dirpath): | 177 for filename in os.listdir(dirpath): |
170 filepath = os.path.join(dirpath,filename) | 178 filepath = os.path.join(dirpath,filename) |
171 if os.path.isdir(filepath): | 179 if os.path.isdir(filepath): |
172 full_destpath = os.path.join(destpath,filename) | 180 full_dest_path = os.path.join(dest_path,filename) |
173 self.__appendDirToList(filepath, full_destpath, options) | 181 self.__appendDirToList(filepath, full_dest_path, options) |
174 else: | 182 else: |
175 self.__appendToList(filepath, destpath, options) | 183 self.__appendToList(filepath, dest_path, options) |
176 except OSError,e: | 184 except OSError,e: |
177 error("Can't copy %(path)s: %(exception)s" % {'path':dirpath, 'exception':e.strerror}) | 185 error("Can't copy %(path)s: %(exception)s" % {'path':dirpath, 'exception':e.strerror}) |
178 | 186 |
179 def __checkArgs(self, options, source_path, args): | 187 def __checkArgs(self, options, source_path, args): |
180 """Check thats args are files, and add them to copy list""" | 188 """Check thats args are files, and add them to copy list""" |
181 assert(len (args)>=2) | 189 assert(len (args)>=2) |
182 try: | 190 try: |
183 destpath = os.path.normpath(os.path.join(os.path.expanduser(source_path), args.pop())) | 191 dest_path = os.path.normpath(os.path.join(os.path.expanduser(source_path), args.pop())) |
184 except OSError,e: | 192 except OSError,e: |
185 error ("Invalid destpath: %s",e) | 193 error ("Invalid dest_path: %s",e) |
186 | 194 |
187 for path in args: | 195 for path in args: |
188 abspath = os.path.normpath(os.path.join(os.path.expanduser(source_path), path)) | 196 abspath = os.path.normpath(os.path.join(os.path.expanduser(source_path), path)) |
189 if not os.path.exists(abspath): | 197 if not os.path.exists(abspath): |
190 warning("The path given in arg doesn't exist or is not accessible: %s",abspath) | 198 warning("The path given in arg doesn't exist or is not accessible: %s",abspath) |
191 else: | 199 else: |
192 if os.path.isdir(abspath): | 200 if os.path.isdir(abspath): |
193 full_destpath = destpath if os.path.isabs(path) else os.path.normpath(os.path.join(destpath, path)) | 201 full_dest_path = dest_path if os.path.isabs(path) else os.path.normpath(os.path.join(dest_path, path)) |
194 if not options.recursive: | 202 if not options.recursive: |
195 warning ('omitting directory "%s"' % abspath) | 203 warning ('omitting directory "%s"' % abspath) |
196 else: | 204 else: |
197 self.__appendDirToList(abspath, full_destpath, options) | 205 self.__appendDirToList(abspath, full_dest_path, options) |
198 else: | 206 else: |
199 self.__appendToList(abspath, destpath, options) | 207 self.__appendToList(abspath, dest_path, options) |
200 | 208 |
209 def __copyNextFile(self): | |
210 """Take the last file in the list, and launch the copy using glib io_watch event | |
211 @return: True a file was added, False else""" | |
212 if self.copy_list: | |
213 source_path, dest_path, options = self.copy_list.pop() | |
214 source_fd = open(source_path, 'r') | |
215 filename = os.path.basename(source_path) | |
216 assert(filename) | |
217 dest_file = os.path.join(dest_path,filename) | |
218 if os.path.exists(dest_file): | |
219 warning ("File [%s] already exists, skipping it !" % dest_file) | |
220 return True | |
221 dest_fd = open(dest_file, 'w') | |
222 | |
223 self.total=0 | |
224 gobject.io_add_watch(source_fd,gobject.IO_IN,self._copyFile,(dest_fd,options), priority=gobject.PRIORITY_HIGH) | |
225 print "** COPYING",source_path,"==>",dest_file | |
226 return True | |
227 else: | |
228 #Nothing left to copy, we quit | |
229 self.loop.quit() | |
230 | |
231 def _copyFile(self, source_fd, condition, data): | |
232 """Actually copy the file, callback used with io_add_watch | |
233 @param source_fd: file descriptor of the file to copy | |
234 @param condition: condition which launched the callback (glib.IO_IN) | |
235 @param data: tuple with (destination file descriptor, copying options)""" | |
236 dest_fd,options = data | |
237 buff = source_fd.read(self.buffer_size) | |
238 dest_fd.write(buff) | |
239 self.total += len(buff) | |
240 sys.stdout.write('%i written\r' % self.total) | |
241 if len(buff) != self.buffer_size: | |
242 sys.stdout.write('\n---\n') | |
243 source_fd.close() | |
244 dest_fd.close() | |
245 return False | |
246 return True | |
247 | |
248 | |
201 | 249 |
202 def parseArguments(self, full_args=sys.argv[1:], source_path = os.getcwd()): | 250 def parseArguments(self, full_args=sys.argv[1:], source_path = os.getcwd()): |
203 """Parse arguments and add files to queue | 251 """Parse arguments and add files to queue |
204 @param full_args: list of arguments strings (without program name) | 252 @param full_args: list of arguments strings (without program name) |
205 @param source_path: path from where the arguments come, ad given by os.getcwd() | 253 @param source_path: path from where the arguments come, ad given by os.getcwd() |
220 parser.add_option("-r", "--recursive", action="store_true", default=False, | 268 parser.add_option("-r", "--recursive", action="store_true", default=False, |
221 help="copy directories recursively") | 269 help="copy directories recursively") |
222 | 270 |
223 parser.add_option("--no-unicode-fix", action="store_true", default=False, | 271 parser.add_option("--no-unicode-fix", action="store_true", default=False, |
224 help="don't fixe name encoding errors") #TODO | 272 help="don't fixe name encoding errors") #TODO |
273 | |
274 parser.add_option("--no-progress", action="store_false", dest="progress", default=True, | |
275 help="deactivate progress bar") | |
276 | |
225 (options, args) = parser.parse_args(full_args) | 277 (options, args) = parser.parse_args(full_args) |
278 if options.progress and not pbar_available: | |
279 warning ("Progress bar is not available, deactivating") | |
280 options.progress = False | |
226 | 281 |
227 if not self._main_instance: | 282 if not self._main_instance: |
228 info ("There is already one instance of %s running, pluging to it" % NAME_SHORT) | 283 info ("There is already one instance of %s running, pluging to it" % NAME_SHORT) |
229 #XXX: we have to serialize data as dbus only accept valid unicode, and filenames | 284 #XXX: we have to serialize data as dbus only accept valid unicode, and filenames |
230 # can have invalid unicode. | 285 # can have invalid unicode. |
233 if len(args) < 2: | 288 if len(args) < 2: |
234 _error_msg = "Wrong number of arguments" | 289 _error_msg = "Wrong number of arguments" |
235 return (False, _error_msg) | 290 return (False, _error_msg) |
236 debug("adding args to gcp: %s",args) | 291 debug("adding args to gcp: %s",args) |
237 self.__checkArgs(options, source_path, args) | 292 self.__checkArgs(options, source_path, args) |
293 gobject.idle_add(self.__copyNextFile) | |
238 return (True,'') | 294 return (True,'') |
239 | 295 |
240 def go(self): | 296 def go(self): |
241 """Launch main loop""" | 297 """Launch main loop""" |
242 self.loop = gobject.MainLoop() | 298 self.loop = gobject.MainLoop() |