← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~mterry/duplicity/backend-log-codes3 into lp:duplicity

 

Michael Terry has proposed merging lp:~mterry/duplicity/backend-log-codes3 into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)

-- 
https://code.launchpad.net/~mterry/duplicity/backend-log-codes3/+merge/42759
Your team duplicity-team is requested to review the proposed merge of lp:~mterry/duplicity/backend-log-codes3 into lp:duplicity.
=== modified file 'duplicity/backends/giobackend.py'
--- duplicity/backends/giobackend.py	2010-11-20 15:39:00 +0000
+++ duplicity/backends/giobackend.py	2010-12-04 22:17:53 +0000
@@ -29,6 +29,7 @@
 import duplicity.backend
 from duplicity import log
 from duplicity import globals
+from duplicity import util
 from duplicity.errors import * #@UnusedWildImport
 from duplicity.util import exception_traceback
 
@@ -88,10 +89,24 @@
                                % str(e), log.ErrorCode.connection_failed)
         loop.quit()
 
+    def handle_error(self, e, op, file1=None, file2=None):
+        code = log.ErrorCode.backend_error
+        if isinstance(e, gio.Error):
+            if e.code == gio.ERROR_PERMISSION_DENIED:
+                code = log.ErrorCode.backend_permission_denied
+            elif e.code == gio.ERROR_NOT_FOUND:
+                code = log.ErrorCode.backend_not_found
+            elif e.code == gio.ERROR_NO_SPACE:
+                code = log.ErrorCode.backend_no_space
+        extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
+        extra = ' '.join([op, extra])
+        log.FatalError(str(e), code, extra)
+
     def copy_progress(self, *args, **kwargs):
         pass
 
-    def copy_file(self, source, target):
+    def copy_file(self, op, source, target):
+        exc = None
         for n in range(1, globals.num_retries+1):
             log.Info(_("Writing %s") % target.get_parse_name())
             try:
@@ -103,8 +118,8 @@
                         % (target.get_parse_name(), n, e.__class__.__name__, str(e)))
                 log.Debug("Backtrace of previous error: %s"
                           % exception_traceback())
-        raise BackendException(_("Could not copy %s to %s") % (source.get_parse_name(),
-                                                               target.get_parse_name()))
+                exc = e
+        self.handle_error(exc, op, source.get_parse_name(), target.get_parse_name())
 
     def put(self, source_path, remote_filename = None):
         """Copy file to remote"""
@@ -112,19 +127,22 @@
             remote_filename = source_path.get_filename()
         source_file = gio.File(path=source_path.name)
         target_file = self.remote_file.get_child_for_display_name(remote_filename)
-        self.copy_file(source_file, target_file)
+        self.copy_file('put', source_file, target_file)
 
     def get(self, filename, local_path):
         """Get file and put in local_path (Path object)"""
         source_file = self.remote_file.get_child_for_display_name(filename)
         target_file = gio.File(path=local_path.name)
-        self.copy_file(source_file, target_file)
+        self.copy_file('get', source_file, target_file)
         local_path.setdata()
 
     def list(self):
         """List files in that directory"""
-        enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
-                                                   gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
+        try:
+            enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+                                                       gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
+        except Exception, e:
+            self.handle_error(e, 'list', self.remote_file.get_parse_name())
         files = []
         try:
             info = enum.next_file()
@@ -133,7 +151,7 @@
                 info = enum.next_file()
             return files
         except Exception, e:
-            raise BackendException(str(e))
+            self.handle_error(e, 'list')
 
     def delete(self, filename_list):
         """Delete all files in filename list"""
@@ -142,4 +160,4 @@
                 for filename in filename_list:
                         self.remote_file.get_child_for_display_name(filename).delete()
         except Exception, e:
-            raise BackendException(str(e))
+            self.handle_error(e, 'delete', self.remote_file.get_child_for_display_name(filename).get_parse_name())

=== modified file 'duplicity/backends/localbackend.py'
--- duplicity/backends/localbackend.py	2010-11-20 15:39:00 +0000
+++ duplicity/backends/localbackend.py	2010-12-04 22:17:53 +0000
@@ -21,10 +21,12 @@
 
 import os
 import types
+import errno
 
 import duplicity.backend
 from duplicity import log
 from duplicity import path
+from duplicity import util
 from duplicity.errors import * #@UnusedWildImport
 
 class LocalBackend(duplicity.backend.Backend):
@@ -41,6 +43,19 @@
             raise BackendException( "Bad file:// path syntax." )
         self.remote_pathdir = path.Path(parsed_url.path[2:])
 
+    def handle_error(self, e, op, file1=None, file2=None):
+        code = log.ErrorCode.backend_error
+        if hasattr(e, 'errno'):
+            if e.errno == errno.EACCES:
+                code = log.ErrorCode.backend_permission_denied
+            elif e.errno == errno.ENOENT:
+                code = log.ErrorCode.backend_not_found
+            elif e.errno == errno.ENOSPC:
+                code = log.ErrorCode.backend_no_space
+        extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
+        extra = ' '.join([op, extra])
+        log.FatalError(str(e), code, extra)
+
     def put(self, source_path, remote_filename = None, rename = None):
         """If rename is set, try that first, copying if doesn't work"""
         if not remote_filename:
@@ -52,14 +67,22 @@
                 source_path.rename(target_path)
             except OSError:
                 pass
+            except Exception, e:
+                handle_error(e, 'put', source_path.name, target_path.name)
             else:
                 return
-        target_path.writefileobj(source_path.open("rb"))
+        try:
+            target_path.writefileobj(source_path.open("rb"))
+        except Exception, e:
+            self.handle_error(e, 'put', source_path.name, target_path.name)
 
     def get(self, filename, local_path):
         """Get file and put in local_path (Path object)"""
         source_path = self.remote_pathdir.append(filename)
-        local_path.writefileobj(source_path.open("rb"))
+        try:
+            local_path.writefileobj(source_path.open("rb"))
+        except Exception, e:
+            self.handle_error(e, 'get', source_path.name, local_path.name)
 
     def list(self):
         """List files in that directory"""
@@ -67,7 +90,10 @@
                 os.makedirs(self.remote_pathdir.base)
         except:
                 pass
-        return self.remote_pathdir.listdir()
+        try:
+            return self.remote_pathdir.listdir()
+        except Exception, e:
+            self.handle_error(e, 'list', self.remote_pathdir.name)
 
     def delete(self, filename_list):
         """Delete all files in filename list"""
@@ -75,8 +101,8 @@
         for filename in filename_list:
             try:
                 self.remote_pathdir.append(filename).delete()
-            except OSError, e:
-                raise BackendException(str(e))
+            except Exception, e:
+                self.handle_error(e, 'delete', self.remote_pathdir.append(filename).name)
 
 
 duplicity.backend.register_backend("file", LocalBackend)

=== modified file 'duplicity/log.py'
--- duplicity/log.py	2010-11-20 15:39:00 +0000
+++ duplicity/log.py	2010-12-04 22:17:53 +0000
@@ -179,6 +179,13 @@
     restart_file_not_found = 39
     gio_not_available = 40
     source_dir_mismatch = 42 # 41 is reserved for par2
+
+    # 50->69 reserved for backend errors
+    backend_error = 50
+    backend_permission_denied = 51
+    backend_not_found = 52
+    backend_no_space = 53
+
     # Reserve 255 because it is used as an error code for gksu
 
 def FatalError(s, code, extra=None):


Follow ups