Skip to content

Add optional submodule scanning - #160

Merged
andrew merged 5 commits into
mainfrom
feature/include-submodules
Aug 27, 2026
Merged

Add optional submodule scanning#160
andrew merged 5 commits into
mainfrom
feature/include-submodules

Conversation

@andrew

@andrew andrew commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Adds --include-submodules to local scan commands so initialized Git submodules participate in language, tool, manifest, dependency, layout, and line-count detection. Submodules remain excluded by default, and uninitialized worktrees and neighboring skipped directories remain excluded.

Keeps submodule discovery within --scan-depth and --scan-limit.

Closes #158
Closes #152

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds opt-in --include-submodules scanning for initialized Git submodules across local detection workflows.

Changes:

  • Adds bounded recursive submodule discovery.
  • Includes submodule data in detection, manifests, dependencies, layout, and line counts.
  • Updates CLI flags, documentation, and tests.

Review findings:

  • cmd/brief/diff.go — Moderate (3 votes): changed gitlink paths are filtered out after the scan, removing submodule detections.
  • detect/detect.go — Moderate (2 votes): relative roots can cause line counting to include files excluded by the project walk.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Summary
README.md Documents submodule scanning behavior.
detect/submodules.go Discovers submodules and analysis roots.
detect/detect.go Integrates submodules across detection paths and line counts.
detect/detect_test.go Tests scanning, bounds, and counters.
cmd/brief/threat.go Propagates the shared scanning flag.
cmd/brief/main.go Adds the scan flag.
cmd/brief/main_test.go Tests CLI flag behavior.
cmd/brief/enrich.go Adds the enrichment flag.
cmd/brief/diff.go Adds the diff flag and scans changed content.
Suppressed comments (4)

detect/detect.go:781

  • This route override applies equally to names from SkipDirs, so an explicit --skip=vendor or --skip=native is silently ignored when the path leads to an initialized submodule. --include-submodules needs to bypass default exclusions to reach submodules below vendor, but it should not defeat the caller's additional exclusions.
	if skipDir {
		if !route {
			return false
		}
		nextRouteOnly = true

detect/detect.go:173

  • loadSubmodulesFrom records direct submodules even when their path is deeper than ScanDepth (the depth check only guards recursive discovery), so this loop still runs git ls-files over the entire out-of-scope submodule in --tracked --include-submodules mode. A large submodule that the bounded filesystem walk will reject at line 786 can therefore still consume unbounded index output and memory; skip initialized submodules whose pathDepth exceeds the configured depth before loading their indexes.
		submoduleRoot := filepath.Join(abs, submodule.Path)

detect/submodules.go:63

  • loadSubmodules is also called from shouldSkipDirPath during ordinary scans, so this budget is applied even when IncludeSubmodules is false. A .gitmodules with more entries than ScanLimit therefore sets scanTruncated and aborts the default walk before its filesystem-entry limit, changing the documented default behavior and potentially hiding root files. Apply the submodule-entry limit only when inclusion is enabled.
		if e.ScanLimit > 0 && e.submoduleEntries >= e.ScanLimit {
			e.scanTruncated = true
			return

detect/submodules.go:107

  • Presence of .git alone does not prove that the submodule worktree is available: a stale gitdir file can point to a removed path, and an arbitrary .git directory also passes. Include mode will then walk leftover files and report languages/manifests for an unavailable submodule, contrary to the requested missing-content behavior. Validate the worktree with Git before returning true.
	if err != nil || !info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
		return false
	}
	_, err = os.Lstat(filepath.Join(root, ".git"))
	return err == nil

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmd/brief/diff.go
Comment thread detect/detect.go
@andrew
andrew force-pushed the feature/include-submodules branch from dd5d0d0 to c9f2d93 Compare August 27, 2026 14:38
Base automatically changed from fix/bounded-project-scans to main August 27, 2026 14:44
@andrew
andrew force-pushed the feature/include-submodules branch from c9f2d93 to b1907dc Compare August 27, 2026 14:44
@andrew
andrew merged commit a8587d5 into main Aug 27, 2026
8 checks passed
@andrew
andrew deleted the feature/include-submodules branch August 27, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an --include-submodules scan flag Pass --no-gitmodule to scc so lines.by_language matches languages[] on fetched submodules

2 participants