26
import gio #@UnresolvedImport
27
import glib #@UnresolvedImport
29
29
import duplicity.backend
30
30
from duplicity import log
31
31
from duplicity import globals
32
from duplicity.errors import *
33
from duplicity.util import exception_traceback
32
from duplicity import util
33
from duplicity.errors import * #@UnusedWildImport
34
from duplicity.util import exception_traceback
36
37
# GIO requires a dbus session bus which can start the gvfs daemons
88
89
% str(e), log.ErrorCode.connection_failed)
92
def handle_error(self, e, op, file1=None, file2=None):
93
code = log.ErrorCode.backend_error
94
if isinstance(e, gio.Error):
95
if e.code == gio.ERROR_PERMISSION_DENIED:
96
code = log.ErrorCode.backend_permission_denied
97
elif e.code == gio.ERROR_NOT_FOUND:
98
code = log.ErrorCode.backend_not_found
99
elif e.code == gio.ERROR_NO_SPACE:
100
code = log.ErrorCode.backend_no_space
101
extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
102
extra = ' '.join([op, extra])
103
log.FatalError(str(e), code, extra)
91
105
def copy_progress(self, *args, **kwargs):
94
def copy_file(self, source, target):
108
def copy_file(self, op, source, target):
95
110
for n in range(1, globals.num_retries+1):
96
111
log.Info(_("Writing %s") % target.get_parse_name())
103
118
% (target.get_parse_name(), n, e.__class__.__name__, str(e)))
104
119
log.Debug("Backtrace of previous error: %s"
105
120
% exception_traceback())
106
raise BackendException(_("Could not copy %s to %s") % (source.get_parse_name(),
107
target.get_parse_name()))
122
self.handle_error(exc, op, source.get_parse_name(), target.get_parse_name())
109
124
def put(self, source_path, remote_filename = None):
110
125
"""Copy file to remote"""
112
127
remote_filename = source_path.get_filename()
113
128
source_file = gio.File(path=source_path.name)
114
129
target_file = self.remote_file.get_child_for_display_name(remote_filename)
115
self.copy_file(source_file, target_file)
130
self.copy_file('put', source_file, target_file)
117
132
def get(self, filename, local_path):
118
133
"""Get file and put in local_path (Path object)"""
119
134
source_file = self.remote_file.get_child_for_display_name(filename)
120
135
target_file = gio.File(path=local_path.name)
121
self.copy_file(source_file, target_file)
136
self.copy_file('get', source_file, target_file)
122
137
local_path.setdata()
125
140
"""List files in that directory"""
126
enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
127
gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
142
enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
143
gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
145
self.handle_error(e, 'list', self.remote_file.get_parse_name())
130
148
info = enum.next_file()
133
151
info = enum.next_file()
135
153
except Exception, e:
136
raise BackendException(str(e))
154
self.handle_error(e, 'list')
138
156
def delete(self, filename_list):
139
157
"""Delete all files in filename list"""
142
160
for filename in filename_list:
143
161
self.remote_file.get_child_for_display_name(filename).delete()
144
162
except Exception, e:
145
raise BackendException(str(e))
163
self.handle_error(e, 'delete', self.remote_file.get_child_for_display_name(filename).get_parse_name())