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.
This commit is contained in:
Thomas Waldmann 2022-12-29 20:03:46 +01:00
parent 32d430a1b0
commit e63cfcd708
No known key found for this signature in database
GPG Key ID: 243ACFA951F78E01
3 changed files with 21 additions and 20 deletions

View File

@ -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})

View File

@ -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))

View File

@ -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)