Preserve user wiki pages on help export push.
Only manifest-managed help pages are updated or removed; add --wipe-unmanaged for a full clean.
This commit is contained in:
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
All notable changes to **export_1c_help** are documented in this file.
|
All notable changes to **export_1c_help** are documented in this file.
|
||||||
|
|
||||||
|
## [0.3.3] - 2026-07-23
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `push` no longer deletes user-written wiki pages; only manifest-managed help pages are updated/removed
|
||||||
|
- Full wipe available explicitly via `--wipe-unmanaged`
|
||||||
|
|
||||||
## [0.3.2] - 2026-07-23
|
## [0.3.2] - 2026-07-23
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -115,7 +115,8 @@ python3 export_1c_help.py push -c /path/to/config --remote upstream
|
|||||||
python3 export_1c_help.py push -c /path/to/config
|
python3 export_1c_help.py push -c /path/to/config
|
||||||
```
|
```
|
||||||
|
|
||||||
**Канон текста** — HTML в конфигурации. Ручные правки wiki сотрутся при следующем `push` (если нет `--keep-unmanaged`).
|
**Канон текста справки** — HTML в конфигурации: страницы, попавшие в `manifest.json`, при `push` перезаписываются.
|
||||||
|
**Пользовательские статьи wiki** (не из выгрузки Help) **сохраняются**. Полная очистка wiki — только с `--wipe-unmanaged`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -155,8 +156,10 @@ python3 export_1c_help.py push -c /path/to/config
|
|||||||
| `--remote` | имя remote для авто-URL (`origin`) |
|
| `--remote` | имя remote для авто-URL (`origin`) |
|
||||||
| `--objects-only` | без справки форм |
|
| `--objects-only` | без справки форм |
|
||||||
| `--dry-run` | без git push |
|
| `--dry-run` | без git push |
|
||||||
|
| `--wipe-unmanaged` | стереть и пользовательские статьи wiki (по умолчанию они сохраняются) |
|
||||||
| `--prev-manifest` | свой предыдущий manifest |
|
| `--prev-manifest` | свой предыдущий manifest |
|
||||||
| `--config-version` | явная версия |
|
| `--config-version` | явная версия |
|
||||||
|
| `-m` / `--message` | сообщение коммита |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+43
-15
@@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Always owned by export_1c_help (not user articles).
|
||||||
|
_MANAGED_FIXED = frozenset({"Home.md", "History.md", "_Sidebar.md", "manifest.json"})
|
||||||
|
_IMAGE_SUFFIXES = frozenset({".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"})
|
||||||
|
|
||||||
|
|
||||||
class WikiPushError(RuntimeError):
|
class WikiPushError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
@@ -32,7 +37,7 @@ def prepare_wiki_clone(
|
|||||||
*,
|
*,
|
||||||
branch: str = "main",
|
branch: str = "main",
|
||||||
) -> Path:
|
) -> Path:
|
||||||
"""Clone or reset wiki working tree; return path to existing manifest.json if any."""
|
"""Clone or reset wiki working tree."""
|
||||||
work_dir = work_dir.resolve()
|
work_dir = work_dir.resolve()
|
||||||
if work_dir.exists() and (work_dir / ".git").exists():
|
if work_dir.exists() and (work_dir / ".git").exists():
|
||||||
_run(["git", "fetch", "origin"], cwd=work_dir)
|
_run(["git", "fetch", "origin"], cwd=work_dir)
|
||||||
@@ -57,6 +62,22 @@ def prepare_wiki_clone(
|
|||||||
return work_dir
|
return work_dir
|
||||||
|
|
||||||
|
|
||||||
|
def managed_filenames_from_manifest(manifest_path: Path) -> set[str]:
|
||||||
|
"""Filenames previously written by export_1c_help."""
|
||||||
|
names = set(_MANAGED_FIXED)
|
||||||
|
if not manifest_path.is_file():
|
||||||
|
return names
|
||||||
|
try:
|
||||||
|
data = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||||
|
except (OSError, json.JSONDecodeError):
|
||||||
|
return names
|
||||||
|
for key in ("pages", "deleted_pages"):
|
||||||
|
for item in data.get(key) or []:
|
||||||
|
if isinstance(item, dict) and item.get("filename"):
|
||||||
|
names.add(str(item["filename"]))
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
def push_wiki(
|
def push_wiki(
|
||||||
content_dir: Path,
|
content_dir: Path,
|
||||||
wiki_url: str,
|
wiki_url: str,
|
||||||
@@ -64,14 +85,14 @@ def push_wiki(
|
|||||||
work_dir: Path,
|
work_dir: Path,
|
||||||
message: str,
|
message: str,
|
||||||
branch: str = "main",
|
branch: str = "main",
|
||||||
keep_unmanaged: bool = False,
|
wipe_unmanaged: bool = False,
|
||||||
already_prepared: bool = False,
|
already_prepared: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Clone/fetch wiki repo into work_dir, replace managed pages, commit, push.
|
Clone/fetch wiki, update only export-managed pages, commit, push.
|
||||||
|
|
||||||
Managed pages = all files from content_dir (md/json/images).
|
User-written wiki pages (not listed in previous manifest.json) are kept
|
||||||
If keep_unmanaged=False, removes other .md/.json/images before copy.
|
unless wipe_unmanaged=True.
|
||||||
"""
|
"""
|
||||||
content_dir = content_dir.resolve()
|
content_dir = content_dir.resolve()
|
||||||
work_dir = work_dir.resolve()
|
work_dir = work_dir.resolve()
|
||||||
@@ -79,20 +100,27 @@ def push_wiki(
|
|||||||
if not already_prepared:
|
if not already_prepared:
|
||||||
prepare_wiki_clone(wiki_url, work_dir, branch=branch)
|
prepare_wiki_clone(wiki_url, work_dir, branch=branch)
|
||||||
|
|
||||||
if not keep_unmanaged:
|
new_files = {
|
||||||
|
p.name
|
||||||
|
for p in content_dir.iterdir()
|
||||||
|
if p.is_file() and p.name != ".git"
|
||||||
|
}
|
||||||
|
prev_managed = managed_filenames_from_manifest(work_dir / "manifest.json")
|
||||||
|
|
||||||
|
if wipe_unmanaged:
|
||||||
for path in work_dir.iterdir():
|
for path in work_dir.iterdir():
|
||||||
if path.name == ".git":
|
if path.name == ".git":
|
||||||
continue
|
continue
|
||||||
if path.is_file() and path.suffix.lower() in {".md", ".json"}:
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
suf = path.suffix.lower()
|
||||||
|
if suf in {".md", ".json"} or suf in _IMAGE_SUFFIXES:
|
||||||
path.unlink()
|
path.unlink()
|
||||||
elif path.is_file() and path.suffix.lower() in {
|
else:
|
||||||
".png",
|
# Drop help pages that disappeared from the configuration export.
|
||||||
".jpg",
|
for name in sorted(prev_managed - new_files):
|
||||||
".jpeg",
|
path = work_dir / name
|
||||||
".gif",
|
if path.is_file():
|
||||||
".bmp",
|
|
||||||
".webp",
|
|
||||||
}:
|
|
||||||
path.unlink()
|
path.unlink()
|
||||||
|
|
||||||
for src in content_dir.iterdir():
|
for src in content_dir.iterdir():
|
||||||
|
|||||||
+10
-2
@@ -89,10 +89,18 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
default=None,
|
default=None,
|
||||||
help="Промежуточный каталог MD (по умолчанию: out/wiki-md-<slug>)",
|
help="Промежуточный каталог MD (по умолчанию: out/wiki-md-<slug>)",
|
||||||
)
|
)
|
||||||
|
w.add_argument(
|
||||||
|
"--wipe-unmanaged",
|
||||||
|
action="store_true",
|
||||||
|
help=(
|
||||||
|
"Удалить из wiki все .md/.json/картинки, не только страницы справки "
|
||||||
|
"(опасно: сотрёт пользовательские статьи)"
|
||||||
|
),
|
||||||
|
)
|
||||||
w.add_argument(
|
w.add_argument(
|
||||||
"--keep-unmanaged",
|
"--keep-unmanaged",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Не удалять чужие .md в wiki перед копированием",
|
help=argparse.SUPPRESS, # legacy no-op: preserving user pages is now default
|
||||||
)
|
)
|
||||||
w.add_argument("-m", "--message", default=None, help="Сообщение коммита wiki")
|
w.add_argument("-m", "--message", default=None, help="Сообщение коммита wiki")
|
||||||
w.add_argument("--branch", default="main")
|
w.add_argument("--branch", default="main")
|
||||||
@@ -278,7 +286,7 @@ def cmd_push(args: argparse.Namespace) -> int:
|
|||||||
work_dir=work,
|
work_dir=work,
|
||||||
message=message,
|
message=message,
|
||||||
branch=branch,
|
branch=branch,
|
||||||
keep_unmanaged=args.keep_unmanaged,
|
wipe_unmanaged=args.wipe_unmanaged,
|
||||||
already_prepared=True,
|
already_prepared=True,
|
||||||
)
|
)
|
||||||
except WikiPushError as exc:
|
except WikiPushError as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user