Browse Source

Merge pull request #9096 from ThomasWaldmann/fix-9095-1.4

json: include archive keys in JSON lines when requested via --format, fixes #9095
TW 3 days ago
parent
commit
b712d55de9
2 changed files with 27 additions and 2 deletions
  1. 7 2
      src/borg/helpers/parseformat.py
  2. 20 0
      src/borg/testsuite/archiver.py

+ 7 - 2
src/borg/helpers/parseformat.py

@@ -798,13 +798,18 @@ class ItemFormatter(BaseFormatter):
             'archiveid': archive.fpr,
         }
         static_keys.update(self.FIXED_KEYS)
+        self.format = partial_format(format, static_keys)
+        self.format_keys = {f[1] for f in Formatter().parse(format)}
         if self.json_lines:
             self.item_data = {}
+            # Include selected static archive-level keys when requested in format for JSON lines
+            # This aligns JSON output with text output where these placeholders are available.
+            for k in ('archivename', 'archiveid'):
+                if k in self.format_keys:
+                    self.item_data[k] = static_keys[k]
             self.format_item = self.format_item_json
         else:
             self.item_data = static_keys
-        self.format = partial_format(format, static_keys)
-        self.format_keys = {f[1] for f in Formatter().parse(format)}
         self.call_keys = {
             'size': self.calculate_size,
             'csize': self.calculate_csize,

+ 20 - 0
src/borg/testsuite/archiver.py

@@ -2614,6 +2614,26 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         assert file1['path'] == 'input/file1'
         assert file1['sha256'] == 'b2915eb69f260d8d3c25249195f2c8f4f716ea82ec760ae929732c0262442b2b'
 
+    def test_list_json_lines_includes_archive_keys_in_format(self):
+        # Issue #9095: archivename/archiveid should be available in JSON lines when requested via --format
+        self.create_regular_file('file1', size=1024)
+        self.cmd('init', '--encryption=repokey', self.repository_location)
+        archive = self.repository_location + '::test'
+        self.cmd('create', archive, 'input')
+        info_archive = json.loads(self.cmd('info', '--json', archive))
+        assert len(info_archive['archives']) == 1
+        archive_info = info_archive['archives'][0]
+        expected_name = archive_info['name']
+        expected_id = archive_info['id']
+        # request both keys explicitly in format
+        out = self.cmd('list', '--json-lines', '--format={archivename} {archiveid}', archive)
+        rows = [json.loads(s) for s in out.splitlines() if s]
+        # ensure we have at least the directory and the file1 item, pick the last as a file
+        assert len(rows) >= 2
+        row = rows[-1]
+        assert row['archivename'] == expected_name
+        assert row['archiveid'] == expected_id
+
     def test_list_json_args(self):
         self.cmd('init', '--encryption=repokey', self.repository_location)
         if self.FORK_DEFAULT: