Back to index

obnam  1.1
convert5to6_plugin.py
Go to the documentation of this file.
00001 # Copyright (C) 2012  Lars Wirzenius
00002 #
00003 # This program is free software: you can redistribute it and/or modify
00004 # it under the terms of the GNU General Public License as published by
00005 # the Free Software Foundation, either version 3 of the License, or
00006 # (at your option) any later version.
00007 #
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 #
00013 # You should have received a copy of the GNU General Public License
00014 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 
00017 import logging
00018 import os
00019 import re
00020 import stat
00021 import tracing
00022 import zlib
00023 
00024 import obnamlib
00025 
00026 
00027 class Convert5to6Plugin(obnamlib.ObnamPlugin):
00028 
00029     '''Convert a version 5 repository to version 6, in place.'''
00030 
00031     def enable(self):
00032         self.app.add_subcommand('convert5to6', self.convert, arg_synopsis='')
00033 
00034     def convert(self, args):
00035         self.app.settings.require('repository')
00036 
00037         self.rawfs = self.app.fsf.new(self.app.settings['repository'])
00038         self.convert_format()
00039         self.repo = self.app.open_repository()
00040         self.convert_files()
00041 
00042     def convert_files(self):
00043         funcs = []
00044         if self.app.settings['compress-with'] == 'gzip':
00045             funcs.append(self.gunzip)
00046         if self.app.settings['encrypt-with']:
00047             self.symmetric_keys = {}
00048             funcs.append(self.decrypt)
00049         tracing.trace('funcs=%s' % repr(funcs))
00050 
00051         for filename in self.find_files():
00052             logging.debug('converting file %s' % filename)
00053             data = self.rawfs.cat(filename)
00054             tracing.trace('old data is %d bytes' % len(data))
00055             for func in funcs:
00056                 data = func(filename, data)
00057             tracing.trace('new data is %d bytes' % len(data))
00058             self.repo.fs.overwrite_file(filename, data)
00059 
00060     def find_files(self):
00061         ignored_pat = re.compile(r'^(tmp.*|lock|format|userkeys|key)$')
00062         for filename, st in self.rawfs.scan_tree('.'):
00063             ignored = ignored_pat.match(os.path.basename(filename))
00064             if stat.S_ISREG(st.st_mode) and not ignored:
00065                 assert filename.startswith('./')
00066                 yield filename[2:]
00067 
00068     def get_symmetric_key(self, filename):
00069         toplevel = filename.split('/')[0]
00070         tracing.trace('toplevel=%s' % toplevel)
00071 
00072         if toplevel not in self.symmetric_keys:
00073             encoded = self.rawfs.cat(os.path.join(toplevel, 'key'))
00074             key = obnamlib.decrypt_with_secret_keys(encoded)
00075             self.symmetric_keys[toplevel] = key
00076         return self.symmetric_keys[toplevel]
00077 
00078     def decrypt(self, filename, data):
00079         symmetric_key = self.get_symmetric_key(filename)
00080         return obnamlib.decrypt_symmetric(data, symmetric_key)
00081 
00082     def gunzip(self, filename, data):
00083         return zlib.decompress(data)
00084         
00085     def convert_format(self):
00086         self.rawfs.overwrite_file('metadata/format', '6\n')
00087