Skip to content

fix: extract hardlinked files that share inodes - #514

Open
dyk1454683243-sudo wants to merge 2 commits into
npm:mainfrom
dyk1454683243-sudo:cursor/fix-hardlink-extract-filter-6425
Open

dyk1454683243-sudo wants to merge 2 commits into
npm:mainfrom
dyk1454683243-sudo:cursor/fix-hardlink-extract-filter-6425

Conversation

@dyk1454683243-sudo

@dyk1454683243-sudo dyk1454683243-sudo commented Sep 20, 2026

Copy link
Copy Markdown

Fixes #285

Cause

FetcherBase extract uses a node-tar filter that skipped every entry whose type matched /Link$/. That matches both SymbolicLink and Link.

node-tar marks a regular file as type Link when nlink > 1 (the first path is written as File; later paths that share the inode are hardlink entries with no file body). Directory installs and tarballStream/extract therefore dropped every hardlinked copy, so the extracted tree depended on whether source files happened to share inodes.

Fix

Skip only SymbolicLink. Keep Link entries (hardlinked regular files) and apply the same file mode / .gitignore handling as File entries. node-tar already strips the package/ prefix from hardlink linkpath when strip: 1, so those entries extract as files in the destination.

Tests

  • Directory fetcher: pack and extract a package whose index.js and dist/index.js share an inode; both files are present with the same content.
  • Existing weird-pkg fixture: index-hardlink.js is now kept (and remains a hardlink to index.js); index-symlink.js remains excluded.

The extract filter skipped every node-tar type ending in Link, so regular
files packed as type Link (nlink > 1) were dropped. Skip only SymbolicLink
and keep hardlink entries so extract does not depend on shared inodes.

Fixes npm#285

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.com>
@dyk1454683243-sudo
dyk1454683243-sudo requested a review from a team as a code owner September 20, 2026 15:40
Keep the directory-fetcher hardlink regression and the existing
weird-pkg extract assertions for Link vs SymbolicLink.

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.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.

[BUG] FetcherBase._tarxOptions removes files with identical inodes

2 participants