Skip to content

Commit b91877f

Browse files
justin808claude
andcommitted
refactor: improve lockfile detection robustness
- Reduce File.read size from 1000 to 300 chars for efficiency - Add error handling for corrupted/unreadable lockfiles - Add tests for error scenarios to improve branch coverage - Default to Yarn Classic on read errors Addresses code review feedback. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent e9da837 commit b91877f

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

lib/package_json.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,20 @@ def detect_manager_from_lockfile
116116

117117
def detect_yarn_version_from_lockfile
118118
lockfile_path = "#{directory}/yarn.lock"
119-
return nil unless File.exist?(lockfile_path)
120119

121120
# Read the first few lines to determine the version
122-
# Yarn Berry lockfiles start with "__metadata:" or have "# yarn lockfile v1" but use a different format
123-
# Yarn Classic lockfiles start with "# THIS IS AN AUTOGENERATED FILE" and "# yarn lockfile v1"
124-
content = File.read(lockfile_path, 1000) # Read first 1000 chars
121+
# Yarn Berry lockfiles start with "__metadata:" within the first few lines
122+
# Yarn Classic lockfiles use the older format without __metadata:
123+
content = File.read(lockfile_path, 300) # Read first 300 chars - sufficient to detect __metadata:
125124

126125
# Yarn Berry uses __metadata: at the start
127126
return :yarn_berry if content.include?("__metadata:")
128127

129128
# Default to Yarn Classic for older format
130129
:yarn_classic
130+
rescue StandardError
131+
# On error (e.g., file read failure, corrupted lockfile), default to Yarn Classic
132+
:yarn_classic
131133
end
132134

133135
def determine_yarn_version(version)

spec/package_json_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@
189189
end
190190
end
191191

192+
it "defaults to yarn classic if yarn.lock is unreadable" do
193+
with_package_json_file({ "version" => "1.0.0" }) do
194+
File.write("yarn.lock", "")
195+
allow(File).to receive(:read).and_call_original
196+
allow(File).to receive(:read).with("#{Dir.pwd}/yarn.lock", 300).and_raise(StandardError)
197+
package_json = described_class.read(Dir.pwd, fallback_manager: :npm)
198+
199+
expect(package_json.manager).to be_a PackageJson::Managers::YarnClassicLike
200+
end
201+
end
202+
192203
it "prioritizes bun.lockb over other lockfiles" do
193204
with_package_json_file({ "version" => "1.0.0" }) do
194205
File.write("bun.lockb", "")
@@ -436,6 +447,17 @@
436447
end
437448
end
438449

450+
it "defaults to yarn classic if yarn.lock is unreadable" do
451+
with_package_json_file({ "version" => "1.0.0" }) do
452+
File.write("yarn.lock", "")
453+
allow(File).to receive(:read).and_call_original
454+
allow(File).to receive(:read).with("#{Dir.pwd}/yarn.lock", 300).and_raise(StandardError)
455+
package_json = described_class.new(fallback_manager: :npm)
456+
457+
expect(package_json.manager).to be_a PackageJson::Managers::YarnClassicLike
458+
end
459+
end
460+
439461
it "does not add the packageManager property" do
440462
with_package_json_file({ "version" => "1.0.0" }) do
441463
described_class.new(fallback_manager: :yarn_classic)

0 commit comments

Comments
 (0)