mirror of
https://github.com/oven-sh/bun
synced 2026-02-04 07:58:54 +00:00
Compare commits
9 Commits
dylan/pyth
...
dylan/scri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62e73d6699 | ||
|
|
7ec2427dbf | ||
|
|
b8882454f1 | ||
|
|
9a93a1f3b8 | ||
|
|
a0cc23047a | ||
|
|
f182f3d74a | ||
|
|
a44784615b | ||
|
|
383f4bfa3e | ||
|
|
3b4f9ae958 |
@@ -348,8 +348,9 @@ pub const TrustCommand = struct {
|
||||
pm.sleep();
|
||||
}
|
||||
|
||||
const output_in_foreground = false;
|
||||
switch (pm.options.log_level) {
|
||||
inline else => |log_level| try pm.spawnPackageLifecycleScripts(ctx, info.scripts_list, log_level),
|
||||
inline else => |log_level| try pm.spawnPackageLifecycleScripts(ctx, info.scripts_list, log_level, output_in_foreground),
|
||||
}
|
||||
|
||||
if (pm.options.log_level.showProgress()) {
|
||||
|
||||
@@ -6435,10 +6435,15 @@ pub const PackageManager = struct {
|
||||
.npm => brk: {
|
||||
if (comptime FeatureFlags.breaking_changes_1_1_0) {
|
||||
if (request.version.tag == .dist_tag) {
|
||||
const fmt = if (options.exact_versions) "{}" else "^{}";
|
||||
break :brk try std.fmt.allocPrint(allocator, fmt, .{
|
||||
request.resolution.value.npm.version.fmt(request.version_buf),
|
||||
});
|
||||
if (options.exact_versions) {
|
||||
break :brk try std.fmt.allocPrint(allocator, "{}", .{
|
||||
request.resolution.value.npm.version.fmt(request.version_buf),
|
||||
});
|
||||
} else {
|
||||
break :brk try std.fmt.allocPrint(allocator, "^{}", .{
|
||||
request.resolution.value.npm.version.fmt(request.version_buf),
|
||||
});
|
||||
}
|
||||
}
|
||||
break :brk null;
|
||||
} else {
|
||||
@@ -8269,7 +8274,8 @@ pub const PackageManager = struct {
|
||||
const tree_id = entry.tree_id;
|
||||
if (this.canRunScripts(tree_id)) {
|
||||
_ = this.pending_lifecycle_scripts.swapRemove(i);
|
||||
this.manager.spawnPackageLifecycleScripts(this.command_ctx, entry.list, log_level) catch |err| {
|
||||
const output_in_foreground = false;
|
||||
this.manager.spawnPackageLifecycleScripts(this.command_ctx, entry.list, log_level, output_in_foreground) catch |err| {
|
||||
if (comptime log_level != .silent) {
|
||||
const fmt = "\n<r><red>error:<r> failed to spawn life-cycle scripts for <b>{s}<r>: {s}\n";
|
||||
const args = .{ name, @errorName(err) };
|
||||
@@ -8307,7 +8313,8 @@ pub const PackageManager = struct {
|
||||
PackageManager.instance.sleep();
|
||||
}
|
||||
|
||||
this.manager.spawnPackageLifecycleScripts(this.command_ctx, entry.list, log_level) catch |err| {
|
||||
const output_in_foreground = false;
|
||||
this.manager.spawnPackageLifecycleScripts(this.command_ctx, entry.list, log_level, output_in_foreground) catch |err| {
|
||||
if (comptime log_level != .silent) {
|
||||
const fmt = "\n<r><red>error:<r> failed to spawn life-cycle scripts for <b>{s}<r>: {s}\n";
|
||||
const args = .{ package_name, @errorName(err) };
|
||||
@@ -9190,23 +9197,6 @@ pub const PackageManager = struct {
|
||||
);
|
||||
}
|
||||
|
||||
const root_lifecycle_scripts_count = brk: {
|
||||
if (this.options.do.run_scripts and
|
||||
this.options.do.install_packages and
|
||||
this.root_lifecycle_scripts != null)
|
||||
{
|
||||
var counter: usize = 0;
|
||||
|
||||
for (this.root_lifecycle_scripts.?.items) |item| {
|
||||
if (item != null) counter += 1;
|
||||
}
|
||||
|
||||
this.total_scripts += counter;
|
||||
break :brk counter;
|
||||
}
|
||||
break :brk 0;
|
||||
};
|
||||
|
||||
var root_node: *Progress.Node = undefined;
|
||||
var download_node: Progress.Node = undefined;
|
||||
var install_node: Progress.Node = undefined;
|
||||
@@ -9220,7 +9210,7 @@ pub const PackageManager = struct {
|
||||
download_node = root_node.start(ProgressStrings.download(), 0);
|
||||
|
||||
install_node = root_node.start(ProgressStrings.install(), this.lockfile.packages.len);
|
||||
scripts_node = root_node.start(ProgressStrings.script(), root_lifecycle_scripts_count);
|
||||
scripts_node = root_node.start(ProgressStrings.script(), 0);
|
||||
this.downloads_node = &download_node;
|
||||
this.scripts_node = &scripts_node;
|
||||
}
|
||||
@@ -9515,10 +9505,14 @@ pub const PackageManager = struct {
|
||||
|
||||
installer.completeRemainingScripts(log_level);
|
||||
|
||||
if (root_lifecycle_scripts_count > 0) {
|
||||
// root lifecycle scripts can run now that all dependencies are installed
|
||||
// and their lifecycle script have finished
|
||||
try this.spawnPackageLifecycleScripts(ctx, this.root_lifecycle_scripts.?, log_level);
|
||||
if (comptime !FeatureFlags.breaking_changes_1_1_0) {
|
||||
if (this.root_lifecycle_scripts) |scripts| {
|
||||
if (comptime log_level.showProgress()) {
|
||||
scripts_node.setEstimatedTotalItems(scripts_node.unprotected_completed_items + scripts.total);
|
||||
}
|
||||
const output_in_foreground = false;
|
||||
try this.spawnPackageLifecycleScripts(ctx, scripts, log_level, output_in_foreground);
|
||||
}
|
||||
}
|
||||
|
||||
while (this.pending_lifecycle_script_tasks.load(.Monotonic) > 0) {
|
||||
@@ -9526,7 +9520,7 @@ pub const PackageManager = struct {
|
||||
if (PackageManager.hasEnoughTimePassedBetweenWaitingMessages()) Output.prettyErrorln("<d>[PackageManager]<r> waiting for {d} scripts\n", .{this.pending_lifecycle_script_tasks.load(.Monotonic)});
|
||||
}
|
||||
|
||||
PackageManager.instance.sleep();
|
||||
this.sleep();
|
||||
}
|
||||
|
||||
if (comptime log_level.showProgress()) {
|
||||
@@ -10166,6 +10160,33 @@ pub const PackageManager = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime FeatureFlags.breaking_changes_1_1_0) {
|
||||
if (manager.options.do.run_scripts) {
|
||||
if (manager.root_lifecycle_scripts) |scripts| {
|
||||
if (comptime Environment.allow_assert) {
|
||||
std.debug.assert(scripts.total > 0);
|
||||
}
|
||||
|
||||
if (comptime log_level != .silent) {
|
||||
Output.printError("\n", .{});
|
||||
Output.flush();
|
||||
}
|
||||
// root lifecycle scripts can run now that all dependencies are installed, dependency scripts
|
||||
// have finished, and lockfiles have been saved
|
||||
const output_in_foreground = true;
|
||||
try manager.spawnPackageLifecycleScripts(ctx, scripts, log_level, output_in_foreground);
|
||||
|
||||
while (manager.pending_lifecycle_script_tasks.load(.Monotonic) > 0) {
|
||||
if (PackageManager.verbose_install) {
|
||||
if (PackageManager.hasEnoughTimePassedBetweenWaitingMessages()) Output.prettyErrorln("<d>[PackageManager]<r> waiting for {d} scripts\n", .{manager.pending_lifecycle_script_tasks.load(.Monotonic)});
|
||||
}
|
||||
|
||||
manager.sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var printed_timestamp = false;
|
||||
if (comptime log_level != .silent) {
|
||||
if (manager.options.do.summary) {
|
||||
@@ -10286,6 +10307,7 @@ pub const PackageManager = struct {
|
||||
ctx: Command.Context,
|
||||
list: Lockfile.Package.Scripts.List,
|
||||
comptime log_level: PackageManager.Options.LogLevel,
|
||||
comptime foreground: bool,
|
||||
) !void {
|
||||
var any_scripts = false;
|
||||
for (list.items) |maybe_item| {
|
||||
@@ -10333,7 +10355,7 @@ pub const PackageManager = struct {
|
||||
try this_bundler.env.map.put("PATH", original_path);
|
||||
PATH.deinit();
|
||||
|
||||
try LifecycleScriptSubprocess.spawnPackageScripts(this, list, envp, log_level);
|
||||
try LifecycleScriptSubprocess.spawnPackageScripts(this, list, envp, log_level, foreground);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
|
||||
has_incremented_alive_count: bool = false,
|
||||
|
||||
foreground: bool = false,
|
||||
|
||||
pub usingnamespace bun.New(@This());
|
||||
|
||||
pub const min_milliseconds_to_log = 500;
|
||||
@@ -109,19 +111,6 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
this.stdout.setParent(this);
|
||||
this.stderr.setParent(this);
|
||||
|
||||
if (manager.scripts_node) |scripts_node| {
|
||||
manager.setNodeName(
|
||||
scripts_node,
|
||||
this.package_name,
|
||||
PackageManager.ProgressStrings.script_emoji,
|
||||
true,
|
||||
);
|
||||
if (manager.finished_installing.load(.Monotonic)) {
|
||||
scripts_node.activate();
|
||||
manager.progress.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
this.current_script_index = next_script_index;
|
||||
this.has_called_process_exit = false;
|
||||
|
||||
@@ -134,6 +123,22 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
|
||||
const combined_script: [:0]u8 = copy_script.items[0 .. copy_script.items.len - 1 :0];
|
||||
|
||||
if (this.foreground and this.manager.options.log_level != .silent) {
|
||||
Output.prettyError("<r><d><magenta>$<r> <d><b>{s}<r>\n", .{combined_script});
|
||||
Output.flush();
|
||||
} else if (manager.scripts_node) |scripts_node| {
|
||||
manager.setNodeName(
|
||||
scripts_node,
|
||||
this.package_name,
|
||||
PackageManager.ProgressStrings.script_emoji,
|
||||
true,
|
||||
);
|
||||
if (manager.finished_installing.load(.Monotonic)) {
|
||||
scripts_node.activate();
|
||||
manager.progress.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
log("{s} - {s} $ {s}", .{ this.package_name, this.scriptName(), combined_script });
|
||||
|
||||
var argv = [_]?[*:0]const u8{
|
||||
@@ -148,7 +153,9 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
}
|
||||
const spawn_options = bun.spawn.SpawnOptions{
|
||||
.stdin = .ignore,
|
||||
.stdout = if (this.manager.options.log_level.isVerbose())
|
||||
.stdout = if (this.manager.options.log_level == .silent)
|
||||
.ignore
|
||||
else if (this.manager.options.log_level.isVerbose() or this.foreground)
|
||||
.inherit
|
||||
else if (Environment.isPosix)
|
||||
.buffer
|
||||
@@ -156,7 +163,9 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
.{
|
||||
.buffer = this.stdout.source.?.pipe,
|
||||
},
|
||||
.stderr = if (this.manager.options.log_level.isVerbose())
|
||||
.stderr = if (this.manager.options.log_level == .silent)
|
||||
.ignore
|
||||
else if (this.manager.options.log_level.isVerbose() or this.foreground)
|
||||
.inherit
|
||||
else if (Environment.isPosix)
|
||||
.buffer
|
||||
@@ -286,11 +295,11 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
Global.exit(exit.code);
|
||||
}
|
||||
|
||||
if (this.manager.scripts_node) |scripts_node| {
|
||||
if (!this.foreground and this.manager.scripts_node != null) {
|
||||
if (this.manager.finished_installing.load(.Monotonic)) {
|
||||
scripts_node.completeOne();
|
||||
this.manager.scripts_node.?.completeOne();
|
||||
} else {
|
||||
_ = @atomicRmw(usize, &scripts_node.unprotected_completed_items, .Add, 1, .Monotonic);
|
||||
_ = @atomicRmw(usize, &this.manager.scripts_node.?.unprotected_completed_items, .Add, 1, .Monotonic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,12 +410,14 @@ pub const LifecycleScriptSubprocess = struct {
|
||||
list: Lockfile.Package.Scripts.List,
|
||||
envp: [:null]?[*:0]u8,
|
||||
comptime log_level: PackageManager.Options.LogLevel,
|
||||
comptime foreground: bool,
|
||||
) !void {
|
||||
var lifecycle_subprocess = LifecycleScriptSubprocess.new(.{
|
||||
.manager = manager,
|
||||
.envp = envp,
|
||||
.scripts = list,
|
||||
.package_name = list.package_name,
|
||||
.foreground = foreground,
|
||||
});
|
||||
|
||||
if (comptime log_level.isVerbose()) {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import { file, spawn } from "bun";
|
||||
import { bunEnv, bunExe, bunEnv as env, isWindows, mergeWindowEnvs, toBeValidBin, toHaveBins } from "harness";
|
||||
import {
|
||||
bunExe,
|
||||
bunEnv as env,
|
||||
isWindows,
|
||||
mergeWindowEnvs,
|
||||
toBeValidBin,
|
||||
toHaveBins,
|
||||
breakingChanges_1_1_0,
|
||||
} from "harness";
|
||||
import { join } from "path";
|
||||
import { mkdtempSync, realpathSync, copyFileSync, mkdirSync } from "fs";
|
||||
import { rm, writeFile, mkdir, exists, cp } from "fs/promises";
|
||||
@@ -7,7 +15,6 @@ import { readdirSorted } from "../dummy.registry";
|
||||
import { tmpdir } from "os";
|
||||
import { fork, ChildProcess } from "child_process";
|
||||
import { beforeAll, afterAll, beforeEach, afterEach, test, expect, describe } from "bun:test";
|
||||
import { f } from "js/bun/http/js-sink-sourmap-fixture/index.mjs";
|
||||
|
||||
expect.extend({
|
||||
toBeValidBin,
|
||||
@@ -3782,94 +3789,103 @@ for (const forceWaiterThread of [false, true]) {
|
||||
expect(await exited).toBe(0);
|
||||
});
|
||||
|
||||
test.todo("default trusted dependencies should not be used of trustedDependencies is populated", async () => {
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
"uses-what-bin": "1.0.0",
|
||||
// fake electron package because it's in the default trustedDependencies list
|
||||
"electron": "1.0.0",
|
||||
},
|
||||
}),
|
||||
);
|
||||
test.if(breakingChanges_1_1_0)(
|
||||
"default trusted dependencies should not be used of trustedDependencies is populated",
|
||||
async () => {
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
"uses-what-bin": "1.0.0",
|
||||
// fake electron package because it's in the default trustedDependencies list
|
||||
"electron": "1.0.0",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
var { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
var { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
// electron lifecycle scripts should run, uses-what-bin scripts should not run
|
||||
var err = await new Response(stderr).text();
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
var out = await new Response(stdout).text();
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
" + uses-what-bin@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("3 packages installed"),
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt"))).toBeFalse();
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeTrue();
|
||||
// electron lifecycle scripts should run, uses-what-bin scripts should not run
|
||||
var err = await new Response(stderr).text();
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
var out = await new Response(stdout).text();
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
" + uses-what-bin@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("3 packages installed"),
|
||||
"",
|
||||
" Blocked 1 postinstall. Run `bun pm untrusted` for details.",
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt"))).toBeFalse();
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeTrue();
|
||||
|
||||
await rm(join(packageDir, "node_modules"), { recursive: true, force: true });
|
||||
await rm(join(packageDir, "bun.lockb"));
|
||||
await rm(join(packageDir, "node_modules"), { recursive: true, force: true });
|
||||
await rm(join(packageDir, "bun.lockb"));
|
||||
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
"uses-what-bin": "1.0.0",
|
||||
"electron": "1.0.0",
|
||||
},
|
||||
trustedDependencies: ["uses-what-bin"],
|
||||
}),
|
||||
);
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
"uses-what-bin": "1.0.0",
|
||||
"electron": "1.0.0",
|
||||
},
|
||||
trustedDependencies: ["uses-what-bin"],
|
||||
}),
|
||||
);
|
||||
|
||||
// now uses-what-bin scripts should run and electron scripts should not run.
|
||||
// now uses-what-bin scripts should run and electron scripts should not run.
|
||||
|
||||
({ stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
}));
|
||||
({ stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
}));
|
||||
|
||||
err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
" + uses-what-bin@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("3 packages installed"),
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
" + uses-what-bin@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("3 packages installed"),
|
||||
"",
|
||||
" Blocked 1 postinstall. Run `bun pm untrusted` for details.",
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
|
||||
expect(await exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt"))).toBeTrue();
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeFalse();
|
||||
});
|
||||
expect(await exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt"))).toBeTrue();
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeFalse();
|
||||
},
|
||||
);
|
||||
|
||||
test.todo("does not run any scripts if trustedDependencies is an empty list", async () => {
|
||||
test.if(breakingChanges_1_1_0)("does not run any scripts if trustedDependencies is an empty list", async () => {
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
@@ -3904,86 +3920,95 @@ for (const forceWaiterThread of [false, true]) {
|
||||
" + uses-what-bin@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("3 packages installed"),
|
||||
"",
|
||||
" Blocked 2 postinstalls. Run `bun pm untrusted` for details.",
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt"))).toBeFalse();
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeFalse();
|
||||
});
|
||||
|
||||
test.todo("will run default trustedDependencies after install that didn't include them", async () => {
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
electron: "1.0.0",
|
||||
},
|
||||
trustedDependencies: ["blah"],
|
||||
}),
|
||||
);
|
||||
test.if(breakingChanges_1_1_0)(
|
||||
"will run default trustedDependencies after install that didn't include them",
|
||||
async () => {
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
electron: "1.0.0",
|
||||
},
|
||||
trustedDependencies: ["blah"],
|
||||
}),
|
||||
);
|
||||
|
||||
// first install does not run electron scripts
|
||||
// first install does not run electron scripts
|
||||
|
||||
var { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
var { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
var err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
var out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("1 package installed"),
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeFalse();
|
||||
var err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
var out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
" + electron@1.0.0",
|
||||
"",
|
||||
expect.stringContaining("1 package installed"),
|
||||
"",
|
||||
" Blocked 1 postinstall. Run `bun pm untrusted` for details.",
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeFalse();
|
||||
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
electron: "1.0.0",
|
||||
},
|
||||
}),
|
||||
);
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
dependencies: {
|
||||
electron: "1.0.0",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// The electron scripts should run now because it's in default trusted dependencies.
|
||||
// The electron scripts should run now because it's in default trusted dependencies.
|
||||
|
||||
({ stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
}));
|
||||
({ stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
}));
|
||||
|
||||
err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
"Checked 1 install across 2 packages (no changes)",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeTrue();
|
||||
});
|
||||
err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).toContain("Saved lockfile");
|
||||
expect(err).not.toContain("not found");
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("panic:");
|
||||
out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([
|
||||
"",
|
||||
"Checked 1 install across 2 packages (no changes)",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeTrue();
|
||||
},
|
||||
);
|
||||
|
||||
describe("--trust", async () => {
|
||||
const trustTests = [
|
||||
@@ -4814,6 +4839,109 @@ for (const forceWaiterThread of [false, true]) {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe.if(breakingChanges_1_1_0)("stdout/stderr is inherited from root scripts during install", async () => {
|
||||
test("without packages", async () => {
|
||||
const exe = bunExe().replace(/\\/g, "\\\\");
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
scripts: {
|
||||
"preinstall": `${exe} -e 'process.stderr.write("preinstall stderr 🍦\\n")'`,
|
||||
"install": `${exe} -e 'process.stdout.write("install stdout 🚀\\n")'`,
|
||||
"prepare": `${exe} -e 'Bun.sleepSync(200); process.stdout.write("prepare stdout done ✅\\n")'`,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
const err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("warn:");
|
||||
expect(err).not.toContain("panic:");
|
||||
expect(err.split(/\r?\n/)).toEqual([
|
||||
expect.stringContaining("bun install"),
|
||||
"No packages! Deleted empty lockfile",
|
||||
"",
|
||||
`$ ${exe} -e 'process.stderr.write("preinstall stderr 🍦\\n")'`,
|
||||
"preinstall stderr 🍦",
|
||||
`$ ${exe} -e 'process.stdout.write("install stdout 🚀\\n")'`,
|
||||
`$ ${exe} -e 'Bun.sleepSync(200); process.stdout.write("prepare stdout done ✅\\n")'`,
|
||||
"",
|
||||
]);
|
||||
const out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.split(/\r?\n/)).toEqual([
|
||||
"install stdout 🚀",
|
||||
"prepare stdout done ✅",
|
||||
"",
|
||||
expect.stringContaining("done"),
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
});
|
||||
test("with a package", async () => {
|
||||
const exe = bunExe().replace(/\\/g, "\\\\");
|
||||
await writeFile(
|
||||
join(packageDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "foo",
|
||||
version: "1.2.3",
|
||||
scripts: {
|
||||
"preinstall": `${exe} -e 'process.stderr.write("preinstall stderr 🍦\\n")'`,
|
||||
"install": `${exe} -e 'process.stdout.write("install stdout 🚀\\n")'`,
|
||||
"prepare": `${exe} -e 'Bun.sleepSync(200); process.stdout.write("prepare stdout done ✅\\n")'`,
|
||||
},
|
||||
dependencies: {
|
||||
"no-deps": "1.0.0",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: packageDir,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
const err = await Bun.readableStreamToText(stderr);
|
||||
expect(err).not.toContain("error:");
|
||||
expect(err).not.toContain("warn:");
|
||||
expect(err).not.toContain("panic:");
|
||||
expect(err.split(/\r?\n/)).toEqual([
|
||||
expect.stringContaining("bun install"),
|
||||
" Resolving dependencies",
|
||||
expect.stringContaining(" Resolved, downloaded and extracted "),
|
||||
" Saved lockfile",
|
||||
"",
|
||||
`$ ${exe} -e 'process.stderr.write("preinstall stderr 🍦\\n")'`,
|
||||
"preinstall stderr 🍦",
|
||||
`$ ${exe} -e 'process.stdout.write("install stdout 🚀\\n")'`,
|
||||
`$ ${exe} -e 'Bun.sleepSync(200); process.stdout.write("prepare stdout done ✅\\n")'`,
|
||||
"",
|
||||
]);
|
||||
const out = await Bun.readableStreamToText(stdout);
|
||||
expect(out.split(/\r?\n/)).toEqual([
|
||||
"install stdout 🚀",
|
||||
"prepare stdout done ✅",
|
||||
"",
|
||||
" + no-deps@1.0.0",
|
||||
"",
|
||||
expect.stringContaining(" 1 package installed"),
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe("pm trust", async () => {
|
||||
@@ -6736,7 +6864,7 @@ test.if(isWindows)(
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: mergeWindowEnvs([bunEnv, { PATH: PATH }]),
|
||||
env: mergeWindowEnvs([env, { PATH: PATH }]),
|
||||
});
|
||||
expect(stderr).toBeDefined();
|
||||
const err = await new Response(stderr).text();
|
||||
@@ -6754,7 +6882,7 @@ test.if(isWindows)(
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: mergeWindowEnvs([bunEnv, { PATH: PATH }]),
|
||||
env: mergeWindowEnvs([env, { PATH: PATH }]),
|
||||
});
|
||||
expect(stderr).toBeDefined();
|
||||
const err = await new Response(stderr).text();
|
||||
@@ -6772,7 +6900,7 @@ test.if(isWindows)(
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: mergeWindowEnvs([bunEnv, { PATH: PATH }]),
|
||||
env: mergeWindowEnvs([env, { PATH: PATH }]),
|
||||
});
|
||||
expect(stderr).toBeDefined();
|
||||
const err = await new Response(stderr).text();
|
||||
@@ -6790,7 +6918,7 @@ test.if(isWindows)(
|
||||
stdout: "pipe",
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: mergeWindowEnvs([bunEnv, { PATH: PATH }]),
|
||||
env: mergeWindowEnvs([env, { PATH: PATH }]),
|
||||
});
|
||||
expect(stderr).toBeDefined();
|
||||
const err = await new Response(stderr).text();
|
||||
|
||||
@@ -10,6 +10,8 @@ export const isPosix = isMacOS || isLinux;
|
||||
export const isWindows = process.platform === "win32";
|
||||
export const isIntelMacOS = isMacOS && process.arch === "x64";
|
||||
|
||||
export const breakingChanges_1_1_0 = false;
|
||||
|
||||
export const bunEnv: NodeJS.ProcessEnv = {
|
||||
...process.env,
|
||||
GITHUB_ACTIONS: "false",
|
||||
|
||||
Reference in New Issue
Block a user