From e63cfcd70804be6eb62aa26d2895549bb78408ce Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 29 Dec 2022 20:03:46 +0100 Subject: [PATCH] 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. --- src/borg/archive.py | 5 +++-- src/borg/archiver/__init__.py | 9 ++++----- src/borg/helpers/parseformat.py | 27 ++++++++++++++------------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index 3fb51b141..fc71ab06d 100644 --- a/src/borg/archive.py +++ b/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}) diff --git a/src/borg/archiver/__init__.py b/src/borg/archiver/__init__.py index 1549f2af7..ad74665aa 100644 --- a/src/borg/archiver/__init__.py +++ b/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)) diff --git a/src/borg/helpers/parseformat.py b/src/borg/helpers/parseformat.py index d9f8b22e6..b08626b50 100644 --- a/src/borg/helpers/parseformat.py +++ b/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)