Skip to content

Fix/windows path separator#27

Merged
kenryu42 merged 19 commits into
mainfrom
fix/windows-path-separator
Jan 25, 2026
Merged

Fix/windows path separator#27
kenryu42 merged 19 commits into
mainfrom
fix/windows-path-separator

Conversation

@kenryu42
Copy link
Copy Markdown
Owner

@kenryu42 kenryu42 commented Jan 25, 2026

Summary

This PR improves Windows compatibility by handling Windows-specific path separators and drive letters in the rm -rf safety rules. It also ensures that the current working directory is always resolved to an absolute path for reliable comparison and adds a dedicated Windows CI workflow.

  • Fixed rm -rf rule to support Windows backslashes and case-insensitive path comparisons.
  • Enforced absolute path resolution for cwd in the explain command configuration.
  • Added Windows testing to the CI pipeline.

Changes

  • Core Rule Updates:
    • Implemented normalizePathForComparison in src/core/rules-rm.ts to handle platform differences correctly (backslashes vs. forward slashes, case-sensitivity).
    • Replaced hardcoded path separators with node:path's sep.
    • Updated absolute path detection to recognize Windows drive letters (e.g., C:\).
  • CLI Configuration:
    • Modified src/bin/explain/config.ts to resolve cwd to an absolute path, preventing mismatches when relative paths are provided.
  • CI/CD & Tooling:
    • Added .github/workflows/test-windows.yml to run the test suite on Windows runners.
    • Updated .husky/pre-push to automatically sync and commit dist/ changes before pushing.
  • Tests:
    • Added a new test suite analyzeRm Windows path handling in tests/core/rules-rm.test.ts.
    • Improved tests/bin/explain/cli.test.ts to use platform-agnostic temporary directories.
    • Added toShellPath helper in tests/helpers.ts to handle path escaping in tests.

Testing

bun run check

Manual verification was performed by running the explain command with Windows-style paths and ensuring correct blocking/allowing logic on both mock and real path scenarios.

Related Issue

Fixes #26

PR Checklist

  • I have read the CONTRIBUTING.md
  • Code follows project conventions (type hints, naming, etc.)
  • bun run check passes (lint, types, dead code, rules, tests)
  • Tests added for new rules (minimum 90% coverage required)
  • Tested locally with Claude Code, OpenCode, Gemini CLI or GitHub Copilot CLI
  • Updated documentation if needed (README, AGENTS.md)
  • No version changes in package.json

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows path handling for safer, more consistent behavior across platforms.
  • Tests

    • Added Windows-focused test coverage and made tests platform-aware (temporary dirs and shell-path normalization).
  • Chores

    • Automated distribution file synchronization in pre-push flow.
    • Added a CI workflow to run Windows tests for increased reliability.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 25, 2026

Warning

Rate limit exceeded

@kenryu42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 46 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Introduces cross-platform path normalization for rm-related safety checks, updates tests and test helpers for Windows paths, makes explain cwd resolution absolute, automates dist synchronization in the pre-push hook, and adds a Windows GitHub Actions workflow to run the test suite on windows-latest.

Changes

Cohort / File(s) Summary
Windows CI Workflow
​.github/workflows/test-windows.yml
Adds a "Windows Tests" GitHub Actions workflow (windows-latest) with path-filtered triggers, concurrency, Bun setup, build/test steps, and a PowerShell step that verifies rm -rf dist is ALLOWED within cwd.
Pre-push Hook Automation
.husky/pre-push
Replaces failing abort behavior when dist/ differs with automated staging and a chore: sync dist commit (no-verify), prompting the user to push again.
Explain config cwd resolution
src/bin/explain/config.ts
Resolves cwd to an absolute path via path.resolve to prevent relative-path comparison issues.
Cross-platform rm path handling
src/core/rules-rm.ts
Adds Windows detection and a normalizePathForComparison helper, uses path.sep/normalized comparisons across rm-related checks (isTempTarget, isCwdHomeForRmPolicy, isCwdSelfTarget, isTargetWithinCwd, isHomeDirectory) to fix path-separator mismatches.
Test helpers
tests/helpers.ts
Adds exported toShellPath(p: string) to convert backslashes to forward slashes for safe embedding of paths in shell commands within tests.
Explain CLI tests
tests/bin/explain/cli.test.ts
Replaces hardcoded /tmp with mkdtempSync(join(tmpdir(), ...)) for a platform-aware temp cwd and adds try/finally cleanup (rmSync) to remove the temp dir.
Rm-rule tests (Windows cases)
tests/core/rules-rm.test.ts
Updates tests to use toShellPath(...) and adds Windows-path test cases (absolute and relative with backslashes/forward slashes), with platform gating for relevant cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰
I hopped through paths both slash and back,
I smoothed the trail and fixed the track.
Now rm can romp inside the tree,
Both Windows and POSIX safe for me! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% 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
Title check ✅ Passed The title 'Fix/windows path separator' clearly and concisely describes the main change addressing Windows path separator issues in the rm -rf safety rules.
Description check ✅ Passed The description comprehensively covers all required sections including summary, specific changes, testing instructions, and related issue; all PR checklist items are marked complete.
Linked Issues check ✅ Passed The PR directly addresses all requirements from issue #26: implements cross-platform path normalization, uses node:path.sep, recognizes Windows drive letters, ensures absolute cwd resolution, and adds Windows testing.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the Windows path separator fix: core rule updates, CLI configuration, Windows CI workflow, and platform-aware tests align with issue #26 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 25, 2026

Codecov Report

❌ Patch coverage is 86.66667% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.44%. Comparing base (bb35b3f) to head (620ba5d).
⚠️ Report is 21 commits behind head on main.

Files with missing lines Patch % Lines
src/core/rules-rm.ts 85.36% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #27      +/-   ##
==========================================
- Coverage   99.51%   99.44%   -0.07%     
==========================================
  Files          50       50              
  Lines        4509     4533      +24     
==========================================
+ Hits         4487     4508      +21     
- Misses         22       25       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jan 25, 2026

Greptile Overview

Greptile Summary

This PR improves Windows compatibility for the rm -rf safety rules by handling Windows-specific path separators and drive letters.

Key Changes

  • Core Logic: Added normalizePathForComparison helper function in src/core/rules-rm.ts:14-23 that normalizes paths for platform-specific comparison by converting forward slashes to backslashes and lowercasing on Windows for case-insensitive matching
  • Path Detection: Updated absolute path detection with regex /^[A-Za-z]:[\\/]/ to recognize Windows drive letters like C:\ or C:/ in src/core/rules-rm.ts:267
  • Separator Handling: Replaced hardcoded / separators with path.sep throughout path comparison logic to support both Unix (/) and Windows (\) separators
  • CWD Resolution: Modified buildAnalyzeOptions in src/bin/explain/config.ts:61 to always resolve cwd to an absolute path, preventing comparison failures when relative paths are provided
  • Test Coverage: Added comprehensive Windows path handling tests with platform-specific skipping using test.skipIf(!isWindows) for tests that require actual Windows path normalization
  • CI/CD: Added dedicated Windows testing workflow that runs on windows-latest with PowerShell integration test
  • Developer Experience: Changed pre-push hook from blocking to auto-committing dist/ changes, improving workflow

Technical Review

The implementation correctly handles the main Windows compatibility issues:

  • Case-insensitive path comparisons on Windows
  • Both forward and backward slash separators
  • Windows drive letter detection (e.g., C:\, D:/)
  • Relative path prefixes like .\dist in addition to ./dist

The normalizePathForComparison function is applied consistently across all path comparison operations in isCwdHomeForRmPolicy, isCwdSelfTarget, isTargetWithinCwd, isTempTarget, and isHomeDirectory.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are well-tested with comprehensive test coverage including platform-specific tests, the core logic is sound with proper normalization applied consistently, and the Windows CI workflow validates functionality on actual Windows environments. The absolute path resolution fix prevents edge cases with relative paths, and the auto-generated dist files reflect the source changes correctly.
  • No files require special attention

Important Files Changed

Filename Overview
src/core/rules-rm.ts Added Windows path handling with normalizePathForComparison helper that handles backslashes and case-insensitive comparisons
src/bin/explain/config.ts Added absolute path resolution for cwd to prevent relative path issues in path comparison logic
tests/core/rules-rm.test.ts Added comprehensive Windows path handling tests with platform-specific skipping where needed
.github/workflows/test-windows.yml New Windows CI workflow added to run tests on windows-latest with manual verification test
.husky/pre-push Changed from blocking on dirty dist/ to auto-committing dist/ changes in pre-push hook

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as cc-safety-net CLI
    participant Config as buildAnalyzeOptions
    participant Analyze as analyzeCommand
    participant RmRules as analyzeRm
    participant PathNorm as normalizePathForComparison

    User->>CLI: execute command with --cwd
    CLI->>Config: buildAnalyzeOptions(explainOptions)
    Config->>Config: resolve(cwd) to absolute path
    Note over Config: Prevents relative path issues<br/>in comparison logic
    Config-->>CLI: AnalyzeOptions with absolute cwd
    
    CLI->>Analyze: analyzeCommand(command, options)
    Analyze->>RmRules: analyzeRm(tokens, options)
    
    alt Target is absolute path
        RmRules->>PathNorm: normalizePathForComparison(target)
        Note over PathNorm: On Windows:<br/>1. normalize()<br/>2. Replace / with \<br/>3. toLowerCase()
        PathNorm-->>RmRules: normalized target
        RmRules->>PathNorm: normalizePathForComparison(cwd)
        PathNorm-->>RmRules: normalized cwd
        RmRules->>RmRules: Check if target starts with cwd+sep
        Note over RmRules: Uses platform-specific<br/>separator from path.sep
    else Target is relative
        RmRules->>RmRules: resolve(cwd, target)
        RmRules->>PathNorm: normalizePathForComparison(resolved)
        PathNorm-->>RmRules: normalized resolved path
        RmRules->>PathNorm: normalizePathForComparison(cwd)
        PathNorm-->>RmRules: normalized cwd
        RmRules->>RmRules: Compare normalized paths
    end
    
    RmRules-->>Analyze: null (allowed) or reason (blocked)
    Analyze-->>CLI: analysis result
    CLI-->>User: ALLOWED or BLOCKED with reason
Loading

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.husky/pre-push:
- Around line 9-14: The pre-push hook uses "git add dist/*" which won't stage
deletions or nested files; replace that call with a command that stages all
changes under the dist tree (e.g., "git add --all dist/" or "git add -A dist/")
so deletions and nested paths are included before the "git commit -m 'chore:
sync dist' --no-verify" step; update the script to use that new add command in
place of "git add dist/*".

In `@src/core/rules-rm.ts`:
- Around line 7-23: normalizePathForComparison currently normalizes slashes and
case on Windows but leaves trailing path separators, which can cause false
negatives when other code appends `${sep}` to prefixes (e.g., comparisons
involving cwd/tmpdir). Update normalizePathForComparison to strip trailing
separators after normalization (for both platforms) while preserving root/drive
roots (e.g., "/" or "C:\") so you don't remove the root separator; keep
referencing IS_WINDOWS and normalize(p) and ensure the function returns the
trimmed path for downstream prefix checks.
🧹 Nitpick comments (1)
tests/helpers.ts (1)

83-90: Add @internal tag for the test-only export.

This helper is exported solely for tests; please tag it to satisfy knip conventions.

♻️ Proposed tweak
 /**
+ * `@internal` Exported for testing
  * Convert Windows backslashes to forward slashes for shell command embedding.
  * shell-quote interprets backslashes as escape characters, which corrupts
  * Windows paths like C:\Users\... into C:Users...
  */
 export function toShellPath(p: string): string {
   return p.replace(/\\/g, '/');
 }
As per coding guidelines, add the `@internal` tag for test-only exports.

Comment thread .husky/pre-push Outdated
Comment thread src/core/rules-rm.ts
@kenryu42 kenryu42 merged commit d302eef into main Jan 25, 2026
10 checks passed
@kenryu42 kenryu42 deleted the fix/windows-path-separator branch January 25, 2026 15:01
@coderabbitai coderabbitai Bot mentioned this pull request Mar 12, 2026
6 tasks
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.

Windows: rm -rf within cwd incorrectly blocked due to path separator mismatch

1 participant