From cd4b08544c07357920a0d46820879d341a492581 Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:17:12 +0200 Subject: [PATCH] Output ndjson in migration script --- UPGRADING/v0_16.md | 2 +- resources/scripts/migrate_v016.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/UPGRADING/v0_16.md b/UPGRADING/v0_16.md index ed6c3581..b71fcf5f 100644 --- a/UPGRADING/v0_16.md +++ b/UPGRADING/v0_16.md @@ -267,7 +267,7 @@ $ sudo -u stalwart env \ The migration output will scroll past. When it finishes, the process stays in the foreground, listening on port `8080`. Leave this terminal open. -**6. Apply the exported snapshot.** From a **second terminal** (on the same host or any machine that can reach the server on port `8080`), install the new CLI: instructions at https://stalw.art/docs/management/cli/overview: and run: +**6. Apply the exported snapshot.** From a **second terminal** (on the same host or any machine that can reach the server on port `8080`), install the new CLI (*make sure to install v1.0.2 or later*): instructions at https://stalw.art/docs/management/cli/overview: and run: ```bash $ export STALWART_URL=http://127.0.0.1:8080 diff --git a/resources/scripts/migrate_v016.py b/resources/scripts/migrate_v016.py index 39120759..9ce26851 100644 --- a/resources/scripts/migrate_v016.py +++ b/resources/scripts/migrate_v016.py @@ -9,8 +9,8 @@ Two modes: convert — read those two JSON files and emit: * config.json — plain DataStore object (Stalwart's main config) - * export.json — array of `update`/`create` ops for everything - else, in load order. + * export.json — NDJSON stream of `update`/`create` ops for + everything else, one op per line, in load order. Usage: python migrate_v016.py dump --url https://mail.example.com \ @@ -1595,8 +1595,10 @@ def cmd_convert(args: argparse.Namespace) -> int: ops = build_export_ops(result) with open(args.output, "w", encoding="utf-8") as f: - json.dump(ops, f, indent=2, ensure_ascii=False) - print(f"wrote {args.output} ({len(ops)} ops)", file=sys.stderr) + for op in ops: + f.write(json.dumps(op, ensure_ascii=False)) + f.write("\n") + print(f"wrote {args.output} ({len(ops)} ops, NDJSON)", file=sys.stderr) for op in ops: kind = op["@type"] name = op["object"] @@ -1635,7 +1637,7 @@ def build_parser() -> argparse.ArgumentParser: help="Output file for the DataStore object " "(default: config.json).") c.add_argument("--output", default="export.json", - help="Output file for the operations array " + help="Output NDJSON file with one operation per line " "(default: export.json).") c.set_defaults(func=cmd_convert)