diff --git a/gitbatch/cli.py b/gitbatch/cli.py index 8f970b3..434b08e 100644 --- a/gitbatch/cli.py +++ b/gitbatch/cli.py @@ -14,6 +14,7 @@ import git from gitbatch import __version__ from gitbatch.logging import SingleLog from gitbatch.utils import normalize_path, to_bool +from gitbatch.utils.copy import copy_file_with_basic_stats class GitBatch: @@ -135,6 +136,7 @@ class GitBatch: repo["dest"], ignore=shutil.ignore_patterns(".git"), dirs_exist_ok=self.config["ignore_existing"], + copy_function=copy_file_with_basic_stats, ) except FileExistsError: self._file_exist_handler() diff --git a/gitbatch/utils.py b/gitbatch/utils/__init__.py similarity index 97% rename from gitbatch/utils.py rename to gitbatch/utils/__init__.py index 9984e30..117775c 100644 --- a/gitbatch/utils.py +++ b/gitbatch/utils/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 """Global utility methods and classes.""" import os diff --git a/gitbatch/utils/copy.py b/gitbatch/utils/copy.py new file mode 100644 index 0000000..70e65b5 --- /dev/null +++ b/gitbatch/utils/copy.py @@ -0,0 +1,36 @@ +"""Copy file utils.""" + +import shutil +from os import utime +from pathlib import Path + + +def _coerce_to_path(source, dest): + return Path(source).resolve(), Path(dest).resolve() + + +def copy_basic_file_stats(source, dest): + """ + Copy only the m_time and a_time attributes from source to destination. + + Both are expected to exist. The extended attribute copy has sideeffects + with SELinux and files copied from temporary directories and copystat + doesn't allow disabling these copies. + """ + source, dest = _coerce_to_path(source, dest) + src_stat = source.stat() + utime(dest, ns=(src_stat.st_atime_ns, src_stat.st_mtime_ns)) + + +def copy_file_with_basic_stats(source, dest): + """ + Simplified copy2 to copy extended file attributes. + + Only the access time and modified times are copied as + extended attribute copy has sideeffects with SELinux and files + copied from temporary directories. + """ + source, dest = _coerce_to_path(source, dest) + + shutil.copy(source, dest) + copy_basic_file_stats(source, dest)