2
0
Эх сурвалжийг харах

json output: use text_to_json, fixes #6151

item: path, source, user, group

for non-unicode stuff borg 1.2 had "bpath".

now we have:
path - unicode approximation (invalid stuff replaced by ?)
path_b64 - base64(path_bytes)  # only if needed

source has the same issue as path and is now covered also.

user and group are usually unicode or even pure ASCII,
but we rather are cautious and cover them also.
Thomas Waldmann 2 жил өмнө
parent
commit
e63cfcd708

+ 3 - 2
src/borg/archive.py

@@ -32,7 +32,7 @@ from .helpers import Error, IntegrityError, set_ec
 from .platform import uid2user, user2uid, gid2group, group2gid
 from .helpers import parse_timestamp, archive_ts_now
 from .helpers import OutputTimestamp, format_timedelta, format_file_size, file_status, FileSize
-from .helpers import safe_encode, make_path_safe, remove_surrogates
+from .helpers import safe_encode, make_path_safe, remove_surrogates, text_to_json
 from .helpers import StableDict
 from .helpers import bin_to_hex
 from .helpers import safe_ns
@@ -165,7 +165,8 @@ Bytes sent to remote: {stats.tx_bytes}
             if self.output_json:
                 if not final:
                     data = self.as_dict()
-                    data["path"] = remove_surrogates(item.path if item else "")
+                    if item:
+                        data.update(text_to_json("path", item.path))
                 else:
                     data = {}
                 data.update({"time": time.time(), "type": "archive_progress", "finished": final})

+ 4 - 5
src/borg/archiver/__init__.py

@@ -26,7 +26,7 @@ try:
     from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE
     from ..helpers import Error, set_ec
     from ..helpers import format_file_size
-    from ..helpers import remove_surrogates
+    from ..helpers import remove_surrogates, text_to_json
     from ..helpers import DatetimeWrapper, replace_placeholders
     from ..helpers import check_python, check_extension_modules
     from ..helpers import is_slow_msgpack, is_supported_msgpack, sysinfo
@@ -139,10 +139,9 @@ class Archiver(
         # if we get called with status == None, the final file status was already printed
         if self.output_list and status is not None and (self.output_filter is None or status in self.output_filter):
             if self.log_json:
-                print(
-                    json.dumps({"type": "file_status", "status": status, "path": remove_surrogates(path)}),
-                    file=sys.stderr,
-                )
+                json_data = {"type": "file_status", "status": status}
+                json_data.update(text_to_json("path", path))
+                print(json.dumps(json_data), file=sys.stderr)
             else:
                 logging.getLogger("borg.output.list").info("%1s %s", status, remove_surrogates(path))
 

+ 14 - 13
src/borg/helpers/parseformat.py

@@ -876,31 +876,32 @@ class ItemFormatter(BaseFormatter):
     def get_item_data(self, item):
         item_data = {}
         item_data.update(self.item_data)
-        mode = stat.filemode(item.mode)
-        item_type = mode[0]
 
+        item_data.update(text_to_json("path", item.path))
         source = item.get("source", "")
-        extra = ""
-        if source:
-            source = remove_surrogates(source)
-            extra = " -> %s" % source
+        item_data.update(text_to_json("source", source))
+        item_data.update(text_to_json("linktarget", source))
+        if not self.json_lines:
+            item_data["extra"] = "" if not source else f" -> {item_data['source']}"
+
         hlid = item.get("hlid")
         hlid = bin_to_hex(hlid) if hlid else ""
+        item_data["hlid"] = hlid
+
+        mode = stat.filemode(item.mode)
+        item_type = mode[0]
         item_data["type"] = item_type
         item_data["mode"] = mode
-        item_data["user"] = item.get("user", str(item.uid))
-        item_data["group"] = item.get("group", str(item.gid))
+
+        item_data.update(text_to_json("user", item.get("user", str(item.uid))))
+        item_data.update(text_to_json("group", item.get("group", str(item.gid))))
         item_data["uid"] = item.uid
         item_data["gid"] = item.gid
-        item_data["path"] = remove_surrogates(item.path)
+
         if self.json_lines:
             item_data["healthy"] = "chunks_healthy" not in item
         else:
-            item_data["extra"] = extra
             item_data["health"] = "broken" if "chunks_healthy" in item else "healthy"
-        item_data["source"] = source
-        item_data["linktarget"] = source
-        item_data["hlid"] = hlid
         item_data["flags"] = item.get("bsdflags")  # int if flags known, else (if flags unknown) None
         for key in self.used_call_keys:
             item_data[key] = self.call_keys[key](item)