Package duplicity :: Package backends :: Module localbackend
[hide private]
[frames] | no frames]

Source Code for Module duplicity.backends.localbackend

  1  # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- 
  2  # 
  3  # Copyright 2002 Ben Escoto <ben@emerose.org> 
  4  # Copyright 2007 Kenneth Loafman <kenneth@loafman.com> 
  5  # 
  6  # This file is part of duplicity. 
  7  # 
  8  # Duplicity is free software; you can redistribute it and/or modify it 
  9  # under the terms of the GNU General Public License as published by the 
 10  # Free Software Foundation; either version 2 of the License, or (at your 
 11  # option) any later version. 
 12  # 
 13  # Duplicity is distributed in the hope that it will be useful, but 
 14  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 16  # General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with duplicity; if not, write to the Free Software Foundation, 
 20  # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 21   
 22  import os 
 23  import types 
 24  import errno 
 25   
 26  import duplicity.backend 
 27  from duplicity import log 
 28  from duplicity import path 
 29  from duplicity import util 
 30  from duplicity.errors import * #@UnusedWildImport 
 31   
 32   
33 -class LocalBackend(duplicity.backend.Backend):
34 """Use this backend when saving to local disk 35 36 Urls look like file://testfiles/output. Relative to root can be 37 gotten with extra slash (file:///usr/local). 38 39 """
40 - def __init__(self, parsed_url):
41 duplicity.backend.Backend.__init__(self, parsed_url) 42 # The URL form "file:MyFile" is not a valid duplicity target. 43 if not parsed_url.path.startswith('//'): 44 raise BackendException("Bad file:// path syntax.") 45 self.remote_pathdir = path.Path(parsed_url.path[2:])
46
47 - def handle_error(self, e, op, file1 = None, file2 = None):
48 code = log.ErrorCode.backend_error 49 if hasattr(e, 'errno'): 50 if e.errno == errno.EACCES: 51 code = log.ErrorCode.backend_permission_denied 52 elif e.errno == errno.ENOENT: 53 code = log.ErrorCode.backend_not_found 54 elif e.errno == errno.ENOSPC: 55 code = log.ErrorCode.backend_no_space 56 extra = ' '.join([util.escape(x) for x in [file1, file2] if x]) 57 extra = ' '.join([op, extra]) 58 if op != 'delete' and op != 'query': 59 log.FatalError(str(e), code, extra) 60 else: 61 log.Warn(str(e), code, extra)
62
63 - def move(self, source_path, remote_filename = None):
64 self.put(source_path, remote_filename, rename_instead = True)
65
66 - def put(self, source_path, remote_filename = None, rename_instead = False):
67 if not remote_filename: 68 remote_filename = source_path.get_filename() 69 target_path = self.remote_pathdir.append(remote_filename) 70 log.Info("Writing %s" % target_path.name) 71 """Try renaming first (if allowed to), copying if doesn't work""" 72 if rename_instead: 73 try: 74 source_path.rename(target_path) 75 except OSError: 76 pass 77 except Exception, e: 78 self.handle_error(e, 'put', source_path.name, target_path.name) 79 else: 80 return 81 try: 82 target_path.writefileobj(source_path.open("rb")) 83 except Exception, e: 84 self.handle_error(e, 'put', source_path.name, target_path.name) 85 86 """If we get here, renaming failed previously""" 87 if rename_instead: 88 """We need to simulate its behaviour""" 89 source_path.delete()
90
91 - def get(self, filename, local_path):
92 """Get file and put in local_path (Path object)""" 93 source_path = self.remote_pathdir.append(filename) 94 try: 95 local_path.writefileobj(source_path.open("rb")) 96 except Exception, e: 97 self.handle_error(e, 'get', source_path.name, local_path.name)
98
99 - def list(self):
100 """List files in that directory""" 101 try: 102 os.makedirs(self.remote_pathdir.base) 103 except Exception: 104 pass 105 try: 106 return self.remote_pathdir.listdir() 107 except Exception, e: 108 self.handle_error(e, 'list', self.remote_pathdir.name)
109
110 - def delete(self, filename_list):
111 """Delete all files in filename list""" 112 assert type(filename_list) is not types.StringType 113 for filename in filename_list: 114 try: 115 self.remote_pathdir.append(filename).delete() 116 except Exception, e: 117 self.handle_error(e, 'delete', self.remote_pathdir.append(filename).name)
118
119 - def _query_file_info(self, filename):
120 """Query attributes on filename""" 121 try: 122 target_file = self.remote_pathdir.append(filename) 123 if not os.path.exists(target_file.name): 124 return {'size': -1} 125 target_file.setdata() 126 size = target_file.getsize() 127 return {'size': size} 128 except Exception, e: 129 self.handle_error(e, 'query', target_file.name) 130 return {'size': None}
131 132 duplicity.backend.register_backend("file", LocalBackend) 133