Skip to content

Detect indent width in pnpm-lock.yaml and shard.lock parsers - #109

Merged
andrew merged 3 commits into
git-pkgs:mainfrom
abhinavgautam01:lockfile-indent-width
Oct 2, 2026
Merged

andrew merged 3 commits into
git-pkgs:mainfrom
abhinavgautam01:lockfile-indent-width

Conversation

@abhinavgautam01

Copy link
Copy Markdown
Contributor

Fixes #108

Problem

The pnpm-lock.yaml and shard.lock parsers scan line by line and compare indentation literally. extractPnpmPackageKey and extractShardName only accept a key indented by exactly two spaces. The shard.lock parser also matches version: and commit: with four literal spaces. A lockfile reformatted with a different indent width (for example by a YAML formatter) parses to zero dependencies with no error.

Fix

Both parsers now take the indent width from the first indented line inside packages: / shards: and compare against it instead of hard-coded widths:

  • A package or shard key is a line indented by exactly the detected width. Nested keys such as peerDependenciesMeta are still skipped (Bug in parsing pnpm-lock files #32).
  • In shard.lock, version: and commit: are matched at any indent deeper than the shard name.
  • A small core.LeadingSpaces helper is shared by both parsers.

The line scanners stay as they are, so there is no added memory cost on large pnpm lockfiles.

Tests

  • TestPnpmLockIndentWidth parses the legacy, v5, v6 and v9 pnpm fixtures with doubled indentation. It asserts the dependencies (name, version, integrity, scope) match the originals exactly.
  • TestShardLockIndentWidth does the same for testdata/crystal/shard.lock. It asserts all 7 shards with their versions.
  • TestExtractPnpmPackageKey now covers 4-space keys, nested keys at 4-space width and the undetected (zero) indent case.

Before and after, parsing through manifests.Parse with indentation doubled:

file before after
testdata/npm/pnpm-lock.yaml 0 deps 9 deps
testdata/crystal/shard.lock 0 deps 7 deps

go build ./..., go vet ./..., go test -race ./... and golangci-lint run all pass.

@andrew andrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Both parsers derive indentation from comment-only lines. Adding a four-space-indented # Dependencies immediately after packages: or shards: makes the existing two-space fixtures return zero dependencies. I reproduced this through manifests.Parse and verified that the YAML values are unchanged: pnpm dependencies fall from 9 to 0, and shards from 7 to 0. The same test passes on main.

Please skip comment-only lines before detecting indentation in both parsers and add regression tests through manifests.Parse.

@abhinavgautam01

Copy link
Copy Markdown
Contributor Author

Thanks.
Both parsers now skip comment-only lines inside packages: / shards:, so comments no longer set the indent width. This also stops a top-level comment from ending the pnpm packages: section early and a comment like # pinned: from being read as a shard name.

I added TestLockfileIndentIgnoresComments, which goes through manifests.Parse for both fixtures. It inserts a comment after the section header that is deeper than the entries, at the entry indent ending in a colon, at column zero, and shallower than the entries in a doubled-indent file. Each case must match the original dependencies (9 for pnpm, 7 for shards).

@andrew andrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comment-indentation issue is fixed in both parsers, with regression coverage through manifests.Parse.

@andrew
andrew merged commit 18719e2 into git-pkgs:main Oct 2, 2026
2 checks passed
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.

pnpm-lock.yaml and shard.lock parse to zero dependencies unless indentation is exactly two spaces

2 participants