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.
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
"""Resolve configuration paths and Gitea/GitLab wiki clone URLs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ResolveError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
def resolve_src_root(config_or_src: Path) -> Path:
|
||||
"""
|
||||
Accept configuration root (…/crm3-26) or its src/ dump.
|
||||
|
||||
Returns absolute path to the directory that contains Catalogs/, Documents/, …
|
||||
"""
|
||||
path = Path(config_or_src).expanduser().resolve()
|
||||
if not path.exists():
|
||||
raise ResolveError(f"path does not exist: {path}")
|
||||
|
||||
if path.is_file():
|
||||
raise ResolveError(f"expected directory, got file: {path}")
|
||||
|
||||
if _looks_like_src(path):
|
||||
return path
|
||||
|
||||
src = path / "src"
|
||||
if src.is_dir() and _looks_like_src(src):
|
||||
return src.resolve()
|
||||
|
||||
raise ResolveError(
|
||||
f"not a 1C configuration dump: {path} "
|
||||
"(need …/src with Catalogs|Documents|Configuration.xml, or the src itself)"
|
||||
)
|
||||
|
||||
|
||||
def resolve_config_root(config_or_src: Path) -> Path:
|
||||
"""Configuration root (parent of src when applicable)."""
|
||||
src = resolve_src_root(config_or_src)
|
||||
if src.name == "src":
|
||||
return src.parent
|
||||
return src
|
||||
|
||||
|
||||
def _looks_like_src(path: Path) -> bool:
|
||||
if (path / "Configuration.xml").is_file():
|
||||
return True
|
||||
markers = ("Catalogs", "Documents", "DataProcessors", "Reports", "CommonModules")
|
||||
return any((path / name).is_dir() for name in markers)
|
||||
|
||||
|
||||
def git_toplevel(path: Path) -> Path | None:
|
||||
"""Nearest git work tree containing path (submodule or root project)."""
|
||||
path = Path(path).resolve()
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["git", "-C", str(path), "rev-parse", "--show-toplevel"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
except OSError:
|
||||
return None
|
||||
if proc.returncode != 0:
|
||||
return None
|
||||
top = proc.stdout.strip()
|
||||
return Path(top) if top else None
|
||||
|
||||
|
||||
def git_remote_url(path: Path, *, remote: str = "origin") -> str | None:
|
||||
"""Clone URL of `remote` for the git repo that owns path."""
|
||||
top = git_toplevel(path)
|
||||
if top is None:
|
||||
return None
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["git", "-C", str(top), "remote", "get-url", remote],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
except OSError:
|
||||
return None
|
||||
if proc.returncode != 0:
|
||||
return None
|
||||
url = proc.stdout.strip()
|
||||
return url or None
|
||||
|
||||
|
||||
def to_wiki_clone_url(repo_url: str) -> str:
|
||||
"""
|
||||
Map configuration repository URL → wiki git URL.
|
||||
|
||||
Gitea / GitLab: https://host/org/repo.git → https://host/org/repo.wiki.git
|
||||
git@host:org/repo.git → git@host:org/repo.wiki.git
|
||||
"""
|
||||
url = repo_url.strip().rstrip("/")
|
||||
if not url:
|
||||
raise ResolveError("empty repository URL")
|
||||
|
||||
if url.endswith(".wiki.git"):
|
||||
return url
|
||||
|
||||
if url.endswith(".git"):
|
||||
return url[: -len(".git")] + ".wiki.git"
|
||||
|
||||
return url + ".wiki.git"
|
||||
|
||||
|
||||
def resolve_wiki_url(
|
||||
config_or_src: Path,
|
||||
*,
|
||||
wiki_url: str | None = None,
|
||||
remote: str = "origin",
|
||||
) -> str:
|
||||
"""Explicit --wiki-url, or derive from git remote of the configuration repo."""
|
||||
if wiki_url:
|
||||
return to_wiki_clone_url(wiki_url)
|
||||
|
||||
root = resolve_config_root(config_or_src)
|
||||
repo = git_remote_url(root, remote=remote)
|
||||
if not repo:
|
||||
raise ResolveError(
|
||||
f"cannot detect git remote '{remote}' for {root}; "
|
||||
"pass --wiki-url explicitly (…/repo.wiki.git)"
|
||||
)
|
||||
return to_wiki_clone_url(repo)
|
||||
|
||||
|
||||
def slug_for_path(path: Path) -> str:
|
||||
"""Short filesystem-safe slug from config root name."""
|
||||
name = resolve_config_root(path).name
|
||||
slug = re.sub(r"[^\w.\-]+", "-", name, flags=re.UNICODE).strip("-")
|
||||
return slug or "config"
|
||||
Reference in New Issue
Block a user