Skip to content

Conversation

dylan-conway
Copy link
Member

What does this PR do?

Fixes #23521

How did you verify your code works?

Added 3 previously failing tests for "bin", "directories.bin", and deduplicating entry in both "bin.directories" and "files"

@robobun
Copy link
Collaborator

robobun commented Oct 13, 2025

Updated 4:28 PM PT - Oct 14th, 2025

@dylan-conway, your commit 090dbc2 has 2 failures in Build #29174 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 23606

That installs a local version of the PR into your bun-23606 executable, so you can run:

bun-23606 --bun

Copy link
Contributor

coderabbitai bot commented Oct 13, 2025

Walkthrough

Refactors pack queue to use PackQueueItem with zero-terminated paths, updates traversal and packing functions to accept bins and PackQueue, and adjusts path handling throughout. Adds tests verifying bin and directories inclusion and deduplication. Updates an internal ban-limit for std.fs.Dir.

Changes

Cohort / File(s) Summary
Pack queue and path handling refactor
src/cli/pack_command.zig
Switches priority queue from stringZ to PackQueueItem with [:0]const u8 path and optional; updates lessThan comparator; converts BinInfo.path to zero-terminated; revises iterateIncludedProjectTree, addEntireTree, iterateProjectTree to accept bins and *PackQueue; updates traversal, archive entry, dry-run accounting, and string ops to z-variants.
Pack tests for bins/directories
test/cli/install/bun-pack.test.ts
Adds tests ensuring bins are included even if not in files, directories from directories are included, and deduplication with files handles bin entries.
Internal ban limits
test/internal/ban-limits.json
Decreases allowed count for std.fs.Dir from 165 to 164.

Suggested reviewers

  • nektro

Pre-merge checks

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR includes an unrelated update to test/internal/ban-limits.json that adjusts the allowed limit for std.fs.Dir, which is not part of the bin inclusion fix described in issue #23521 and appears external to the primary objectives. Consider removing the ban-limits adjustment from this PR and submitting it separately or documenting why the limit change is necessary for the bin packaging implementation.
Description Check ⚠️ Warning The PR description follows the template headings but the “What does this PR do?” section only references the issue number without summarizing the implementation, leaving it too minimal, and the “How did you verify your code works?” section is adequate but also lacks detail on verification steps. Please enhance the “What does this PR do?” section with a brief summary of the actual code changes and testing approach, and consider adding more detail to the verification section about how the tests cover the new behavior.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly describes the primary change by indicating the pack operation fix for including bin entries not listed in files, matching the PR’s intent and following conventional commit style.
Linked Issues Check ✅ Passed The changes in pack_command.zig update the traversal and queue logic to always include files referenced by bin by passing and checking the bins list in tree iteration and archive entry functions, and the added tests validate inclusion and deduplication behaviors, fully addressing the requirements of issue #23521.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c820c2b and 090dbc2.

📒 Files selected for processing (3)
  • src/cli/pack_command.zig (24 hunks)
  • test/cli/install/bun-pack.test.ts (1 hunks)
  • test/internal/ban-limits.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/internal/ban-limits.json
  • test/cli/install/bun-pack.test.ts
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Files:

  • src/cli/pack_command.zig
src/**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

In Zig code, manage memory carefully and use defer for cleanup of allocations/resources

src/**/*.zig: Use the # prefix to declare private fields in Zig structs (e.g., struct { #foo: u32 })
Prefer decl literals when initializing values in Zig (e.g., const decl: Decl = .{ .binding = 0, .value = 0 })
Place @import directives at the bottom of Zig files
Use @import("bun") instead of @import("root").bun

When adding debug logs in Zig, create a scoped logger and log via Bun APIs: const log = bun.Output.scoped(.${SCOPE}, .hidden); then log("...", .{})

Files:

  • src/cli/pack_command.zig
test/cli/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/cli/**/*.{js,ts}: Place CLI command tests (e.g., bun install, bun init) under test/cli/
When testing Bun as a CLI, use spawn with bunExe() and bunEnv from harness, and capture stdout/stderr via pipes

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.{ts,tsx}: Test files must live under test/ and end with .test.ts or .test.tsx
In tests, always use port: 0; do not hardcode ports or roll your own random port
Prefer normalizeBunSnapshot for snapshotting test output instead of asserting raw strings
Do not write tests that assert absence of crashes (e.g., 'no panic' or 'no uncaught exception')
Use Bun’s Jest-compatible runner (import { test, expect } from "bun:test") for tests
Avoid shell commands like find or grep in tests; use Bun’s Glob and built-in tools instead
Prefer running tests via bun bd test and use provided harness utilities (bunEnv, bunExe, tempDir)
Use Bun.spawn with proper stdio handling and await proc.exited in process-spawning tests

Files:

  • test/cli/install/bun-pack.test.ts
test/cli/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place CLI command tests under test/cli/

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}: Use bun:test for files ending with *.test.{ts,js,jsx,tsx,mjs,cjs}
Prefer concurrent tests (test.concurrent/describe.concurrent) over sequential when feasible
Organize tests with describe blocks to group related tests
Use utilities like describe.each, toMatchSnapshot, and lifecycle hooks (beforeAll, beforeEach, afterEach) and track resources for cleanup

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.{ts,tsx,js,jsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

For large/repetitive strings, use Buffer.alloc(count, fill).toString() instead of "A".repeat(count)

Files:

  • test/cli/install/bun-pack.test.ts
🧠 Learnings (5)
📚 Learning: 2025-09-26T01:10:04.233Z
Learnt from: nektro
PR: oven-sh/bun#22781
File: test/internal/ban-limits.json:25-26
Timestamp: 2025-09-26T01:10:04.233Z
Learning: The test/internal/ban-limits.json file contains accurate counts that are validated by tests - if the counts were incorrect, the associated tests would fail, so the values in this file reflect the actual current state of the codebase.

Applied to files:

  • test/internal/ban-limits.json
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/js/bun/**/*.{js,ts} : Place Bun API tests under test/js/bun/, separated by category (e.g., test/js/bun/glob/)

Applied to files:

  • test/cli/install/bun-pack.test.ts
📚 Learning: 2025-10-12T02:22:34.373Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-10-12T02:22:34.373Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun:test` for files ending with `*.test.{ts,js,jsx,tsx,mjs,cjs}`

Applied to files:

  • test/cli/install/bun-pack.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/cli/**/*.{js,ts} : Place CLI command tests (e.g., bun install, bun init) under test/cli/

Applied to files:

  • test/cli/install/bun-pack.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/cli/**/*.{js,ts} : When testing Bun as a CLI, use spawn with bunExe() and bunEnv from harness, and capture stdout/stderr via pipes

Applied to files:

  • test/cli/install/bun-pack.test.ts
🧬 Code graph analysis (1)
test/cli/install/bun-pack.test.ts (2)
test/harness.ts (2)
  • pack (1304-1326)
  • bunEnv (49-64)
src/js/internal-for-testing.ts (1)
  • readTarball (125-125)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Format
🔇 Additional comments (15)
test/internal/ban-limits.json (1)

36-36: LGTM!

The decrease from 165 to 164 aligns with the refactoring in src/cli/pack_command.zig that consolidated file/directory handling by introducing PackQueueItem and reducing direct std.fs.Dir usage.

Based on learnings.

src/cli/pack_command.zig (11)

216-227: LGTM!

The introduction of PackQueueItem with zero-terminated paths and an optional flag provides a clean abstraction for handling both regular files and potentially missing bin entries. The priority queue ordering by path ensures deterministic packing order.


235-243: LGTM!

The signature update to accept bins and the updated PackQueue type is necessary for implementing the bin inclusion logic. The call site at lines 1432-1441 correctly passes the bins parameter.


329-333: LGTM!

The bin deduplication logic correctly skips entries that will be added separately as bins, preventing duplicate entries in the tarball. The checks cover both files and directories, and the use of continue :next_entry cleanly exits the current iteration.

Also applies to: 343-347, 356-362


384-390: LGTM!

The signature update and bin deduplication logic in addEntireTree mirrors the approach in iterateIncludedProjectTree, ensuring consistent behavior across both code paths. The checks for both files and directories prevent bin entries from being duplicated.

Also applies to: 472-485


804-810: LGTM!

The signature update and bin deduplication logic in iterateProjectTree maintains consistency with the other traversal functions. The addition of the root_dir: DirInfo parameter provides better context for directory iteration.

Also applies to: 885-898


966-974: LGTM!

Changing BinInfo.path to a zero-terminated slice ([:0]const u8) ensures consistency with PackQueueItem.path and provides better interoperability with filesystem operations that expect null-terminated strings.


988-988: LGTM!

The use of allocator.dupeZ correctly creates zero-terminated copies of normalized bin paths, ensuring consistency with the updated BinInfo.path type. Memory management appears sound, with cleanup handled by the deferred free at line 1384.

Also applies to: 1003-1003, 1023-1023


1380-1400: LGTM!

The bin initialization logic correctly:

  • Retrieves bins from package.json
  • Marks bin files as optional (line 1389) to gracefully handle missing executables
  • Expands bin directories via iterateProjectTree (line 1397)
  • Ensures bins are always included in the pack regardless of "files" field

This implementation directly addresses the PR objective of fixing issue #23521.


1432-1441: LGTM!

Both code paths correctly pass the bins parameter to the traversal functions, ensuring bin deduplication works regardless of whether the "files" field is present in package.json.

Also applies to: 1447-1456


1647-1685: LGTM!

The optional item handling correctly:

  • Checks the optional flag (line 1651)
  • Decrements total_files when skipping missing optional entries (line 1652)
  • Prevents crashes when bin files don't exist on disk

This ensures graceful degradation for missing bin entries.


1687-1716: LGTM!

The optional item handling for bundled dependencies mirrors the logic for the main pack queue, ensuring consistent behavior across both packing paths.

test/cli/install/bun-pack.test.ts (3)

1284-1314: LGTM!

This test directly validates the PR objective (issue #23521): bins are included in the tarball even when not listed in the "files" field. The test setup is clean, and the expectations correctly verify that both the bin file and the dist directory contents are present.


1316-1351: LGTM!

This test validates that bin directories specified via "directories.bin" are fully traversed and included alongside "files" entries. The inclusion of a nested file (bins/what/what.js) ensures recursive traversal is working correctly.


1353-1388: LGTM!

This test validates the deduplication logic for bin entries that appear in both "directories.bin" and "files". The expectation of exactly 4 unique files (package.json, bins/bin.js, bins/what/what.js, dist/hi.js) confirms that bins/bin.js is not duplicated despite being referenced twice.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

coderabbitai bot commented Oct 13, 2025

Walkthrough

Refactors pack logic to use PackQueueItem in a priority queue, updates comparison to sort by item.path, threads bins and pack_queue through traversal functions with signature and return-type changes, adjusts path handling and dedupe, adds tests for bin inclusion and directories/files interaction, and updates an internal ban-limits value.

Changes

Cohort / File(s) Summary of changes
Pack queue refactor and traversal updates
src/cli/pack_command.zig
Introduced PackQueueItem and changed PackQueue to PriorityQueue(PackQueueItem, ...); updated PackQueueContext.lessThan to compare a.path vs b.path; revised signatures/returns for iterateIncludedProjectTree, addEntireTree, and iterateProjectTree to pass *PackQueue, bins, and DirInfo; switched path handling to item.path; added bin-aware skip checks; set optional flags where applicable.
Tests for bin handling and dedupe
test/cli/install/bun-pack.test.ts
Added test cases validating bin inclusion when not in files, directories mapping with files, and deduplication with overlapping entries; assertions on tarball contents and paths.
Internal limits adjustment
test/internal/ban-limits.json
Decremented ban-limits value for std.fs.Dir from 165 to 164.

Suggested reviewers

  • nektro

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The modification to test/internal/ban-limits.json adjusting the “std.fs.Dir” limit is unrelated to the pack command’s bin inclusion logic and does not serve the objectives of the linked issue. Please remove or isolate the ban-limits.json change into a separate pull request so that this PR remains focused solely on addressing the bin inclusion behavior.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly describes the primary change by indicating that the pack command will always include binaries even when they are not listed in the files field, which matches the core issue being addressed. It is concise, specific, and clearly communicates the fix to anyone scanning the repository history. There is no extraneous information or ambiguity in the phrasing.
Linked Issues Check ✅ Passed The changes directly implement support for including bin entries not listed in the files array by extending the pack queue logic to handle paths and optional flags, and the added tests validate this behavior, thereby fulfilling the objective of issue #23521.
Description Check ✅ Passed The pull request description follows the repository’s template by providing the “What does this PR do?” and “How did you verify your code works?” sections with appropriate details about fixing the linked issue and adding tests. Both required headings are present and contain concise information on the fix and verification steps, making the description complete and clear.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c820c2b and b766963.

📒 Files selected for processing (3)
  • src/cli/pack_command.zig (24 hunks)
  • test/cli/install/bun-pack.test.ts (1 hunks)
  • test/internal/ban-limits.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/internal/ban-limits.json
  • test/cli/install/bun-pack.test.ts
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Files:

  • src/cli/pack_command.zig
src/**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

In Zig code, manage memory carefully and use defer for cleanup of allocations/resources

src/**/*.zig: Use the # prefix to declare private fields in Zig structs (e.g., struct { #foo: u32 })
Prefer decl literals when initializing values in Zig (e.g., const decl: Decl = .{ .binding = 0, .value = 0 })
Place @import directives at the bottom of Zig files
Use @import("bun") instead of @import("root").bun

When adding debug logs in Zig, create a scoped logger and log via Bun APIs: const log = bun.Output.scoped(.${SCOPE}, .hidden); then log("...", .{})

Files:

  • src/cli/pack_command.zig
test/cli/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/cli/**/*.{js,ts}: Place CLI command tests (e.g., bun install, bun init) under test/cli/
When testing Bun as a CLI, use spawn with bunExe() and bunEnv from harness, and capture stdout/stderr via pipes

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.{ts,tsx}: Test files must live under test/ and end with .test.ts or .test.tsx
In tests, always use port: 0; do not hardcode ports or roll your own random port
Prefer normalizeBunSnapshot for snapshotting test output instead of asserting raw strings
Do not write tests that assert absence of crashes (e.g., 'no panic' or 'no uncaught exception')
Use Bun’s Jest-compatible runner (import { test, expect } from "bun:test") for tests
Avoid shell commands like find or grep in tests; use Bun’s Glob and built-in tools instead
Prefer running tests via bun bd test and use provided harness utilities (bunEnv, bunExe, tempDir)
Use Bun.spawn with proper stdio handling and await proc.exited in process-spawning tests

Files:

  • test/cli/install/bun-pack.test.ts
test/cli/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place CLI command tests under test/cli/

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}: Use bun:test for files ending with *.test.{ts,js,jsx,tsx,mjs,cjs}
Prefer concurrent tests (test.concurrent/describe.concurrent) over sequential when feasible
Organize tests with describe blocks to group related tests
Use utilities like describe.each, toMatchSnapshot, and lifecycle hooks (beforeAll, beforeEach, afterEach) and track resources for cleanup

Files:

  • test/cli/install/bun-pack.test.ts
test/**/*.{ts,tsx,js,jsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

For large/repetitive strings, use Buffer.alloc(count, fill).toString() instead of "A".repeat(count)

Files:

  • test/cli/install/bun-pack.test.ts
🧠 Learnings (3)
📚 Learning: 2025-09-26T01:10:04.233Z
Learnt from: nektro
PR: oven-sh/bun#22781
File: test/internal/ban-limits.json:25-26
Timestamp: 2025-09-26T01:10:04.233Z
Learning: The test/internal/ban-limits.json file contains accurate counts that are validated by tests - if the counts were incorrect, the associated tests would fail, so the values in this file reflect the actual current state of the codebase.

Applied to files:

  • test/internal/ban-limits.json
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/js/bun/**/*.{js,ts} : Place Bun API tests under test/js/bun/, separated by category (e.g., test/js/bun/glob/)

Applied to files:

  • test/cli/install/bun-pack.test.ts
📚 Learning: 2025-10-12T02:22:34.349Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-10-12T02:22:34.349Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun:test` for files ending with `*.test.{ts,js,jsx,tsx,mjs,cjs}`

Applied to files:

  • test/cli/install/bun-pack.test.ts
🧬 Code graph analysis (1)
test/cli/install/bun-pack.test.ts (2)
test/harness.ts (2)
  • pack (1304-1326)
  • bunEnv (49-64)
src/js/internal-for-testing.ts (1)
  • readTarball (125-125)
🔇 Additional comments (8)
test/internal/ban-limits.json (1)

36-36: Count update looks correct

The adjusted ban-limits count aligns with the test-driven source of truth for this file.

Based on learnings

src/cli/pack_command.zig (6)

217-228: Solid queue refactor and ordering

Switching to PackQueueItem and ordering by path is clean and future-proof. It enables optional entries and stable, predictable output.


236-244: Correctly integrates bins with “files” traversal and dedupe

  • Passing bins and pack_queue into iterateIncludedProjectTree/addEntireTree prevents duplicates.
  • Skipping bin dirs/files during include traversal aligns with pre-seeding/explicit bin handling.
  • Dedupe map avoids repeated file enqueue within “files”-driven traversal.

Also applies to: 329-334, 343-347, 356-363, 371-380


385-392: addEntireTree bin-aware and deduped

Dedupe + bin-file/dir skipping avoids double-inclusion while still walking included subtrees.

Also applies to: 470-478, 480-485


803-811: Default traversal now bin-aware

Skipping bin files/dirs in iterateProjectTree prevents duplication with the bin prepass. Good separation of concerns.

Also applies to: 819-820, 850-851, 885-891, 893-899


967-975: Bin parsing and path handling are robust

  • Normalizing to posix paths and storing as [:0]const u8 is appropriate.
  • Memory management via dupeZ and per-bin free at scope end is correct.

Also applies to: 985-992, 1001-1006, 1019-1026


1380-1401: Bin inclusion semantics match npm; optional flag is a nice touch

  • Pre-adding file bins (optional=true) ensures inclusion even when “files” omits them.
  • directories.bin traversal includes nested files while exec bits only apply to direct children (see isPackageBin), matching expectations.
  • Integrating bins into both “files” and default traversal via skip rules avoids duplicates.

Consider adding a test for a missing bin file (bin points to non-existent path) to confirm optional behavior matches npm for both normal and --dry-run modes. I can add it if you like.

Also applies to: 1433-1442, 1449-1457

test/cli/install/bun-pack.test.ts (1)

1284-1314: Great coverage for bins × files/directories and dedupe

  • Verifies bins are included even when “files” omits them.
  • Confirms directories.bin is traversed and coexists with “files”.
  • Ensures deduplication when entries appear via both routes.

Consider adding:

  • A case where bin points to a missing file to validate optional handling and Total files in --dry-run.
  • An assertion that nested entries under directories.bin (e.g. bins/what/what.js) do not get exec bits, while direct children do. Current behavior enforces this.

Also applies to: 1316-1351, 1353-1388

Comment on lines 2484 to 2498
while (pack_list.removeOrNull()) |item| {
const stat = root_dir.statat(item.path).unwrap() catch |err| {
if (item.optional) {
continue;
}
Output.err(err, "failed to stat file: \"{s}\"", .{item.path});
Global.crash();
};

ctx.stats.unpacked_size += @intCast(stat.size);

Output.prettyln(packed_fmt, .{
bun.fmt.size(stat.size, .{ .space_between_number_and_unit = false }),
filename,
item.path,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Dry-run “Total files” can be inflated when skipping missing optional entries

In dry-run, missing optional items are silently skipped in listing but not decremented from stats.total_files, unlike the non-dry-run path where you decrement when opening fails. Adjust stats in the dry-run branch to keep summary accurate.

Apply this diff:

-            while (pack_list.removeOrNull()) |item| {
-                const stat = root_dir.statat(item.path).unwrap() catch |err| {
-                    if (item.optional) {
-                        continue;
-                    }
+            while (pack_list.removeOrNull()) |item| {
+                const stat = root_dir.statat(item.path).unwrap() catch |err| {
+                    if (item.optional) {
+                        // keep Total files accurate in --dry-run
+                        ctx.stats.total_files -= 1;
+                        continue;
+                    }
                     Output.err(err, "failed to stat file: \"{s}\"", .{item.path});
                     Global.crash();
                 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while (pack_list.removeOrNull()) |item| {
const stat = root_dir.statat(item.path).unwrap() catch |err| {
if (item.optional) {
continue;
}
Output.err(err, "failed to stat file: \"{s}\"", .{item.path});
Global.crash();
};
ctx.stats.unpacked_size += @intCast(stat.size);
Output.prettyln(packed_fmt, .{
bun.fmt.size(stat.size, .{ .space_between_number_and_unit = false }),
filename,
item.path,
});
while (pack_list.removeOrNull()) |item| {
const stat = root_dir.statat(item.path).unwrap() catch |err| {
if (item.optional) {
// keep Total files accurate in --dry-run
ctx.stats.total_files -= 1;
continue;
}
Output.err(err, "failed to stat file: \"{s}\"", .{item.path});
Global.crash();
};
ctx.stats.unpacked_size += @intCast(stat.size);
Output.prettyln(packed_fmt, .{
bun.fmt.size(stat.size, .{ .space_between_number_and_unit = false }),
item.path,
});
🤖 Prompt for AI Agents
In src/cli/pack_command.zig around lines 2484 to 2498, when stat() fails for an
optional item the code currently continues without adjusting summary counts,
causing dry-run "Total files" to be inflated; modify the error handling in that
catch so that if item.optional you decrement ctx.stats.total_files (matching the
non-dry-run path) before continue, and leave non-optional behavior unchanged
(log error and Global.crash()).

@Jarred-Sumner
Copy link
Collaborator

LGTM once windows tests are fixed

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.

bun pm pack has different resolution than npm pack

3 participants