Compare commits

...

4 Commits

Author SHA1 Message Date
Don Isaac
a9ae300752 Merge branch 'main' into don/fix/pm-pack-case-insensitive 2025-04-09 17:35:12 -07:00
Don Isaac
3d6e1153fc Merge branch 'main' into don/fix/pm-pack-case-insensitive 2025-04-07 10:27:55 -07:00
Don Isaac
ff939e9fb3 Merge branch 'main' into don/fix/pm-pack-case-insensitive 2025-04-01 17:25:11 -07:00
Don Isaac
ff9c466f9b fix(pack): use case-insensitive equality on all platforms 2025-03-31 13:49:39 -07:00
2 changed files with 83 additions and 31 deletions

View File

@@ -2455,22 +2455,15 @@ pub const PackCommand = struct {
isSpecialFileOrVariant(filename, "README"));
}
// TODO: should this be case insensitive on all platforms?
const stringsEql = if (Environment.isLinux)
strings.eqlComptime
else
strings.eqlCaseInsensitiveASCIIICheckLength;
const stringsEql = strings.eqlCaseInsensitiveASCIIICheckLength;
fn isSpecialFileOrVariant(filename: []const u8, comptime name: []const u8) callconv(bun.callconv_inline) bool {
return switch (filename.len) {
inline 0...name.len - 1 => false,
inline name.len => stringsEql(filename, name),
inline name.len + 1 => false,
else => blk: {
bun.unsafeAssert(filename.len > name.len + 1);
break :blk filename[name.len] == '.' and stringsEql(filename[0..name.len], name);
},
};
if (filename.len < name.len) return false;
if (filename.len == name.len) return strings.eqlCaseInsensitiveASCIIIgnoreLength(filename, name);
if (filename.len > name.len + 1 and filename[name.len] == '.') {
return strings.eqlCaseInsensitiveASCIIIgnoreLength(filename[0..name.len], name);
}
return false;
}
};

View File

@@ -1,6 +1,6 @@
import { file, spawn, write } from "bun";
import { readTarball } from "bun:internal-for-testing";
import { beforeEach, describe, expect, test } from "bun:test";
import { beforeAll, beforeEach, describe, expect, test, it } from "bun:test";
import { exists, mkdir, rm } from "fs/promises";
import { bunEnv, bunExe, runBunInstall, tmpdirSync, pack, tempDirWithFiles } from "harness";
import { join } from "path";
@@ -909,26 +909,85 @@ describe("bundledDependnecies", () => {
});
describe("files", () => {
test("CHANGELOG is not included by default", async () => {
await Promise.all([
write(
join(packageDir, "package.json"),
JSON.stringify({
describe("When 'files' is set in package.json", () => {
let dir: string;
let tarball: any;
beforeAll(async () => {
dir = tempDirWithFiles("bun-pack-files", {
"package.json": JSON.stringify({
name: "pack-files-changelog",
version: "1.1.1",
files: ["lib"],
files: ["index.ts"],
}),
),
write(join(packageDir, "CHANGELOG.md"), "hello"),
write(join(packageDir, "lib", "index.js"), "console.log('hello ./lib/index.js')"),
]);
"index.ts": "console.log('hello ./index.ts')",
"foo.ts": "console.log('hello ./foo.ts')",
"LICENSE": "hello",
"LICENCE": "hello",
"LICENSE.txt": "hello",
"LICENSE.md": "hello",
"LICENCE.txt": "hello",
"CHANGELOG.md": "hello",
"changelog": "hello",
});
await write(join(dir, "licence"), "hello");
await write(join(dir, "license"), "hello");
console.log(dir);
await pack(dir, bunEnv);
tarball = readTarball(join(dir, "pack-files-changelog-1.1.1.tgz"));
expect(tarball.entries).toBeArray();
});
await pack(packageDir, bunEnv);
const tarball = readTarball(join(packageDir, "pack-files-changelog-1.1.1.tgz"));
expect(tarball.entries).toMatchObject([
{ "pathname": "package/package.json" },
{ "pathname": "package/lib/index.js" },
]);
it("should not include changelogs", () => {
expect(tarball.entries).not.toContainEqual(expect.objectContaining({ "pathname": "package/CHANGELOG.md" }));
expect(tarball.entries).not.toContainEqual(expect.objectContaining({ "pathname": "package/changelog" }));
});
it("always includes package.json", () => {
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/package.json" }));
});
it("includes license files", () => {
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/LICENSE" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/LICENCE" }));
});
it("special file inclusion is case insensitive", async () => {
// dir/tarball must be re-created here b/c files with the same name, just
// different casing, aren't getting created
let dir = tempDirWithFiles("bun-pack-files-case-insensitive", {
"package.json": JSON.stringify({
name: "pack-files-changelog",
version: "1.1.1",
files: ["index.ts"],
}),
"index.ts": "console.log('hello ./index.ts')",
"license": "MIT",
"licence": "MIT",
"license.txt": "MIT",
"licence.md": "MIT",
});
await pack(dir, bunEnv);
let tarball = readTarball(join(dir, "pack-files-changelog-1.1.1.tgz"));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/license" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/licence" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/license.txt" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/licence.md" }));
});
it("includes variants of license files", () => {
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/LICENSE.md" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/LICENSE.txt" }));
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/LICENCE.txt" }));
});
it("includes files in 'files'", () => {
expect(tarball.entries).toContainEqual(expect.objectContaining({ "pathname": "package/index.ts" }));
});
it('does not include source files not explicitly in "files"', () => {
expect(tarball.entries).not.toContainEqual({ "pathname": "package/foo.ts" });
});
});
test(".npmignore cannot exclude CHANGELOG", async () => {