commit cd2f58e8772c30d47b044e258a58ceed4ec992a6
author: polymath <polymath@localhost>
date: 2026-08-26 12:09
parents: d04929cf
Publish this project itself as the xgit repository. Support path:. mirrors so the site can browse its own source tree.
| M | README.md | +16 | -1 |
| M | config.toml | +6 | -0 |
| M | xgit/fetch.py | +27 | -0 |
diff --git a/README.md b/README.md index 1599d19..7cd72e8 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,22 @@ owner = "polymath" Needs your SSH agent / keys available to the machine running xgit. -### Local path mirrors +### Local filesystem checkout (`path:`) + +Publish this xgit project (or any other checkout on disk): + +```toml +[[repos]] +name = "xgit" +url = "path:." +description = "this project — static git page generator by polymath" +owner = "polymath" +``` + +`path:.` is relative to the directory that contains `config.toml`. +Absolute paths work too: `path:/home/you/code/myapp`. + +### Local seed demos ```toml [[repos]] diff --git a/config.toml b/config.toml index aeb7ada..6274c8e 100644 --- a/config.toml +++ b/config.toml @@ -19,6 +19,12 @@ max_diff_bytes = 1048576 # ── Demo repositories (local, created by ./demo or ./sync) ───────────── +[[repos]] +name = "xgit" +url = "path:." +description = "this project — static git page generator by polymath" +owner = "polymath" + [[repos]] name = "hello" url = "local:hello" diff --git a/xgit/fetch.py b/xgit/fetch.py index 15c0abf..95bb2bb 100644 --- a/xgit/fetch.py +++ b/xgit/fetch.py @@ -18,6 +18,7 @@ def fetch_all(cfg: Config) -> None: def fetch_one(cfg: Config, repo: RepoConfig) -> Path: dest = cfg.repo_path(repo.name) + if repo.url.startswith("local:"): local_name = repo.url.split(":", 1)[1] seed_dir = cfg.root / "data" / "seed" / local_name @@ -34,6 +35,19 @@ def fetch_one(cfg: Config, repo: RepoConfig) -> Path: gitutil.set_description(dest, repo.description) return dest + path_src = _local_git_path(cfg, repo.url) + if path_src is not None: + if not path_src.exists() or not gitutil.is_git_repo(path_src): + raise gitutil.GitError(f"path is not a git repository: {path_src}") + # Never mirror a repo into itself + if path_src.resolve() == dest.resolve(): + raise gitutil.GitError(f"refusing to mirror {path_src} onto itself") + print(f" mirroring {path_src}") + _mirror_from_workdir(path_src, dest) + if repo.description: + gitutil.set_description(dest, repo.description) + return dest + if dest.exists() and gitutil.is_git_repo(dest): gitutil.fetch_all(dest) else: @@ -47,6 +61,19 @@ def fetch_one(cfg: Config, repo: RepoConfig) -> Path: return dest +def _local_git_path(cfg: Config, url: str) -> Path | None: + """Resolve path:. / file:// URLs to a filesystem git checkout.""" + if url.startswith(("local:", "git@", "http://", "https://", "git://", "ssh://")): + return None + if url.startswith("path:"): + raw = url.split(":", 1)[1].strip() or "." + p = Path(raw).expanduser() + return p.resolve() if p.is_absolute() else (cfg.root / p).resolve() + if url.startswith("file://"): + return Path(url[7:]).expanduser().resolve() + return None + + def _mirror_from_workdir(workdir: Path, dest: Path) -> None: """Create/update a bare mirror from a local non-bare repo.""" if dest.exists():