diff --git a/borg/archive.py b/borg/archive.py index da8a0e70a..f69834ce4 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -185,7 +185,7 @@ class IncompatibleFilesystemEncodingError(Error): """Failed to encode filename "{}" into file system encoding "{}". Consider configuring the LANG environment variable.""" def __init__(self, repository, key, manifest, name, cache=None, create=False, - checkpoint_interval=300, numeric_owner=False, progress=False, + checkpoint_interval=300, numeric_owner=False, noatime=False, noctime=False, progress=False, chunker_params=CHUNKER_PARAMS, start=None, end=None): self.cwd = os.getcwd() self.key = key @@ -198,6 +198,8 @@ def __init__(self, repository, key, manifest, name, cache=None, create=False, self.name = name self.checkpoint_interval = checkpoint_interval self.numeric_owner = numeric_owner + self.noatime = noatime + self.noctime = noctime if start is None: start = datetime.utcnow() self.start = start @@ -571,10 +573,15 @@ def stat_attrs(self, st, path): b'mode': st.st_mode, b'uid': st.st_uid, b'user': uid2user(st.st_uid), b'gid': st.st_gid, b'group': gid2group(st.st_gid), - b'atime': int_to_bigint(st.st_atime_ns), - b'ctime': int_to_bigint(st.st_ctime_ns), b'mtime': int_to_bigint(st.st_mtime_ns), } + # borg can work with archives only having mtime (older attic archives do not have + # atime/ctime). it can be useful to omit atime/ctime, if they change without the + # file content changing - e.g. to get better metadata deduplication. + if not self.noatime: + item[b'atime'] = int_to_bigint(st.st_atime_ns) + if not self.noctime: + item[b'ctime'] = int_to_bigint(st.st_ctime_ns) if self.numeric_owner: item[b'user'] = item[b'group'] = None with backup_io(): diff --git a/borg/archiver.py b/borg/archiver.py index ecc44be76..bd3382251 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -281,7 +281,8 @@ def create_inner(archive, cache): with Cache(repository, key, manifest, do_files=args.cache_files, lock_wait=self.lock_wait) as cache: archive = Archive(repository, key, manifest, args.location.archive, cache=cache, create=True, checkpoint_interval=args.checkpoint_interval, - numeric_owner=args.numeric_owner, progress=args.progress, + numeric_owner=args.numeric_owner, noatime=args.noatime, noctime=args.noctime, + progress=args.progress, chunker_params=args.chunker_params, start=t0) create_inner(archive, cache) else: @@ -1301,6 +1302,12 @@ def build_parser(self, args=None, prog=None): subparser.add_argument('--numeric-owner', dest='numeric_owner', action='store_true', default=False, help='only store numeric user and group identifiers') + subparser.add_argument('--noatime', dest='noatime', + action='store_true', default=False, + help='do not store atime into archive') + subparser.add_argument('--noctime', dest='noctime', + action='store_true', default=False, + help='do not store ctime into archive') subparser.add_argument('--timestamp', dest='timestamp', type=timestamp, default=None, metavar='yyyy-mm-ddThh:mm:ss',