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

Proposed by Michael Terry
Status: Merged
Approved by: Kenneth Loafman
Approved revision: 687
Merged at revision: 687
Proposed branch: lp:~mterry/duplicity/backend-log-codes3
Merge into: lp:duplicity/0.6
Diff against target: 193 lines (+65/-14)
3 files modified
duplicity/backends/giobackend.py (+27/-9)
duplicity/backends/localbackend.py (+31/-5)
duplicity/log.py (+7/-0)
To merge this branch: bzr merge lp:~mterry/duplicity/backend-log-codes3
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+42759@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'duplicity/backends/giobackend.py'
2--- duplicity/backends/giobackend.py 2010-11-20 15:39:00 +0000
3+++ duplicity/backends/giobackend.py 2010-12-04 22:17:53 +0000
4@@ -29,6 +29,7 @@
5 import duplicity.backend
6 from duplicity import log
7 from duplicity import globals
8+from duplicity import util
9 from duplicity.errors import * #@UnusedWildImport
10 from duplicity.util import exception_traceback
11
12@@ -88,10 +89,24 @@
13 % str(e), log.ErrorCode.connection_failed)
14 loop.quit()
15
16+ def handle_error(self, e, op, file1=None, file2=None):
17+ code = log.ErrorCode.backend_error
18+ if isinstance(e, gio.Error):
19+ if e.code == gio.ERROR_PERMISSION_DENIED:
20+ code = log.ErrorCode.backend_permission_denied
21+ elif e.code == gio.ERROR_NOT_FOUND:
22+ code = log.ErrorCode.backend_not_found
23+ elif e.code == gio.ERROR_NO_SPACE:
24+ code = log.ErrorCode.backend_no_space
25+ extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
26+ extra = ' '.join([op, extra])
27+ log.FatalError(str(e), code, extra)
28+
29 def copy_progress(self, *args, **kwargs):
30 pass
31
32- def copy_file(self, source, target):
33+ def copy_file(self, op, source, target):
34+ exc = None
35 for n in range(1, globals.num_retries+1):
36 log.Info(_("Writing %s") % target.get_parse_name())
37 try:
38@@ -103,8 +118,8 @@
39 % (target.get_parse_name(), n, e.__class__.__name__, str(e)))
40 log.Debug("Backtrace of previous error: %s"
41 % exception_traceback())
42- raise BackendException(_("Could not copy %s to %s") % (source.get_parse_name(),
43- target.get_parse_name()))
44+ exc = e
45+ self.handle_error(exc, op, source.get_parse_name(), target.get_parse_name())
46
47 def put(self, source_path, remote_filename = None):
48 """Copy file to remote"""
49@@ -112,19 +127,22 @@
50 remote_filename = source_path.get_filename()
51 source_file = gio.File(path=source_path.name)
52 target_file = self.remote_file.get_child_for_display_name(remote_filename)
53- self.copy_file(source_file, target_file)
54+ self.copy_file('put', source_file, target_file)
55
56 def get(self, filename, local_path):
57 """Get file and put in local_path (Path object)"""
58 source_file = self.remote_file.get_child_for_display_name(filename)
59 target_file = gio.File(path=local_path.name)
60- self.copy_file(source_file, target_file)
61+ self.copy_file('get', source_file, target_file)
62 local_path.setdata()
63
64 def list(self):
65 """List files in that directory"""
66- enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
67- gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
68+ try:
69+ enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
70+ gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
71+ except Exception, e:
72+ self.handle_error(e, 'list', self.remote_file.get_parse_name())
73 files = []
74 try:
75 info = enum.next_file()
76@@ -133,7 +151,7 @@
77 info = enum.next_file()
78 return files
79 except Exception, e:
80- raise BackendException(str(e))
81+ self.handle_error(e, 'list')
82
83 def delete(self, filename_list):
84 """Delete all files in filename list"""
85@@ -142,4 +160,4 @@
86 for filename in filename_list:
87 self.remote_file.get_child_for_display_name(filename).delete()
88 except Exception, e:
89- raise BackendException(str(e))
90+ self.handle_error(e, 'delete', self.remote_file.get_child_for_display_name(filename).get_parse_name())
91
92=== modified file 'duplicity/backends/localbackend.py'
93--- duplicity/backends/localbackend.py 2010-11-20 15:39:00 +0000
94+++ duplicity/backends/localbackend.py 2010-12-04 22:17:53 +0000
95@@ -21,10 +21,12 @@
96
97 import os
98 import types
99+import errno
100
101 import duplicity.backend
102 from duplicity import log
103 from duplicity import path
104+from duplicity import util
105 from duplicity.errors import * #@UnusedWildImport
106
107 class LocalBackend(duplicity.backend.Backend):
108@@ -41,6 +43,19 @@
109 raise BackendException( "Bad file:// path syntax." )
110 self.remote_pathdir = path.Path(parsed_url.path[2:])
111
112+ def handle_error(self, e, op, file1=None, file2=None):
113+ code = log.ErrorCode.backend_error
114+ if hasattr(e, 'errno'):
115+ if e.errno == errno.EACCES:
116+ code = log.ErrorCode.backend_permission_denied
117+ elif e.errno == errno.ENOENT:
118+ code = log.ErrorCode.backend_not_found
119+ elif e.errno == errno.ENOSPC:
120+ code = log.ErrorCode.backend_no_space
121+ extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
122+ extra = ' '.join([op, extra])
123+ log.FatalError(str(e), code, extra)
124+
125 def put(self, source_path, remote_filename = None, rename = None):
126 """If rename is set, try that first, copying if doesn't work"""
127 if not remote_filename:
128@@ -52,14 +67,22 @@
129 source_path.rename(target_path)
130 except OSError:
131 pass
132+ except Exception, e:
133+ handle_error(e, 'put', source_path.name, target_path.name)
134 else:
135 return
136- target_path.writefileobj(source_path.open("rb"))
137+ try:
138+ target_path.writefileobj(source_path.open("rb"))
139+ except Exception, e:
140+ self.handle_error(e, 'put', source_path.name, target_path.name)
141
142 def get(self, filename, local_path):
143 """Get file and put in local_path (Path object)"""
144 source_path = self.remote_pathdir.append(filename)
145- local_path.writefileobj(source_path.open("rb"))
146+ try:
147+ local_path.writefileobj(source_path.open("rb"))
148+ except Exception, e:
149+ self.handle_error(e, 'get', source_path.name, local_path.name)
150
151 def list(self):
152 """List files in that directory"""
153@@ -67,7 +90,10 @@
154 os.makedirs(self.remote_pathdir.base)
155 except:
156 pass
157- return self.remote_pathdir.listdir()
158+ try:
159+ return self.remote_pathdir.listdir()
160+ except Exception, e:
161+ self.handle_error(e, 'list', self.remote_pathdir.name)
162
163 def delete(self, filename_list):
164 """Delete all files in filename list"""
165@@ -75,8 +101,8 @@
166 for filename in filename_list:
167 try:
168 self.remote_pathdir.append(filename).delete()
169- except OSError, e:
170- raise BackendException(str(e))
171+ except Exception, e:
172+ self.handle_error(e, 'delete', self.remote_pathdir.append(filename).name)
173
174
175 duplicity.backend.register_backend("file", LocalBackend)
176
177=== modified file 'duplicity/log.py'
178--- duplicity/log.py 2010-11-20 15:39:00 +0000
179+++ duplicity/log.py 2010-12-04 22:17:53 +0000
180@@ -179,6 +179,13 @@
181 restart_file_not_found = 39
182 gio_not_available = 40
183 source_dir_mismatch = 42 # 41 is reserved for par2
184+
185+ # 50->69 reserved for backend errors
186+ backend_error = 50
187+ backend_permission_denied = 51
188+ backend_not_found = 52
189+ backend_no_space = 53
190+
191 # Reserve 255 because it is used as an error code for gksu
192
193 def FatalError(s, code, extra=None):

Subscribers

People subscribed via source and target branches

to all changes: