From 80e60b4f6fc3b08590949542db41185da0b6936e Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Mon, 16 Mar 2026 21:18:55 +0100 Subject: [PATCH] info: show cwd at the time of backup creation, fixes #6191 Useful if one archives relative paths. Together with the cwd one can know the full path of the files. --- src/borg/archive.py | 2 ++ src/borg/archiver.py | 1 + src/borg/constants.py | 2 +- src/borg/item.pyx | 1 + src/borg/testsuite/archiver.py | 10 ++++++++++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index ef020948d..ef5de3f0c 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -555,6 +555,7 @@ class Archive: cp = normalize_chunker_params(cp) if cp is not None else '' info.update({ 'command_line': self.metadata.cmdline, + 'cwd': self.metadata.get('cwd', ''), 'hostname': self.metadata.hostname, 'username': self.metadata.username, 'comment': self.metadata.get('comment', ''), @@ -635,6 +636,7 @@ Utilization of max. archive size: {csize_max:.0%} 'username': getuser(), 'time': start.strftime(ISO_FORMAT), 'time_end': end.strftime(ISO_FORMAT), + 'cwd': self.cwd, 'chunker_params': self.chunker_params, } # we always want to create archives with the addtl. metadata (nfiles, etc.), diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 35ea637ef..0470991b7 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -1567,6 +1567,7 @@ class Archiver: Time (end): {end} Duration: {duration} Number of files: {stats[nfiles]} + Working Directory: {cwd} Command line: {command_line} Utilization of maximum supported archive size: {limits[max_archive_size]:.0%} ------------------------------------------------------------------------------ diff --git a/src/borg/constants.py b/src/borg/constants.py index f5fe38630..9fc572fee 100644 --- a/src/borg/constants.py +++ b/src/borg/constants.py @@ -12,7 +12,7 @@ ARCHIVE_KEYS = frozenset(['version', 'name', 'items', 'cmdline', 'hostname', 'us 'comment', 'chunker_params', 'recreate_cmdline', 'recreate_source_id', 'recreate_args', 'recreate_partial_chunks', # used in 1.1.0b1 .. b2 - 'size', 'csize', 'nfiles', 'size_parts', 'csize_parts', 'nfiles_parts', ]) + 'size', 'csize', 'nfiles', 'size_parts', 'csize_parts', 'nfiles_parts', 'cwd', ]) # This is the set of keys that are always present in archives: REQUIRED_ARCHIVE_KEYS = frozenset(['version', 'name', 'items', 'cmdline', 'time', ]) diff --git a/src/borg/item.pyx b/src/borg/item.pyx index df9fa018d..cc03b69d3 100644 --- a/src/borg/item.pyx +++ b/src/borg/item.pyx @@ -390,6 +390,7 @@ class ArchiveItem(PropDict): size_parts = PropDict._make_property('size_parts', int) csize_parts = PropDict._make_property('csize_parts', int) nfiles_parts = PropDict._make_property('nfiles_parts', int) + cwd = PropDict._make_property('cwd', str, 'surrogate-escaped str', encode=safe_encode, decode=safe_decode) class ManifestItem(PropDict): diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index 09d1c1dac..ab7a7a972 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -1710,6 +1710,16 @@ class ArchiverTestCase(ArchiverTestCaseBase): info_repo = json.loads(self.cmd('info', '--json', '--last=1', self.repository_location)) assert info_repo["archives"] == [] + def test_info_working_directory(self): + # create a file in input and create the archive from inside the input directory + self.create_regular_file('file1', size=1) + self.cmd('init', '--encryption=repokey', self.repository_location) + expected_cwd = os.path.abspath('input') + with changedir('input'): + self.cmd('create', self.repository_location + '::test', '.') + info_archive = self.cmd('info', self.repository_location + '::test') + assert f'Working Directory: {expected_cwd}' in info_archive + def test_comment(self): self.create_regular_file('file1', size=1024 * 80) self.cmd('init', '--encryption=repokey', self.repository_location)