def test_round_trip_for_None_values(self): metadata = obnamlib.metadata.Metadata() encoded = obnamlib.encode_metadata(metadata) decoded = obnamlib.decode_metadata(encoded) for name in dir(metadata): if name in obnamlib.metadata.metadata_fields: self.assertEqual(getattr(decoded, name), None, 'attribute %s must be None' % name)
def get_metadata(self, gen, filename): '''Return metadata for a file in a generation.''' self.require_open_client() try: encoded = self.client.get_metadata(gen, filename) except KeyError: raise obnamlib.Error('%s does not exist' % filename) return obnamlib.decode_metadata(encoded)
def create(self, filename, encoded_metadata): tracing.trace('filename=%s', filename) file_id = self.set_file_id(filename) gen_id = self.get_generation_id(self.tree) try: old_metadata = self.get_metadata(gen_id, filename) except KeyError: old_metadata = None self.file_count += 1 else: old = obnamlib.decode_metadata(old_metadata) if old.isfile(): self.total_data -= old.st_size or 0 metadata = obnamlib.decode_metadata(encoded_metadata) if metadata.isfile(): self.total_data += metadata.st_size or 0 if encoded_metadata != old_metadata: tracing.trace('new or changed metadata') self.set_metadata(filename, encoded_metadata) # Add to parent's contents, unless already there. parent = os.path.dirname(filename) tracing.trace('parent=%s', parent) if parent != filename: # root dir is its own parent basename = os.path.basename(filename) parent_id = self.set_file_id(parent) key = self.fskey(parent_id, self.DIR_CONTENTS, file_id) # We could just insert, but that would cause unnecessary # churn in the tree if nothing changes. try: self.tree.lookup(key) tracing.trace('was already in parent') # pragma: no cover except KeyError: self.tree.insert(key, basename) tracing.trace('added to parent')
def get_file_key(self, generation_id, filename, key): self._require_existing_file(generation_id, filename) client_name, gen_number = generation_id client = self._open_client(client_name) encoded_metadata = client.get_metadata(gen_number, filename) metadata = obnamlib.decode_metadata(encoded_metadata) if key == obnamlib.REPO_FILE_MTIME: return metadata.st_mtime_sec or 0 elif key == obnamlib.REPO_FILE_TEST_KEY: return metadata.target or '' else: raise obnamlib.RepositoryFileKeyNotAllowed( self.format, client_name, key)
def remove(self, filename): tracing.trace('filename=%s', filename) file_id = self.get_file_id(self.tree, filename) genid = self.get_generation_id(self.tree) self.file_count -= 1 try: encoded_metadata = self.get_metadata(genid, filename) except KeyError: pass else: metadata = obnamlib.decode_metadata(encoded_metadata) if metadata.isfile(): self.total_data -= metadata.st_size or 0 # Remove any children. minkey = self.fskey(file_id, self.DIR_CONTENTS, 0) maxkey = self.fskey(file_id, self.DIR_CONTENTS, obnamlib.MAX_ID) for key, basename in self.tree.lookup_range(minkey, maxkey): self.remove(os.path.join(filename, basename)) # Remove chunk refs. for chunkid in self.get_file_chunks(genid, filename): key = self.chunk_key(chunkid, file_id) self.tree.remove_range(key, key) # Remove this file's metadata. minkey = self.fskey(file_id, 0, 0) maxkey = self.fskey(file_id, self.TYPE_MAX, self.SUBKEY_MAX) self.tree.remove_range(minkey, maxkey) # Remove filename. default_file_id = self.default_file_id(filename) key = self.fskey(default_file_id, self.FILE_NAME, file_id) self.tree.remove_range(key, key) # Also remove from parent's contents. parent = os.path.dirname(filename) if parent != filename: # root dir is its own parent parent_id = self.set_file_id(parent) key = self.fskey(parent_id, self.DIR_CONTENTS, file_id) # The range removal will work even if the key does not exist. self.tree.remove_range(key, key)
def test_round_trip_for_maximum_values(self): unsigned_max = 2**64 - 1 signed_max = 2**63 - 1 metadata = obnamlib.metadata.Metadata( st_mode=unsigned_max, st_mtime_sec=signed_max, st_mtime_nsec=unsigned_max, st_nlink=unsigned_max, st_size=signed_max, st_uid=unsigned_max, st_blocks=signed_max, st_dev=unsigned_max, st_gid=unsigned_max, st_ino=unsigned_max, st_atime_sec=signed_max, st_atime_nsec=unsigned_max) encoded = obnamlib.encode_metadata(metadata) decoded = obnamlib.decode_metadata(encoded) self.equal(metadata, decoded)
def test_round_trip(self): metadata = obnamlib.metadata.Metadata(st_mode=1, st_mtime_sec=2, st_mtime_nsec=12756, st_nlink=3, st_size=4, st_uid=5, st_blocks=6, st_dev=7, st_gid=8, st_ino=9, st_atime_sec=10, st_atime_nsec=123, groupname='group', username='******', target='target', md5='checksum') encoded = obnamlib.encode_metadata(metadata) decoded = obnamlib.decode_metadata(encoded) self.equal(metadata, decoded)
def set_file_key(self, generation_id, filename, key, value): client_name, gen_number = generation_id self._require_client_lock(client_name) self._require_existing_file(generation_id, filename) client = self._open_client(client_name) encoded_metadata = client.get_metadata(gen_number, filename) metadata = obnamlib.decode_metadata(encoded_metadata) if key == obnamlib.REPO_FILE_MTIME: metadata.st_mtime_sec = value elif key == obnamlib.REPO_FILE_TEST_KEY: metadata.target = value else: raise obnamlib.RepositoryFileKeyNotAllowed( self.format, client_name, key) encoded_metadata = obnamlib.encode_metadata(metadata) # FIXME: Only sets in unfinished generation client.set_metadata(filename, encoded_metadata)