search/query/impact ignore explicit --repo inside a monorepo (git-root walk overrides it)
Version: code-review-graph 2.3.7 (PyPI)
OS: Windows 11 (amd64), Python 3.14.4
Repo layout tested: llvm-project (single top-level .git, 21 subdirectories used as independently build/registered CRG projects, e.g. llvm/, clang/)
Summary
build, register, daemon add, and status all correctly treat an explicit path as the
project root — even when that path is a subdirectory of a larger git checkout, as long as it
has its own .code-review-graph marker. search, query, and impact do not: they resolve
--repo through find_project_root() → find_repo_root(), which walks up the directory tree
looking only for .git/.svn and ignores .code-review-graph. In a monorepo (one .git at the
top, modules as subdirectories — a very common layout, e.g. llvm-project), this always resolves
to the monorepo root instead of the module you asked for, and the command fails with:
No graph found at <monorepo_root>\.code-review-graph\graph.db. Run `code-review-graph build` first.
even though the graph exists exactly where --repo pointed.
Repro
# llvm-project has a single .git at its root; llvm/ and clang/ are subdirectories.
code-review-graph build --repo "D:\llvm-project\llvm" # succeeds, creates
# D:\llvm-project\llvm\.code-review-graph\graph.db
code-review-graph status --repo "D:\llvm-project\llvm" # OK — respects the path, shows real stats
code-review-graph search "raw_ostream" --repo "D:\llvm-project\llvm"
# -> No graph found at D:\llvm-project\.code-review-graph\graph.db. Run `code-review-graph build` first.
# ^^^^^^^^^^^^^^^^ resolved to the monorepo root, not the --repo path
query and impact fail the same way (they're all wired through the same
_GRAPH_TOOL_COMMANDS branch in cli.py).
Root cause
cli.py, in the _GRAPH_TOOL_COMMANDS dispatch:
requested_root = Path(args.repo).expanduser() if args.repo else None
repo_root = find_project_root(requested_root)
find_project_root() (in incremental.py) passes requested_root into find_repo_root() as the
starting point for an upward walk, not as an already-resolved root:
def find_repo_root(start=None, stop_at=None):
current = start or Path.cwd()
while current != current.parent:
if (current / ".git").exists():
return current
...
current = current.parent
...
So an explicit --repo is only ever used as a starting point to search upward for .git/.svn
— never validated/accepted on its own, and never checked for .code-review-graph. This is
inconsistent with tools/_common.py::_validate_repo_root(), which build/register/status use
and which correctly accepts .git or .svn or .code-review-graph at the exact given
path.
Suggested fix
Make the _GRAPH_TOOL_COMMANDS branch in cli.py use _validate_repo_root() when --repo is
explicitly given, matching build/register/status, and only fall back to the upward
find_project_root() walk when no --repo was passed (cwd auto-detect):
if args.repo:
from .tools._common import _validate_repo_root
repo_root = _validate_repo_root(Path(args.repo).expanduser())
else:
repo_root = find_project_root(None)
I've verified this fix locally against a 21-module build of llvm-project (largest module,
llvm/, ~80K files / 130K nodes / 1.5M edges) — search, query callers_of, and
impact --files all return correct results with --repo pointing at a module subdirectory, with
no behavior change for the no---repo cwd-based auto-detect path. Happy to open a PR with this
change plus a regression test (build two nested fake repos under one .git, assert search --repo <child> doesn't resolve to <parent>) if useful.
Workaround (for anyone hitting this before a fix ships)
Set CRG_REPO_ROOT (highest-precedence override in find_project_root) instead of --repo:
$env:CRG_REPO_ROOT = "D:\llvm-project\llvm"
code-review-graph search "raw_ostream"
search/query/impactignore explicit--repoinside a monorepo (git-root walk overrides it)Version: code-review-graph 2.3.7 (PyPI)
OS: Windows 11 (amd64), Python 3.14.4
Repo layout tested:
llvm-project(single top-level.git, 21 subdirectories used as independentlybuild/registered CRG projects, e.g.llvm/,clang/)Summary
build,register,daemon add, andstatusall correctly treat an explicit path as theproject root — even when that path is a subdirectory of a larger git checkout, as long as it
has its own
.code-review-graphmarker.search,query, andimpactdo not: they resolve--repothroughfind_project_root()→find_repo_root(), which walks up the directory treelooking only for
.git/.svnand ignores.code-review-graph. In a monorepo (one.gitat thetop, modules as subdirectories — a very common layout, e.g.
llvm-project), this always resolvesto the monorepo root instead of the module you asked for, and the command fails with:
even though the graph exists exactly where
--repopointed.Repro
queryandimpactfail the same way (they're all wired through the same_GRAPH_TOOL_COMMANDSbranch incli.py).Root cause
cli.py, in the_GRAPH_TOOL_COMMANDSdispatch:find_project_root()(inincremental.py) passesrequested_rootintofind_repo_root()as thestarting point for an upward walk, not as an already-resolved root:
So an explicit
--repois only ever used as a starting point to search upward for.git/.svn— never validated/accepted on its own, and never checked for
.code-review-graph. This isinconsistent with
tools/_common.py::_validate_repo_root(), whichbuild/register/statususeand which correctly accepts
.gitor.svnor.code-review-graphat the exact givenpath.
Suggested fix
Make the
_GRAPH_TOOL_COMMANDSbranch incli.pyuse_validate_repo_root()when--repoisexplicitly given, matching
build/register/status, and only fall back to the upwardfind_project_root()walk when no--repowas passed (cwd auto-detect):I've verified this fix locally against a 21-module build of
llvm-project(largest module,llvm/, ~80K files / 130K nodes / 1.5M edges) —search,query callers_of, andimpact --filesall return correct results with--repopointing at a module subdirectory, withno behavior change for the no-
--repocwd-based auto-detect path. Happy to open a PR with thischange plus a regression test (build two nested fake repos under one
.git, assertsearch --repo <child>doesn't resolve to<parent>) if useful.Workaround (for anyone hitting this before a fix ships)
Set
CRG_REPO_ROOT(highest-precedence override infind_project_root) instead of--repo: