From 6b65e831a34f06bb9da663329af0185f3782f21d Mon Sep 17 00:00:00 2001 From: Eric Torres Date: Wed, 17 Apr 2019 10:01:55 -0700 Subject: [PATCH] Rename _gen_metadata and cleanup code --- rbackup/struct/hierarchy.py | 27 ++++++++++++++++++++++----- rbackup/struct/repository.py | 29 +++++++++++++++-------------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/rbackup/struct/hierarchy.py b/rbackup/struct/hierarchy.py index 8ca9e01..531b1d2 100644 --- a/rbackup/struct/hierarchy.py +++ b/rbackup/struct/hierarchy.py @@ -13,6 +13,9 @@ syslog = logging.getLogger(__name__) # ========== Constants ========== +DIRMODE = 0o755 +FILEMODE = 0o644 + METADATA_READ = "r" METADATA_WRITE = "w" @@ -53,6 +56,13 @@ class Hierarchy(PathLike): """Return a string representation of this Hierarchy.""" return str(self._path) + def _gen_metadata(self): + """Generate metadata for this repository. + + After this method is called, the data necessary for this hierarchy has been created. + """ + raise NotImplementedError("This method must be called in a child class.") + @property def path(self): """ @@ -77,12 +87,19 @@ class Hierarchy(PathLike): """ return self._metadata_path - def gen_metadata(self): - """Generate metadata for this repository. + def cleanup(self, **kwargs): + """Clean up this Hierarchy's data from the filesystem.""" + import shutil - After this method is called, the data necessary for this hierarchy has been created. - """ - raise NotImplementedError("This method must be called in a child class.") + syslog.info(f"Performing cleanup on {self._path}") + + # We don't want to risk symlink attacks + # noinspection PyUnresolvedReferences + if not shutil.rmtree.avoids_symlink_attacks: + syslog.error( + "shutil cannot avoid symlink attacks on this platform. Ignoring." + ) + return def read_metadata(self): """Read this repository's metadata from its file and diff --git a/rbackup/struct/repository.py b/rbackup/struct/repository.py index 8163067..b0fbfd2 100644 --- a/rbackup/struct/repository.py +++ b/rbackup/struct/repository.py @@ -83,10 +83,7 @@ class Repository(Hierarchy): """Default constructor for the Repository class.""" super().__init__(dest) - if self.metadata_path.exists(): - self._snapshot_metadata = self.read_metadata() - else: - self.gen_metadata() + self._gen_metadata() self._snapshots = [ Snapshot(self.snapshot_dir / s) for s in self._snapshot_metadata @@ -142,6 +139,17 @@ class Repository(Hierarchy): """ return bool(re.match(VALID_SNAPSHOT_NAME, name)) + def _gen_metadata(self): + """Generate metadata for this repository. + After this method is called, the data necessary for this repository has been created. + """ + if self.metadata_path.exists(): + self._snapshot_metadata = self.read_metadata() + else: + self._snapshot_metadata = [] + self.metadata_path.touch(mode=FILEMODE) + self.write_metadata(self._snapshot_metadata) + @property def snapshot_dir(self): """ @@ -247,7 +255,9 @@ class Repository(Hierarchy): raise ValueError(f"'{name}' is an invalid name") elif snapshot_name in self: syslog.warning("Snapshot already exists, data will be overwritten.") - existing_snapshot = self._snapshots[self._snapshot_metadata.index(snapshot_name)] + existing_snapshot = self._snapshots[ + self._snapshot_metadata.index(snapshot_name) + ] self.symlink_snapshot(existing_snapshot) return existing_snapshot else: @@ -263,15 +273,6 @@ class Repository(Hierarchy): self.symlink_snapshot(new_snapshot) return new_snapshot - def gen_metadata(self): - """Generate metadata for this repository. - After this method is called, the data necessary for this repository has been created. - """ - self._snapshot_metadata = [] - self.metadata_path.parent.mkdir(mode=DIRMODE, exist_ok=True) - self.metadata_path.touch(mode=FILEMODE) - self.write_metadata(self._snapshot_metadata) - def symlink_snapshot(self, snapshot): """Create a symbolic link in the Repository directory to a snapshot.