Files
export_1c_help/export_1c_help.py
T
mihailkudravcev 02a05d34d0 Support any 1C config dump and auto wiki URL from its git remote.
Add info command, -c/--config, derived repo.wiki.git target, and README for submodule/root workflows.
2026-07-23 15:24:59 +03:00

299 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""CLI: export 1C Help (ru.html) to Markdown / Gitea/GitLab wiki."""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
TOOL_ROOT = Path(__file__).resolve().parent
if str(TOOL_ROOT) not in sys.path:
sys.path.insert(0, str(TOOL_ROOT))
from export1c_help import __status__, __version__ # noqa: E402
from export1c_help.config_version import ( # noqa: E402
read_config_name,
read_config_version,
)
from export1c_help.export import export_help # noqa: E402
from export1c_help.resolve import ( # noqa: E402
ResolveError,
git_remote_url,
git_toplevel,
resolve_config_root,
resolve_src_root,
resolve_wiki_url,
slug_for_path,
)
from export1c_help.wiki import WikiPushError, prepare_wiki_clone, push_wiki # noqa: E402
def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(
prog="export_1c_help",
description=(
f"Выгрузка встроенной справки любой конфигурации 1С в Markdown / wiki. "
f"v{__version__} ({__status__})."
),
)
p.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
sub = p.add_subparsers(dest="cmd", required=True)
i = sub.add_parser(
"info",
help="Показать src, версию, git remote и wiki URL для конфигурации",
)
_add_config_path_args(i)
i.add_argument("--remote", default="origin", help="Git remote (по умолчанию origin)")
i.add_argument(
"--wiki-url",
default=None,
help="Явный wiki URL (иначе из remote конфигурации)",
)
i.set_defaults(func=cmd_info)
c = sub.add_parser("convert", help="Конвертация Help → Markdown в каталог")
_add_convert_args(c)
c.set_defaults(func=cmd_convert)
w = sub.add_parser(
"push",
help="convert + push в wiki (явный --wiki-url или wiki репозитория конфигурации)",
)
_add_convert_args(w, require_out=False)
w.add_argument(
"--wiki-url",
default=None,
help=(
"URL wiki-репозитория (…/repo.wiki.git). "
"Если не задан — берётся из git remote конфигурации (…/repo.git → …/repo.wiki.git)"
),
)
w.add_argument(
"--remote",
default="origin",
help="Git remote конфигурации для авто-wiki URL (по умолчанию origin)",
)
w.add_argument(
"--work-dir",
type=Path,
default=None,
help="Локальный clone wiki (по умолчанию: out/wiki_clone-<slug>)",
)
w.add_argument(
"-o",
"--out",
type=Path,
default=None,
help="Промежуточный каталог MD (по умолчанию: out/wiki-md-<slug>)",
)
w.add_argument(
"--keep-unmanaged",
action="store_true",
help="Не удалять чужие .md в wiki перед копированием",
)
w.add_argument("-m", "--message", default=None, help="Сообщение коммита wiki")
w.add_argument("--branch", default="main")
w.add_argument("--dry-run", action="store_true", help="Только convert, без git push")
w.set_defaults(func=cmd_push)
return p
def _add_config_path_args(p: argparse.ArgumentParser) -> argparse._MutuallyExclusiveGroup:
g = p.add_mutually_exclusive_group(required=True)
g.add_argument(
"-c",
"--config",
type=Path,
help="Корень выгрузки конфигурации (каталог с src/) или сам src/",
)
g.add_argument(
"-s",
"--src",
type=Path,
help="Каталог src выгрузки (эквивалент -c …/src)",
)
return g
def _add_convert_args(p: argparse.ArgumentParser, *, require_out: bool = True) -> None:
_add_config_path_args(p)
if require_out:
p.add_argument(
"-o",
"--out",
type=Path,
required=True,
help="Каталог результата (wiki working tree)",
)
p.add_argument(
"--objects-only",
action="store_true",
help="Только справка объектов (без Forms/*/Ext/Help)",
)
p.add_argument(
"--keep-empty",
action="store_true",
help="Не пропускать почти пустые страницы",
)
p.add_argument(
"--clean",
action="store_true",
help="Очистить --out перед записью (кроме .git)",
)
p.add_argument("--source-label", default=None, help="Подпись источника в Home.md")
p.add_argument(
"--prev-manifest",
type=Path,
default=None,
help="Предыдущий manifest.json (жизненный цикл страниц)",
)
p.add_argument(
"--config-version",
default=None,
help="Версия конфигурации (иначе VERSION / Configuration.xml)",
)
def _config_input(args: argparse.Namespace) -> Path:
return args.config if getattr(args, "config", None) else args.src
def _resolve_src(args: argparse.Namespace) -> Path:
return resolve_src_root(_config_input(args))
def _print_stats(stats, dest: Path) -> None:
print(
f"OK: config={stats.config_version} "
f"written={stats.pages_written} "
f"+{stats.created_count}/~{stats.edited_count}/={stats.unchanged_count}/{stats.deleted_count} "
f"skipped_empty={stats.pages_skipped_empty} "
f"total={stats.pages_total} "
f"images={stats.images_copied}{dest}"
)
def cmd_info(args: argparse.Namespace) -> int:
try:
src = _resolve_src(args)
root = resolve_config_root(src)
wiki = resolve_wiki_url(src, wiki_url=args.wiki_url, remote=args.remote)
except ResolveError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
top = git_toplevel(root)
remote_url = git_remote_url(root, remote=args.remote)
print(f"config_root: {root}")
print(f"src: {src}")
print(f"config_name: {read_config_name(src) or ''}")
print(f"config_version: {read_config_version(src)}")
print(f"git_toplevel: {top or ''}")
print(f"git_remote({args.remote}): {remote_url or ''}")
print(f"wiki_url: {wiki}")
print(f"slug: {slug_for_path(src)}")
return 0
def cmd_convert(args: argparse.Namespace) -> int:
try:
src = _resolve_src(args)
except ResolveError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
stats = export_help(
src,
args.out,
include_forms=not args.objects_only,
skip_empty=not args.keep_empty,
clean=args.clean,
source_label=args.source_label or str(src),
prev_manifest_path=args.prev_manifest,
config_version=args.config_version,
)
_print_stats(stats, args.out)
return 0
def cmd_push(args: argparse.Namespace) -> int:
try:
src = _resolve_src(args)
wiki_url = resolve_wiki_url(
src, wiki_url=args.wiki_url, remote=args.remote
)
except ResolveError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
slug = slug_for_path(src)
out = args.out or (TOOL_ROOT / "out" / f"wiki-md-{slug}")
work = args.work_dir or (TOOL_ROOT / "out" / f"wiki_clone-{slug}")
branch = args.branch
print(f"wiki_url: {wiki_url}")
print(f"src: {src}")
try:
prepare_wiki_clone(wiki_url, work, branch=branch)
except WikiPushError as exc:
print(f"wiki prepare failed:\n{exc}", file=sys.stderr)
return 1
prev = args.prev_manifest or (work / "manifest.json")
cfg = args.config_version or read_config_version(src)
stats = export_help(
src,
out,
include_forms=not args.objects_only,
skip_empty=not args.keep_empty,
clean=True,
source_label=args.source_label or str(src),
prev_manifest_path=prev if Path(prev).is_file() else None,
config_version=cfg,
)
print(
f"convert: config={stats.config_version} "
f"written={stats.pages_written} "
f"+{stats.created_count}/~{stats.edited_count}/={stats.unchanged_count}/{stats.deleted_count} "
f"{out}"
)
if args.dry_run:
print("dry-run: push skipped")
return 0
message = args.message or (
f"export_1c_help v{__version__}: sync help cfg {stats.config_version} "
f"({stats.pages_written} pages, +{stats.created_count}/~{stats.edited_count}/{stats.deleted_count})"
)
try:
push_wiki(
out,
wiki_url,
work_dir=work,
message=message,
branch=branch,
keep_unmanaged=args.keep_unmanaged,
already_prepared=True,
)
except WikiPushError as exc:
print(f"push failed:\n{exc}", file=sys.stderr)
return 1
print(f"OK: pushed → {wiki_url}")
return 0
def main(argv: list[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
return args.func(args)
if __name__ == "__main__":
raise SystemExit(main())