Skip to content

Commit

Permalink
Support reading from $HOME/.npmrc (#13990)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertshuford authored Sep 26, 2024
1 parent d42c032 commit 5e97fb8
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 9 deletions.
20 changes: 11 additions & 9 deletions src/ini.zig
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ pub const IniTestingAPIs = struct {

const install = allocator.create(bun.Schema.Api.BunInstall) catch bun.outOfMemory();
install.* = std.mem.zeroes(bun.Schema.Api.BunInstall);
loadNpmrc(allocator, install, env, false, &log, &source) catch {
loadNpmrc(allocator, install, env, false, ".npmrc", &log, &source) catch {
return log.toJS(globalThis, allocator, "error");
};

Expand Down Expand Up @@ -878,35 +878,36 @@ pub fn loadNpmrcFromFile(
install: *bun.Schema.Api.BunInstall,
env: *bun.DotEnv.Loader,
auto_loaded: bool,
npmrc_path: [:0]const u8,
) void {
var log = bun.logger.Log.init(allocator);
defer log.deinit();
const npmrc_file = switch (bun.sys.openat(bun.FD.cwd(), ".npmrc", bun.O.RDONLY, 0)) {
const npmrc_file = switch (bun.sys.openat(bun.FD.cwd(), npmrc_path, bun.O.RDONLY, 0)) {
.result => |fd| fd,
.err => |err| {
if (auto_loaded) return;
Output.prettyErrorln("{}\nwhile opening .npmrc \"{s}\"", .{
err,
".npmrc",
npmrc_path,
});
Global.exit(1);
},
};
defer _ = bun.sys.close(npmrc_file);

const source = switch (bun.sys.File.toSource(".npmrc", allocator)) {
const source = switch (bun.sys.File.toSource(npmrc_path, allocator)) {
.result => |s| s,
.err => |e| {
Output.prettyErrorln("{}\nwhile reading .npmrc \"{s}\"", .{
e,
".npmrc",
npmrc_path,
});
Global.exit(1);
},
};
defer allocator.free(source.contents);

loadNpmrc(allocator, install, env, auto_loaded, &log, &source) catch {
loadNpmrc(allocator, install, env, auto_loaded, npmrc_path, &log, &source) catch {
if (log.errors == 1)
Output.warn("Encountered an error while reading <b>.npmrc<r>:\n", .{})
else
Expand All @@ -920,10 +921,11 @@ pub fn loadNpmrc(
install: *bun.Schema.Api.BunInstall,
env: *bun.DotEnv.Loader,
auto_loaded: bool,
npmrc_path: [:0]const u8,
log: *bun.logger.Log,
source: *const bun.logger.Source,
) !void {
var parser = bun.ini.Parser.init(allocator, ".npmrc", source.contents, env);
var parser = bun.ini.Parser.init(allocator, npmrc_path, source.contents, env);
defer parser.deinit();
parser.parse(parser.arena.allocator()) catch |e| {
if (e == error.ParserError) {
Expand All @@ -933,13 +935,13 @@ pub fn loadNpmrc(
if (auto_loaded) {
Output.warn("{}\nwhile reading .npmrc \"{s}\"", .{
e,
".npmrc",
npmrc_path,
});
return;
}
Output.prettyErrorln("{}\nwhile reading .npmrc \"{s}\"", .{
e,
".npmrc",
npmrc_path,
});
Global.exit(1);
};
Expand Down
26 changes: 26 additions & 0 deletions src/install/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8492,6 +8492,31 @@ pub const PackageManager = struct {
try env.load(entries_option.entries, &[_][]u8{}, .production, false);

initializeStore();
if (bun.getenvZ("XDG_CONFIG_HOME") orelse bun.getenvZ(bun.DotEnv.home_env)) |data_dir| {
var buf: bun.PathBuffer = undefined;
var parts = [_]string{
"./.npmrc",
};

bun.ini.loadNpmrcFromFile(
ctx.allocator,
ctx.install orelse brk: {
const install_ = ctx.allocator.create(Api.BunInstall) catch bun.outOfMemory();
install_.* = std.mem.zeroes(Api.BunInstall);
ctx.install = install_;
break :brk install_;
},
env,
true,
Path.joinAbsStringBufZ(
data_dir,
&buf,
&parts,
.auto,
),
);
}

bun.ini.loadNpmrcFromFile(
ctx.allocator,
ctx.install orelse brk: {
Expand All @@ -8502,6 +8527,7 @@ pub const PackageManager = struct {
},
env,
true,
".npmrc",
);

var cpu_count = @as(u32, @truncate(((try std.Thread.getCpuCount()) + 1)));
Expand Down
91 changes: 91 additions & 0 deletions test/cli/install/registry/bun-install-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,97 @@ registry = http://localhost:${port}/
await Bun.$`${bunExe()} install`.cwd(packageDir).throws(true);
});

it("works with home config", async () => {
console.log("package dir", packageDir);
await Bun.$`rm -rf ${packageDir}/bunfig.toml`;

const homeDir = `${packageDir}/home_dir`;
await Bun.$`mkdir -p ${homeDir}`;
console.log("home dir", homeDir);

const ini = /* ini */ `
registry=http://localhost:${port}/
`;

await Bun.$`echo ${ini} > ${homeDir}/.npmrc`;
await Bun.$`echo ${JSON.stringify({
name: "foo",
dependencies: {
"no-deps": "1.0.0",
},
})} > package.json`.cwd(packageDir);
await Bun.$`${bunExe()} install`
.env({
...process.env,
XDG_CONFIG_HOME: `${homeDir}`,
})
.cwd(packageDir)
.throws(true);
});

it("works with two configs", async () => {
await Bun.$`rm -rf ${packageDir}/bunfig.toml`;

console.log("package dir", packageDir);
const packageIni = /* ini */ `
@types:registry=http://localhost:${port}/
`;
await Bun.$`echo ${packageIni} > ${packageDir}/.npmrc`;

const homeDir = `${packageDir}/home_dir`;
await Bun.$`mkdir -p ${homeDir}`;
console.log("home dir", homeDir);
const homeIni = /* ini */ `
registry = http://localhost:${port}/
`;
await Bun.$`echo ${homeIni} > ${homeDir}/.npmrc`;

await Bun.$`echo ${JSON.stringify({
name: "foo",
dependencies: {
"no-deps": "1.0.0",
"@types/no-deps": "1.0.0",
},
})} > package.json`.cwd(packageDir);
await Bun.$`${bunExe()} install`
.env({
...process.env,
XDG_CONFIG_HOME: `${homeDir}`,
})
.cwd(packageDir)
.throws(true);
});

it("package config overrides home config", async () => {
await Bun.$`rm -rf ${packageDir}/bunfig.toml`;

console.log("package dir", packageDir);
const packageIni = /* ini */ `
@types:registry=http://localhost:${port}/
`;
await Bun.$`echo ${packageIni} > ${packageDir}/.npmrc`;

const homeDir = `${packageDir}/home_dir`;
await Bun.$`mkdir -p ${homeDir}`;
console.log("home dir", homeDir);
const homeIni = /* ini */ "@types:registry=https://registry.npmjs.org/";
await Bun.$`echo ${homeIni} > ${homeDir}/.npmrc`;

await Bun.$`echo ${JSON.stringify({
name: "foo",
dependencies: {
"@types/no-deps": "1.0.0",
},
})} > package.json`.cwd(packageDir);
await Bun.$`${bunExe()} install`
.env({
...process.env,
XDG_CONFIG_HOME: `${homeDir}`,
})
.cwd(packageDir)
.throws(true);
});

it("default registry from env variable", async () => {
const ini = /* ini */ `
registry=\${LOL}
Expand Down

0 comments on commit 5e97fb8

Please sign in to comment.