Skip to content

fix: Remove duplicate path segments after symlink resolution (#36)#52

Open
vanmarkic wants to merge 3 commits intojacksteamdev:mainfrom
vanmarkic:claude/fix-issue-36-duplicate-path-01DypPdPvjF9qDyRDG1CAob5
Open

fix: Remove duplicate path segments after symlink resolution (#36)#52
vanmarkic wants to merge 3 commits intojacksteamdev:mainfrom
vanmarkic:claude/fix-issue-36-duplicate-path-01DypPdPvjF9qDyRDG1CAob5

Conversation

@vanmarkic
Copy link
Copy Markdown

Summary

  • Fixes issue where symlink resolution caused duplicate path segments
  • Adds function to detect and remove duplicate consecutive path segments
  • Includes comprehensive test coverage

Changes

  • Implemented removeDuplicatePathSegments function to clean resolved paths
  • Added 114 lines of tests covering various duplicate path scenarios
  • Preserves leading slashes while removing internal duplicates

Related Issue

Fixes bug #36

🤖 Generated with Claude Code

…amdev#36)

The MCP server installation was creating paths with duplicate segments (e.g., /home/user/home/user/vault) when resolving symlinks. This occurred because the symlink resolution process would replace the entire path with the resolved path, potentially including duplicate segments.

This fix adds a removeDuplicatePathSegments function that:
- Detects and removes consecutive duplicate path segment sequences
- Works with both POSIX and Windows paths
- Handles complex cases like /home/user/home/user/vault -> /home/user/vault

The function is applied after all symlink resolution to ensure paths are normalized correctly.

Fixes jacksteamdev#36
…ksteamdev#36)

- Test simple duplicate removal (/home/user/home/user -> /home/user)
- Test multiple consecutive duplicates
- Test complex duplicate patterns
- Test preservation of non-duplicate paths
- Test Windows-style paths with duplicates
- Test iCloud Drive duplicate paths
- Test root directory handling
- Test paths with similar but non-duplicate segments
…dev#36)

- Fix bug where path.join() with empty first element drops leading slash
- Handle special case for root directory (/)
- Handle empty normalized arrays
- Update test function to match implementation
- All tests now pass
@netlify
Copy link
Copy Markdown

netlify bot commented Nov 15, 2025

Deploy Preview for superb-starlight-b5acb5 canceled.

Name Link
🔨 Latest commit b772682
🔍 Latest deploy log https://app.netlify.com/projects/superb-starlight-b5acb5/deploys/6918c1a81f644a000870b9c4

istefox added a commit to istefox/obsidian-mcp-tools that referenced this pull request Apr 11, 2026
…cluster E)

Fix four related path-resolution bugs that combined to make the Linux
and WSL installation paths unusable and list_vault_files crash-prone
on some layouts:

1. POSIX-vs-Win32 absoluteness check order (PR jacksteamdev#75, laplaque)
   `path.win32.isAbsolute("/foo")` returns true because in Win32
   semantics a leading "/" is the root of the current drive. The
   previous code checked Win32 first, so on Linux / macOS / WSL it
   would push `parts[0]` (an empty string) instead of "/", producing
   a relative-looking path that made realpath prepend CWD repeatedly.
   Now checks POSIX first.

2. Duplicate path segments after symlink resolution (PR jacksteamdev#52, vanmarkic)
   On some iCloud Drive / symlinked vault layouts, `fsp.realpath`
   returns paths like `/home/user/home/user/vault` or
   `/Users/me/Library/Mobile Documents/Users/me/Library/Mobile
   Documents/vault`. These doubled paths broke the subsequent
   filesystem checks in getInstallationStatus. Added a new
   `removeDuplicatePathSegments()` helper in a dedicated module
   (`services/pathSegments.ts`) that walks the segment list and
   collapses any run matching the tail of what it has already
   accumulated. resolveSymlinks calls it after every successful
   realpath. Isolated in its own module so the pure logic is
   unit-testable without pulling in Obsidian imports.

3. Linux Claude Desktop config path (PR jacksteamdev#49, vanmarkic, issue jacksteamdev#31)
   Constants said `~/.config/claude/config.json`. Actual Claude
   Desktop Linux install uses `~/.config/Claude/claude_desktop_config.json`
   (capital C, full filename, matching macOS/Windows). Fixed.
   Also split the static path constants into a macro-free module
   (`constants/paths.ts`) so they can be imported from unit tests
   without triggering the `environmentVariables()` bundle-time macro.

4. Double slashes at vault root (PR jacksteamdev#53, vanmarkic)
   `list_vault_files` concatenated `args.directory` directly, so
   callers passing `"Documents/"` produced `/vault/Documents//` which
   Local REST API returns as HTTP 500. Now strips trailing slashes
   before composing the URL.

Adds three new test files:
- services/status.test.ts: 8 tests for removeDuplicatePathSegments
  (simple duplicate, multiple runs, multi-segment prefix, no-dup
  preservation, single-segment, similar-but-distinct, bare root,
  real-world iCloud case).
- constants/constants.test.ts: 12 tests for the platform constants
  (including explicit regression on the Linux capital-C fix).
- features/local-rest-api/pathNormalization.test.ts: 13 tests for
  the trailing-slash stripping logic in list_vault_files (single
  slash, multiple slashes, undefined, nested paths, vault-boundary
  double-slash prevention).

Total: 33 new tests across server + plugin packages. Plugin went from
0 tests to 20.

Refs: jacksteamdev#31, jacksteamdev#36, jacksteamdev#37
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants