Skip to content

Git branch strict#11

Merged
b4prog merged 8 commits into
mainfrom
git-branch-strict
Jun 28, 2026
Merged

Git branch strict#11
b4prog merged 8 commits into
mainfrom
git-branch-strict

Conversation

@b4prog

@b4prog b4prog commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added a strict Git branch mode flag to scope reporting to changed line ranges.
    • Updated complexity and duplicate reporting to use branch-scoped file/line selection.
    • Expanded README and CLI help with installation instructions, clearer usage, and strict-mode examples.
  • Bug Fixes
    • Improved branch-scope behavior so results and verbose output align with the selected Git branch mode.
    • Verbose “files analyzed” output now includes changed line ranges when strict mode is active.
  • Chores
    • Bumped the crate version to 0.7.4.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 338f1ba5-8335-4056-bac6-3c3011e71e79

📥 Commits

Reviewing files that changed from the base of the PR and between 7c69cb7 and 999e1a7.

📒 Files selected for processing (1)
  • src/discovery/git.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/discovery/git.rs

📝 Walkthrough

Walkthrough

Adds a -git-branch-strict CLI flag that restricts duplicate and complexity report results to findings overlapping changed line ranges on the current Git branch. Introduces line-range model types, git diff parsing, report orchestration, renderer updates, and README/version changes.

Changes

git-branch-strict feature

Layer / File(s) Summary
New model types
src/model.rs
Defines LineRange, ChangedFileLines, and AnalyzedFile used across discovery, reporting, and rendering.
Git changed-line discovery
src/discovery/git.rs, src/discovery/mod.rs
Adds changed_lines_against_origin, parses git diff hunks into per-file line ranges, handles quoted paths and untracked files, and re-exports the new API.
CLI flag, validation, and help text
src/cli/mod.rs, src/cli/args.rs, src/cli/help.rs
Adds git_branch_strict to config and parsing, rejects invalid flag combinations, maps the normalized option name, and updates help text/tests.
BranchScope orchestration in report runners
src/lib.rs
Adds branch-scoped file and line filtering for duplicate and complexity reports, with strict changed-line overlap matching and tests.
AnalyzedFile renderer updates
src/report/duplicate_renderer.rs, src/report/complexity_renderer.rs
Switches verbose analyzed-file rendering to AnalyzedFile and appends changed-line ranges when present, with updated tests.
README and version bump
README.md, Cargo.toml
Reworks the README usage/install/development documentation and bumps the crate version to 0.7.4.

Sequence Diagram(s)

sequenceDiagram
  participant changed_lines_against_origin
  participant git diff
  participant git ls-files
  participant ChangedFileLines

  changed_lines_against_origin->>git diff: --unified=0 diff against merge base
  changed_lines_against_origin->>git ls-files: --others --exclude-standard -z
  git diff-->>changed_lines_against_origin: file headers and hunk headers
  changed_lines_against_origin-->>ChangedFileLines: Vec<ChangedFileLines>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • b4prog/CodeM8#3: Both PRs touch the duplicate-report rendering path, changing what duplicate-report output includes/shows in the renderer and tests.
  • b4prog/CodeM8#8: Both PRs modify src/lib.rs branch-mode file selection for duplicate reporting, and this PR extends that flow to strict changed-line scoping.
  • b4prog/CodeM8#10: Both PRs modify the complexity reporting pipeline and its renderer-facing analyzed-file handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding a strict git-branch mode for CodeM8.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch git-branch-strict

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🧹 Nitpick comments (2)
src/report/duplicate_renderer.rs (1)

282-309: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a duplicate-report test for changed-line suffixes.

Lines 288-295 only cover changed_lines: None, so the new format_analyzed_file/format_line_ranges path is untested here. Please add the same (3-17,21)-style assertion that src/report/complexity_renderer.rs now has, so both renderers stay locked to the same output contract.

Suggested test shape
 #[test]
+fn renders_verbose_changed_line_ranges() {
+    let report = DuplicateReport {
+        analyzed_files: 1,
+        analyzed_extensions: vec!["rs".to_string()],
+        analyzed_file_paths: Some(vec![AnalyzedFile {
+            path: PathBuf::from("src/lib.rs"),
+            changed_lines: Some(vec![
+                LineRange { start: 3, end: 17 },
+                LineRange { start: 21, end: 21 },
+            ]),
+        }]),
+        timings: None,
+        duplicate_blocks: Vec::new(),
+    };
+    let output = render_duplicate_report(&report, true);
+    assert!(output.contains("Files analyzed:\n- src/lib.rs (3-17,21)\n"));
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/report/duplicate_renderer.rs` around lines 282 - 309, Add a
duplicate-report test covering the changed_lines suffix formatting in
duplicate_renderer::renders_analyzed_file_list_only_in_verbose_mode. The current
test only exercises AnalyzedFile entries with changed_lines: None, so extend it
to include a case with a populated changed_lines range and assert the rendered
verbose output matches the same line-range suffix contract used in
complexity_renderer’s test (the "(3-17,21)"-style formatting). Use the
format_analyzed_file and format_line_ranges output path as the behavior to
verify, while keeping the existing verbose/quiet assertions intact.
src/lib.rs (1)

98-111: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Short-circuit duplicate scans when the branch scope is empty.

For -git-branch/-git-branch-strict, duplicate_discovery_files(config) returns None, so a clean branch still recursively discovers/processes all files and runs duplicate detection before filtering to zero. Pass an empty file slice when branch_scope.files() is empty.

♻️ Proposed fix
     let branch_scope = changed_branch_scope(config, current_dir)?;
+    let branch_files = branch_scope.files();
+    let discovery_files = if branch_files.is_some_and(|files| files.is_empty()) {
+        branch_files
+    } else {
+        duplicate_discovery_files(config)
+    };
     let (source_files, discovery_duration) = discover_report_files(
         config.verbose,
         current_dir,
         &config.file_extensions,
-        duplicate_discovery_files(config),
+        discovery_files,
     )?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib.rs` around lines 98 - 111, The duplicate scan path still discovers,
processes, and detects duplicates for every file even when the branch scope is
empty, which defeats the intended short-circuit for
-git-branch/-git-branch-strict. Update the flow around changed_branch_scope,
discover_report_files, line::process_source_files, and
report::detect_duplicate_blocks so that when branch_scope.files() is empty you
pass an empty file slice into discovery and skip downstream processing/detection
entirely, letting the later filtering stay empty without doing work.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli/help.rs`:
- Around line 41-44: The `-git-branch-strict` help text in `help.rs` is too
broad for duplicate-mode behavior and should be narrowed. Update the wording so
it clearly distinguishes complexity-mode from duplicate-mode, since `lib.rs`’s
duplicate scanning still processes all files and `git-branch-strict` only limits
overlap/changed-line reporting rather than restricting duplicate discovery to
changed files. Keep the incompatibility note with `-files` and `-git-branch`,
and align the text with the actual behavior exposed by the duplicate-detection
flow in `lib.rs` and the CLI help entry.

In `@src/discovery/git.rs`:
- Around line 210-217: The untracked-file path in changed_lines_against_origin
is decoding file contents too early via count_lines, which can fail on non-UTF-8
artifacts before report filtering. Update the logic around count_lines and
merge_changed_file so untracked files are handled without reading/UTF-8-decoding
content here, or are skipped unless they are already known to be supported text
files. Apply the same fix to the duplicated handling at the other referenced
location so strict-mode can continue past binary/generated files.
- Around line 223-235: Handle quoted `+++` diff headers in `parse_changed_lines`
so `current_path` is set correctly for paths with spaces or quotes. Update the
header parsing branch that currently matches `strip_prefix("+++ b/")` and the
`current_path` lookup used before `parse_hunk_range` to also recognize the
quoted `+++ "b/..."` form, or otherwise disable Git path quoting for these
diffs. Keep the `+++ /dev/null` handling intact and ensure the `missing file`
error is no longer triggered for valid quoted paths.
- Around line 79-116: The changed-line collection in `extend_changed_lines` is
merging ranges from `merge_base..HEAD`, `--cached`, and the unstaged diff
without normalizing them to the same tree state. Update the logic in
`src/discovery/git.rs` so `changed_files` is built from one consistent snapshot
before unioning ranges, using the existing helpers like `extend_changed_lines`
and `extend_untracked_changed_lines` to rebase each hunk to the same coordinate
space.

---

Nitpick comments:
In `@src/lib.rs`:
- Around line 98-111: The duplicate scan path still discovers, processes, and
detects duplicates for every file even when the branch scope is empty, which
defeats the intended short-circuit for -git-branch/-git-branch-strict. Update
the flow around changed_branch_scope, discover_report_files,
line::process_source_files, and report::detect_duplicate_blocks so that when
branch_scope.files() is empty you pass an empty file slice into discovery and
skip downstream processing/detection entirely, letting the later filtering stay
empty without doing work.

In `@src/report/duplicate_renderer.rs`:
- Around line 282-309: Add a duplicate-report test covering the changed_lines
suffix formatting in
duplicate_renderer::renders_analyzed_file_list_only_in_verbose_mode. The current
test only exercises AnalyzedFile entries with changed_lines: None, so extend it
to include a case with a populated changed_lines range and assert the rendered
verbose output matches the same line-range suffix contract used in
complexity_renderer’s test (the "(3-17,21)"-style formatting). Use the
format_analyzed_file and format_line_ranges output path as the behavior to
verify, while keeping the existing verbose/quiet assertions intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 16660b9b-7397-4fbb-bf55-f4de3b33efcf

📥 Commits

Reviewing files that changed from the base of the PR and between cbe4028 and a6f5ac6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • Cargo.toml
  • README.md
  • src/cli/args.rs
  • src/cli/help.rs
  • src/cli/mod.rs
  • src/discovery/git.rs
  • src/discovery/mod.rs
  • src/lib.rs
  • src/model.rs
  • src/report/complexity_renderer.rs
  • src/report/duplicate_renderer.rs
📜 Review details
🔇 Additional comments (12)
Cargo.toml (1)

3-3: LGTM!

README.md (1)

4-11: LGTM!

Also applies to: 22-27, 45-59, 81-94, 103-119, 153-168

src/report/duplicate_renderer.rs (1)

4-11: LGTM!

Also applies to: 63-95, 174-175

src/report/complexity_renderer.rs (1)

4-11: LGTM!

Also applies to: 85-122, 222-259

src/lib.rs (1)

14-40: LGTM!

Also applies to: 112-117, 136-160, 172-212, 277-277, 292-304, 321-435, 752-804, 940-1016

src/model.rs (1)

3-19: LGTM!

src/cli/mod.rs (1)

31-31: LGTM!

src/cli/args.rs (2)

23-24: LGTM!

Also applies to: 67-77, 117-121, 135-143, 282-283


313-313: LGTM!

Also applies to: 361-370, 422-422, 497-516, 526-534

src/cli/help.rs (1)

9-25: LGTM!

Also applies to: 56-78, 105-105, 124-124, 134-162

src/discovery/git.rs (1)

7-7: LGTM!

src/discovery/mod.rs (1)

7-7: LGTM!

Comment thread src/cli/help.rs
Comment thread src/discovery/git.rs
Comment thread src/discovery/git.rs
Comment thread src/discovery/git.rs
@b4prog

b4prog commented Jun 28, 2026

Copy link
Copy Markdown
Owner Author

@CodeRabbit resume

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/discovery/git.rs`:
- Around line 248-321: The quoted git path parsing in
parse_quoted_diff_path/parse_diff_escape/parse_diff_octal_escape is decoding
octal escapes into chars one byte at a time, which corrupts non-ASCII filenames.
Change the implementation to accumulate raw bytes for the escaped path,
interpret simple and octal escapes as bytes, and then decode the full buffer
once with String::from_utf8 so paths like café.txt are preserved correctly. Keep
the existing error handling and locate the fix in the quoted-path parsing
helpers in src/discovery/git.rs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9d48a0be-72f7-44e7-9d64-ec255a89131d

📥 Commits

Reviewing files that changed from the base of the PR and between a6f5ac6 and 7c69cb7.

📒 Files selected for processing (2)
  • src/cli/help.rs
  • src/discovery/git.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/cli/help.rs
📜 Review details
🔇 Additional comments (2)
src/discovery/git.rs (2)

199-246: LGTM!


383-390: LGTM!

Also applies to: 478-485, 561-645

Comment thread src/discovery/git.rs
@b4prog

b4prog commented Jun 28, 2026

Copy link
Copy Markdown
Owner Author

@CodeRabbit resume

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@b4prog b4prog merged commit 163b78c into main Jun 28, 2026
3 checks passed
@b4prog b4prog deleted the git-branch-strict branch June 28, 2026 15:17
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.

1 participant