On this page
The primitives both repository conversions share -- neither conversion is here: the shared error type, the filter-repo runners, dangling-entry pruning.
#rlsbl.commands.monorepo.extract
#rlsbl.commands.monorepo.extract
The primitives both repository conversions share.
NEITHER conversion is here any more. Both are reconcilers on the shared observe/preview/apply skeleton and both live beside this module: rlsbl monorepo extract in :mod:rlsbl.commands.monorepo.extract_cmd, and rlsbl monorepo absorb in :mod:rlsbl.commands.monorepo.absorb_cmd.
What stays is what both directions need: the shared error type, the git-filter-repo dependency check, the git and filter-repo runners with the timeouts a whole-history rewrite needs, the clone identity fix, and the dangling-changelog-entry pruning a rewrite leaves behind.
#ExtractError
Error during extract or absorb operations.
#require_filter_repo
def require_filter_repo()Raise if git-filter-repo is not installed.
Checks that the git-filter-repo command is available on PATH. Raises ExtractError with install instructions if missing.
#_run_git
def _run_git(cwd, *args, timeout=GIT_TIMEOUT)Run a git command and return stdout. Raises subprocess.CalledProcessError on failure.
#_run_filter_repo
def _run_filter_repo(cwd, *args)Run git-filter-repo in cwd, wrapping failures in ExtractError.
Raw subprocess.CalledProcessError from a filter-repo run is an opaque stack trace to the caller; wrap it so the extract flow reports a clean, actionable error including filter-repo's own stderr.
#_ensure_git_identity
def _ensure_git_identity(clone_path, source_path)Copy the source repo's committer identity into a fresh clone.
git clone does not carry over the source's local user.name / user.email, so a commit inside the clone can fail with "please tell me who you are" in environments without a global identity. We read the source's effective identity (local or global) and set it locally in the clone. If the source has none configured, the clone inherits whatever global identity exists (unchanged).
#_commit_resolves
def _commit_resolves(repo, commit_hash)Whether commit_hash resolves to an existing commit object in repo.
#_prune_dangling_entries
def _prune_dangling_entries(changes_dir, repo_root)Drop changelog entries whose commits no longer resolve after a rewrite.
Runs AFTER :func:remap_jsonl_hashes has mapped every survivable hash to its post-rewrite SHA. Any commit that still fails to resolve in repo_root was pruned by the filter (or was never mappable):
- An entry with at least one surviving commit is kept, narrowed to just the
resolving hashes (a partial survival, logged).
- An entry whose EVERY commit fails to resolve is DROPPED entirely, with a
loud log line -- never left dangling with a null/stale hash.
Returns {jsonl filename: entries dropped}, naming only the files that LOST entries. A dropped entry changes what the version's generated markdown should say, so the caller regenerates exactly those files' .md; a narrowed entry does not (the markdown carries descriptions, not hashes).