diff --git a/spqr/curateipsum/backup.py b/spqr/curateipsum/backup.py index 3a6c48a..de14722 100644 --- a/spqr/curateipsum/backup.py +++ b/spqr/curateipsum/backup.py @@ -9,7 +9,7 @@ import shutil from datetime import datetime from typing import Optional -from spqr.curateipsum.fs import hardlink_dir, rsync +import spqr.curateipsum.fs as fs BACKUP_ENT_FMT = "%y%m%d_%H%M" _lg = logging.getLogger(__name__) @@ -71,13 +71,12 @@ def initiate_backup(sources, backup_dir: pathlib.Path, dry_run=False): cur_backup.name, ) - hardlink_dir(latest_backup, cur_backup) - - # for src in sources: - # src_abs = pathlib.Path(os.path.abspath(src)) - # dst_abs = pathlib.Path(os.path.join(cur_backup, src_abs.name)) - # _lg.info("Backing up directory %s to %s backup", src_abs, cur_backup.name) - # rsync(src_abs, cur_backup) + hl_res = fs.hardlink_dir(latest_backup, cur_backup) + if not hl_res: + _lg.error("Something went wrong during copying data from latest backup," + " removing created %s", cur_backup.name) + shutil.rmtree(cur_backup, ignore_errors=True) + return if dry_run: _lg.info("Dry-run, removing created backup: %s", cur_backup.name) shutil.rmtree(cur_backup, ignore_errors=True) diff --git a/spqr/curateipsum/fs.py b/spqr/curateipsum/fs.py index 49db99d..a4de87a 100644 --- a/spqr/curateipsum/fs.py +++ b/spqr/curateipsum/fs.py @@ -209,7 +209,7 @@ def rsync(src_dir, dst_dir, dry_run=False): copy_direntry(src_entry, dst_path) -def _hardlink_dir_ext(src, dst): +def _hardlink_dir_ext(src, dst) -> bool: """ Make hardlink for a directory using cp -al. Both src and dst should exist. :param src: absolute path to source directory. @@ -222,16 +222,16 @@ def _hardlink_dir_ext(src, dst): cp = "cp" src_content = glob.glob(f"{src}/*") cmd = [cp, "--archive", "--verbose", "--link", *src_content, dst] - _lg.debug("Executing external command: %s", " ".join(cmd)) + _lg.info("Executing external command: %s", " ".join(cmd)) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) with process.stdout: for line in iter(process.stdout.readline, b""): logging.debug("%s: %s", cp, line.decode("utf-8").strip()) exitcode = process.wait() - return exitcode + return not bool(exitcode) -def _recursive_hardlink(src, dst): +def _recursive_hardlink(src, dst) -> bool: """ Do hardlink directory recursively using python only. Both src and dst directories should exist. @@ -261,13 +261,15 @@ def _recursive_hardlink(src, dst): # something that is not a file, symlink or directory raise NotImplementedError(ent.path) + return True -def hardlink_dir(src_dir, dst_dir): + +def hardlink_dir(src_dir, dst_dir) -> bool: """ Make hardlink for a directory with all its content. :param src_dir: path to source directory :param dst_dir: path to target directory - :return: None + :return: boolean result """ _lg.info(f"Recursive hardlinking: {src_dir} -> {dst_dir}") src_abs = os.path.abspath(src_dir) @@ -283,8 +285,5 @@ def hardlink_dir(src_dir, dst_dir): _lg.debug(f"Creating directory: {dst_abs}") os.mkdir(dst_abs) - res = _hardlink_dir_ext(src_abs, dst_abs) - if res: - _lg.error("Something went wrong during hardlink_dir, removing created dest dir: %s", dst_abs) - shutil.rmtree(dst_abs, ignore_errors=True) - return + + return _hardlink_dir_ext(src_abs, dst_abs)