summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2015-08-19 19:12:19 +0200
committerLars Wirzenius <liw@liw.fi>2015-08-19 19:58:32 +0200
commit8b39988d0cccff274a7bf7e36448dcc7216c2ea3 (patch)
treeb3dec8118cf8540bdbf804f0cbfcf51f3dadaea4
parent7e462bae7d53f08ed6079c522bbe237bbc1c3cc5 (diff)
downloadobnam-8b39988d0cccff274a7bf7e36448dcc7216c2ea3.tar.gz
Add get_metadata_from_file_keys and use it
-rw-r--r--obnamlib/__init__.py3
-rw-r--r--obnamlib/delegator.py5
-rw-r--r--obnamlib/fmt_ga/client.py57
-rw-r--r--obnamlib/plugins/backup_plugin.py18
-rw-r--r--obnamlib/plugins/fuse_plugin.py33
-rw-r--r--obnamlib/plugins/restore_plugin.py31
-rw-r--r--obnamlib/repo_interface.py65
7 files changed, 91 insertions, 121 deletions
diff --git a/obnamlib/__init__.py b/obnamlib/__init__.py
index 9f2792f7..e4ecfd0e 100644
--- a/obnamlib/__init__.py
+++ b/obnamlib/__init__.py
@@ -168,7 +168,8 @@ from repo_interface import (
REPO_FILE_DEV,
REPO_FILE_INO,
REPO_FILE_MD5,
- REPO_FILE_INTEGER_KEYS)
+ REPO_FILE_INTEGER_KEYS,
+ metadata_file_key_mapping)
from .delegator import RepositoryDelegator, GenerationId
diff --git a/obnamlib/delegator.py b/obnamlib/delegator.py
index e477d706..78eccc98 100644
--- a/obnamlib/delegator.py
+++ b/obnamlib/delegator.py
@@ -220,6 +220,11 @@ class RepositoryDelegator(obnamlib.RepositoryInterface):
client = self._lookup_client_by_generation(generation_id)
return client.remove_file(generation_id.gen_number, filename)
+ def get_metadata_from_file_keys(self, generation_id, filename):
+ client = self._lookup_client_by_generation(generation_id)
+ return client.get_metadata_from_file_keys(
+ generation_id.gen_number, filename)
+
def get_file_key(self, generation_id, filename, key):
if key not in self.get_allowed_file_keys():
raise obnamlib.RepositoryFileKeyNotAllowed(
diff --git a/obnamlib/fmt_ga/client.py b/obnamlib/fmt_ga/client.py
index 95f4ac73..66a71ab5 100644
--- a/obnamlib/fmt_ga/client.py
+++ b/obnamlib/fmt_ga/client.py
@@ -262,6 +262,14 @@ class GAClient(object):
genspec=gen_number,
filename=filename)
+ def get_metadata_from_file_keys(self, gen_number, filename):
+ self._load_data()
+ self._require_file_exists(gen_number, filename)
+
+ generation = self._lookup_generation_by_gen_number(gen_number)
+ metadata_obj = generation.get_file_metadata()
+ return metadata_obj.get_metadata_from_file_keys(filename)
+
def set_file_key(self, gen_number, filename, key, value):
self._load_data()
generation = self._lookup_generation_by_gen_number(gen_number)
@@ -523,27 +531,34 @@ class GAFileMetadata(object):
else:
return None
- def set_file_keys_from_metadata(self, filename, file_metadata):
- mapping = [
- (obnamlib.REPO_FILE_MODE, 'st_mode'),
- (obnamlib.REPO_FILE_MTIME_SEC, 'st_mtime_sec'),
- (obnamlib.REPO_FILE_MTIME_NSEC, 'st_mtime_nsec'),
- (obnamlib.REPO_FILE_ATIME_SEC, 'st_atime_sec'),
- (obnamlib.REPO_FILE_ATIME_NSEC, 'st_atime_nsec'),
- (obnamlib.REPO_FILE_NLINK, 'st_nlink'),
- (obnamlib.REPO_FILE_SIZE, 'st_size'),
- (obnamlib.REPO_FILE_UID, 'st_uid'),
- (obnamlib.REPO_FILE_USERNAME, 'username'),
- (obnamlib.REPO_FILE_GID, 'st_gid'),
- (obnamlib.REPO_FILE_GROUPNAME, 'groupname'),
- (obnamlib.REPO_FILE_SYMLINK_TARGET, 'target'),
- (obnamlib.REPO_FILE_XATTR_BLOB, 'xattr'),
- (obnamlib.REPO_FILE_BLOCKS, 'st_blocks'),
- (obnamlib.REPO_FILE_DEV, 'st_dev'),
- (obnamlib.REPO_FILE_INO, 'st_ino'),
- (obnamlib.REPO_FILE_MD5, 'md5'),
- ]
+ def get_metadata_from_file_keys(self, filename):
+ if filename in self._added_files:
+ return self._make_metadata(
+ lambda key: self._added_files.get_file_key(filename, key))
+ else:
+ dir_obj, dir_path, basename = self._get_dir_obj(filename)
+ # We've already verifed the file exists, so we don't need
+ # to handle the case where dir_obj is None.
+ assert dir_obj is not None
+
+ return self._make_metadata(
+ lambda key: dir_obj.get_file_key(basename, key))
+ def _make_metadata(self, get_value):
+ metadata = obnamlib.Metadata()
+
+ for key, field in obnamlib.metadata_file_key_mapping:
+ value = get_value(key)
+ if value is None:
+ if key in obnamlib.REPO_FILE_INTEGER_KEYS:
+ value = 0
+ else:
+ value = ''
+ setattr(metadata, field, value)
+
+ return metadata
+
+ def set_file_keys_from_metadata(self, filename, file_metadata):
if filename in self._added_files:
self._added_files.set_file_key(
filename, obnamlib.REPO_FILE_MODE, file_metadata.st_mode)
@@ -553,7 +568,7 @@ class GAFileMetadata(object):
if not dir_obj:
return False
- for key, field in mapping:
+ for key, field in obnamlib.metadata_file_key_mapping:
value = getattr(file_metadata, field)
dir_obj.set_file_key(basename, key, value)
diff --git a/obnamlib/plugins/backup_plugin.py b/obnamlib/plugins/backup_plugin.py
index 15dcf21f..09ea3387 100644
--- a/obnamlib/plugins/backup_plugin.py
+++ b/obnamlib/plugins/backup_plugin.py
@@ -808,23 +808,7 @@ class BackupPlugin(obnamlib.ObnamPlugin):
return False
def get_metadata_from_generation(self, gen, pathname):
- return obnamlib.Metadata(
- st_mtime_sec=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_MTIME_SEC),
- st_mtime_nsec=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_MTIME_NSEC),
- st_mode=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_MODE),
- st_nlink=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_NLINK),
- st_size=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_SIZE),
- st_uid=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_UID),
- st_gid=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_GID),
- xattr=self.repo.get_file_key(
- gen, pathname, obnamlib.REPO_FILE_XATTR_BLOB))
+ return self.repo.get_metadata_from_file_keys(gen, pathname)
def add_file_to_generation(self, filename, metadata):
self.repo.add_file(self.new_generation, filename)
diff --git a/obnamlib/plugins/fuse_plugin.py b/obnamlib/plugins/fuse_plugin.py
index 2bf8d0a7..a52b77d6 100644
--- a/obnamlib/plugins/fuse_plugin.py
+++ b/obnamlib/plugins/fuse_plugin.py
@@ -282,8 +282,8 @@ class ObnamFuse(fuse.Fuse):
def get_metadata_in_generation(self, path):
tracing.trace('path=%r', path)
- metadata = self.construct_metadata_object(
- self.obnam.repo, *self.get_gen_path(path))
+ gen, filename = self.get_gen_path(path)
+ metadata = self.obnam.repo.get_metadata_from_file_keys(gen, filename)
# FUSE does not allow negative timestamps, truncate to zero
if metadata.st_atime_sec < 0:
@@ -293,35 +293,6 @@ class ObnamFuse(fuse.Fuse):
return metadata
- def construct_metadata_object(self, repo, gen, filename):
- allowed = set(repo.get_allowed_file_keys())
-
- def K(key):
- if key in allowed:
- return repo.get_file_key(gen, filename, key)
- else:
- return None
-
- return obnamlib.Metadata(
- st_atime_sec=K(obnamlib.REPO_FILE_ATIME_SEC),
- st_atime_nsec=K(obnamlib.REPO_FILE_ATIME_NSEC),
- st_mtime_sec=K(obnamlib.REPO_FILE_MTIME_SEC),
- st_mtime_nsec=K(obnamlib.REPO_FILE_MTIME_NSEC),
- st_blocks=K(obnamlib.REPO_FILE_BLOCKS),
- st_dev=K(obnamlib.REPO_FILE_DEV),
- st_gid=K(obnamlib.REPO_FILE_GID),
- st_ino=K(obnamlib.REPO_FILE_INO),
- st_mode=K(obnamlib.REPO_FILE_MODE),
- st_nlink=K(obnamlib.REPO_FILE_NLINK),
- st_size=K(obnamlib.REPO_FILE_SIZE),
- st_uid=K(obnamlib.REPO_FILE_UID),
- username=K(obnamlib.REPO_FILE_USERNAME),
- groupname=K(obnamlib.REPO_FILE_GROUPNAME),
- target=K(obnamlib.REPO_FILE_SYMLINK_TARGET),
- xattr=K(obnamlib.REPO_FILE_XATTR_BLOB),
- md5=K(obnamlib.REPO_FILE_MD5),
- )
-
def get_stat_in_generation(self, path):
tracing.trace('path=%r', path)
metadata = self.get_metadata_in_generation(path)
diff --git a/obnamlib/plugins/restore_plugin.py b/obnamlib/plugins/restore_plugin.py
index 3f85d74f..71266b62 100644
--- a/obnamlib/plugins/restore_plugin.py
+++ b/obnamlib/plugins/restore_plugin.py
@@ -198,42 +198,13 @@ class RestorePlugin(obnamlib.ObnamPlugin):
self.app.ts['current'] = pathname
self.restore_safely(gen, pathname)
- def construct_metadata_object(self, gen, filename):
- allowed = set(self.repo.get_allowed_file_keys())
-
- def K(key):
- if key in allowed:
- return self.repo.get_file_key(gen, filename, key)
- else:
- return None
-
- return obnamlib.Metadata(
- st_atime_sec=K(obnamlib.REPO_FILE_ATIME_SEC),
- st_atime_nsec=K(obnamlib.REPO_FILE_ATIME_NSEC),
- st_mtime_sec=K(obnamlib.REPO_FILE_MTIME_SEC),
- st_mtime_nsec=K(obnamlib.REPO_FILE_MTIME_NSEC),
- st_blocks=K(obnamlib.REPO_FILE_BLOCKS),
- st_dev=K(obnamlib.REPO_FILE_DEV),
- st_gid=K(obnamlib.REPO_FILE_GID),
- st_ino=K(obnamlib.REPO_FILE_INO),
- st_mode=K(obnamlib.REPO_FILE_MODE),
- st_nlink=K(obnamlib.REPO_FILE_NLINK),
- st_size=K(obnamlib.REPO_FILE_SIZE),
- st_uid=K(obnamlib.REPO_FILE_UID),
- username=K(obnamlib.REPO_FILE_USERNAME),
- groupname=K(obnamlib.REPO_FILE_GROUPNAME),
- target=K(obnamlib.REPO_FILE_SYMLINK_TARGET),
- xattr=K(obnamlib.REPO_FILE_XATTR_BLOB),
- md5=K(obnamlib.REPO_FILE_MD5),
- )
-
def restore_safely(self, gen, pathname):
try:
dirname = os.path.dirname(pathname)
if self.write_ok and not self.fs.exists('./' + dirname):
self.fs.makedirs('./' + dirname)
- metadata = self.construct_metadata_object(gen, pathname)
+ metadata = self.repo.get_metadata_from_file_keys(gen, pathname)
set_metadata = True
if metadata.isdir():
diff --git a/obnamlib/repo_interface.py b/obnamlib/repo_interface.py
index d0d1521a..f51dbc56 100644
--- a/obnamlib/repo_interface.py
+++ b/obnamlib/repo_interface.py
@@ -94,6 +94,28 @@ def repo_key_name(key_value):
WRONG_KEY = -1
+# A mapping between file keys and obnamlib.Metadata object fields.
+metadata_file_key_mapping = [
+ (REPO_FILE_MODE, 'st_mode'),
+ (REPO_FILE_MTIME_SEC, 'st_mtime_sec'),
+ (REPO_FILE_MTIME_NSEC, 'st_mtime_nsec'),
+ (REPO_FILE_ATIME_SEC, 'st_atime_sec'),
+ (REPO_FILE_ATIME_NSEC, 'st_atime_nsec'),
+ (REPO_FILE_NLINK, 'st_nlink'),
+ (REPO_FILE_SIZE, 'st_size'),
+ (REPO_FILE_UID, 'st_uid'),
+ (REPO_FILE_USERNAME, 'username'),
+ (REPO_FILE_GID, 'st_gid'),
+ (REPO_FILE_GROUPNAME, 'groupname'),
+ (REPO_FILE_SYMLINK_TARGET, 'target'),
+ (REPO_FILE_XATTR_BLOB, 'xattr'),
+ (REPO_FILE_BLOCKS, 'st_blocks'),
+ (REPO_FILE_DEV, 'st_dev'),
+ (REPO_FILE_INO, 'st_ino'),
+ (REPO_FILE_MD5, 'md5'),
+]
+
+
class RepositoryClientListLockingFailed(obnamlib.ObnamError):
msg = 'Repository client list could not be locked'
@@ -681,7 +703,28 @@ class RepositoryInterface(object):
'''
raise NotImplementedError()
+ def get_metadata_from_file_keys(self, generation_id, filename):
+ '''Return a Metadata constructed from the file's keys.
+
+ This is equivalent to creating the Metadata object and calling
+ get_file_key for every allowed key and setting the
+ corresponding field in the Metadata object. It may be faster
+ on some repository formats, however.
+
+ '''
+
+ metadata = obnamlib.Metadata()
+
+ allowed = set(self.get_allowed_file_keys())
+ for key, field in obnamlib.metadata_file_key_mapping:
+ if key in allowed:
+ value = self.get_file_key(generation_id, filename, key)
+ setattr(metadata, field, value)
+
+ return metadata
+
def set_file_key(self, generation_id, filename, key, value):
+
'''Set value for a file key.
It is an error to set the value for a file key if the file does
@@ -698,28 +741,8 @@ class RepositoryInterface(object):
'''
- mapping = [
- (REPO_FILE_MODE, 'st_mode'),
- (REPO_FILE_MTIME_SEC, 'st_mtime_sec'),
- (REPO_FILE_MTIME_NSEC, 'st_mtime_nsec'),
- (REPO_FILE_ATIME_SEC, 'st_atime_sec'),
- (REPO_FILE_ATIME_NSEC, 'st_atime_nsec'),
- (REPO_FILE_NLINK, 'st_nlink'),
- (REPO_FILE_SIZE, 'st_size'),
- (REPO_FILE_UID, 'st_uid'),
- (REPO_FILE_USERNAME, 'username'),
- (REPO_FILE_GID, 'st_gid'),
- (REPO_FILE_GROUPNAME, 'groupname'),
- (REPO_FILE_SYMLINK_TARGET, 'target'),
- (REPO_FILE_XATTR_BLOB, 'xattr'),
- (REPO_FILE_BLOCKS, 'st_blocks'),
- (REPO_FILE_DEV, 'st_dev'),
- (REPO_FILE_INO, 'st_ino'),
- (REPO_FILE_MD5, 'md5'),
- ]
-
allowed = set(self.get_allowed_file_keys())
- for key, field in mapping:
+ for key, field in obnamlib.metadata_file_key_mapping:
if key in allowed:
self.set_file_key(
generation_id, filename, key, getattr(metadata, field))