aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/install/extract_tarball.zig4
-rw-r--r--src/install/install.zig58
-rw-r--r--src/install/lockfile.zig19
-rw-r--r--src/install/npm.zig40
-rw-r--r--src/install/resolution.zig15
-rw-r--r--src/install/versioned_url.zig31
6 files changed, 124 insertions, 43 deletions
diff --git a/src/install/extract_tarball.zig b/src/install/extract_tarball.zig
index fe50aa734..8dea0dfba 100644
--- a/src/install/extract_tarball.zig
+++ b/src/install/extract_tarball.zig
@@ -20,8 +20,8 @@ cache_dir: std.fs.Dir,
temp_dir: std.fs.Dir,
package_id: PackageID,
skip_verify: bool = false,
-
integrity: Integrity = Integrity{},
+url: string = "",
pub inline fn run(this: ExtractTarball, bytes: []const u8) !string {
if (!this.skip_verify and this.integrity.tag.isSupported()) {
@@ -220,7 +220,7 @@ fn extract(this: *const ExtractTarball, tgz_bytes: []const u8) !string {
Output.flush();
}
}
- var folder_name = PackageManager.instance.cachedNPMPackageFolderNamePrint(&abs_buf2, name, this.resolution.value.npm);
+ var folder_name = PackageManager.instance.cachedNPMPackageFolderNamePrint(&abs_buf2, name, this.resolution.value.npm.version);
if (folder_name.len == 0 or (folder_name.len == 1 and folder_name[0] == '/')) @panic("Tried to delete root and stopped it");
var cache_dir = this.cache_dir;
cache_dir.deleteTree(folder_name) catch {};
diff --git a/src/install/install.zig b/src/install/install.zig
index f8e0eb4c3..3f5f7a88f 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -358,12 +358,16 @@ const NetworkTask = struct {
tarball: ExtractTarball,
scope: *const Npm.Registry.Scope,
) !void {
- this.url_buf = try ExtractTarball.buildURL(
- scope.url.href,
- tarball.name,
- tarball.resolution.value.npm,
- PackageManager.instance.lockfile.buffers.string_bytes.items,
- );
+ if (tarball.url.len == 0) {
+ this.url_buf = try ExtractTarball.buildURL(
+ scope.url.href,
+ tarball.name,
+ tarball.resolution.value.npm.version,
+ PackageManager.instance.lockfile.buffers.string_bytes.items,
+ );
+ } else {
+ this.url_buf = tarball.url;
+ }
this.request_buffer = try MutableString.init(allocator, 0);
this.response_buffer = try MutableString.init(allocator, 0);
@@ -379,7 +383,6 @@ const NetworkTask = struct {
header_builder.content.cap += "Basic ".len + scope.auth.len;
}
- var header_entries = header_builder.entries;
var header_buf: string = "";
if (header_builder.header_count > 0) {
try header_builder.allocate(allocator);
@@ -389,13 +392,15 @@ const NetworkTask = struct {
} else if (scope.auth.len > 0) {
header_builder.appendFmt("Authorization", "Basic {s}", .{scope.auth});
}
+
+ header_buf = header_builder.content.ptr.?[0..header_builder.content.len];
}
this.http = try AsyncHTTP.init(
allocator,
.GET,
URL.parse(this.url_buf),
- header_entries,
+ header_builder.entries,
header_buf,
&this.response_buffer,
&this.request_buffer,
@@ -445,6 +450,8 @@ pub const Features = struct {
.optional_dependencies = true,
};
+ pub const tarball = npm;
+
pub const npm_manifest = Features{
.optional_dependencies = true,
};
@@ -1300,7 +1307,7 @@ pub const PackageManager = struct {
return .done;
}
- const folder_path = manager.cachedNPMPackageFolderName(this.name.slice(lockfile.buffers.string_bytes.items), this.resolution.value.npm);
+ const folder_path = manager.cachedNPMPackageFolderName(this.name.slice(lockfile.buffers.string_bytes.items), this.resolution.value.npm.version);
if (manager.isFolderInCache(folder_path)) {
manager.setPreinstallState(this.meta.id, lockfile, .done);
return .done;
@@ -1556,7 +1563,12 @@ pub const PackageManager = struct {
if (behavior.isPeer()) version else null,
.{
.tag = .npm,
- .value = .{ .npm = find_result.version },
+ .value = .{
+ .npm = .{
+ .version = find_result.version,
+ .url = find_result.package.tarball_url.value,
+ },
+ },
},
)) |id| {
this.lockfile.buffers.resolutions.items[dependency_id] = id;
@@ -1606,10 +1618,10 @@ pub const PackageManager = struct {
const task_id = Task.Id.forNPMPackage(
Task.Tag.extract,
name.slice(this.lockfile.buffers.string_bytes.items),
- package.resolution.value.npm,
+ package.resolution.value.npm.version,
);
- var network_task = (try this.generateNetworkTaskForTarball(task_id, package)).?;
+ var network_task = (try this.generateNetworkTaskForTarball(task_id, manifest.str(find_result.package.tarball_url), package)).?;
return ResolvedPackageResult{
.package = package,
@@ -1623,7 +1635,7 @@ pub const PackageManager = struct {
return ResolvedPackageResult{ .package = package };
}
- pub fn generateNetworkTaskForTarball(this: *PackageManager, task_id: u64, package: Lockfile.Package) !?*NetworkTask {
+ pub fn generateNetworkTaskForTarball(this: *PackageManager, task_id: u64, url: string, package: Lockfile.Package) !?*NetworkTask {
const dedupe_entry = try this.network_dedupe_map.getOrPut(this.allocator, task_id);
if (dedupe_entry.found_existing) return null;
@@ -1656,6 +1668,7 @@ pub const PackageManager = struct {
.registry = scope.url.href,
.package_id = package.meta.id,
.integrity = package.meta.integrity,
+ .url = url,
},
scope,
);
@@ -4171,7 +4184,7 @@ pub const PackageManager = struct {
if (this.manager.task_queue.fetchRemove(Task.Id.forNPMPackage(
Task.Tag.extract,
name,
- resolution.value.npm,
+ resolution.value.npm.version,
))) |removed| {
var callbacks = removed.value;
defer callbacks.deinit(this.manager.allocator);
@@ -4214,7 +4227,7 @@ pub const PackageManager = struct {
switch (resolution.tag) {
.npm => {
- installer.cache_dir_subpath = this.manager.cachedNPMPackageFolderName(name, resolution.value.npm);
+ installer.cache_dir_subpath = this.manager.cachedNPMPackageFolderName(name, resolution.value.npm.version);
installer.cache_dir = this.manager.getCacheDirectory();
},
.folder => {
@@ -4304,7 +4317,10 @@ pub const PackageManager = struct {
},
.fail => |cause| {
if (cause.isPackageMissingFromCache()) {
- const task_id = Task.Id.forNPMPackage(Task.Tag.extract, name, resolution.value.npm);
+ std.debug.assert(resolution.tag == .npm);
+ std.debug.assert(resolution.value.npm.url.len() > 0);
+
+ const task_id = Task.Id.forNPMPackage(Task.Tag.extract, name, resolution.value.npm.version);
var task_queue = this.manager.task_queue.getOrPut(this.manager.allocator, task_id) catch unreachable;
if (!task_queue.found_existing) {
task_queue.value_ptr.* = .{};
@@ -4317,10 +4333,12 @@ pub const PackageManager = struct {
},
) catch unreachable;
- if (this.manager.generateNetworkTaskForTarball(task_id, this.lockfile.packages.get(package_id)) catch unreachable) |task| {
- task.schedule(&this.manager.network_tarball_batch);
- if (this.manager.network_tarball_batch.len > 0) {
- _ = this.manager.scheduleNetworkTasks();
+ if (!task_queue.found_existing) {
+ if (this.manager.generateNetworkTaskForTarball(task_id, resolution.value.npm.url.slice(buf), this.lockfile.packages.get(package_id)) catch unreachable) |task| {
+ task.schedule(&this.manager.network_tarball_batch);
+ if (this.manager.network_tarball_batch.len > 0) {
+ _ = this.manager.scheduleNetworkTasks();
+ }
}
}
} else {
diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig
index eb53bb763..1c66056a1 100644
--- a/src/install/lockfile.zig
+++ b/src/install/lockfile.zig
@@ -1503,7 +1503,7 @@ pub fn getPackageID(
switch (version_.tag) {
.npm => {
// is it a peerDependency satisfied by a parent package?
- if (version_.value.npm.satisfies(resolutions[id].value.npm)) {
+ if (version_.value.npm.satisfies(resolutions[id].value.npm.version)) {
return id;
}
},
@@ -1527,7 +1527,7 @@ pub fn getPackageID(
return id;
}
- if (can_satisfy and version.?.value.npm.satisfies(resolutions[id].value.npm)) {
+ if (can_satisfy and version.?.value.npm.satisfies(resolutions[id].value.npm.version)) {
return id;
}
}
@@ -2002,6 +2002,8 @@ pub const Package = extern struct {
bin_extern_strings_count = package_version.bin.count(string_buf, manifest.extern_strings_bin_entries, @TypeOf(&string_builder), &string_builder);
}
+ string_builder.count(manifest.str(package_version_ptr.tarball_url));
+
try string_builder.allocate();
defer string_builder.clamp();
var extern_strings_list = &lockfile.buffers.extern_strings;
@@ -2020,11 +2022,14 @@ pub const Package = extern struct {
package.name = package_name.value;
package.resolution = Resolution{
.value = .{
- .npm = version.clone(
- manifest.string_buf,
- @TypeOf(&string_builder),
- &string_builder,
- ),
+ .npm = .{
+ .version = version.clone(
+ manifest.string_buf,
+ @TypeOf(&string_builder),
+ &string_builder,
+ ),
+ .url = string_builder.append(String, manifest.str(package_version_ptr.tarball_url)),
+ },
},
.tag = .npm,
};
diff --git a/src/install/npm.zig b/src/install/npm.zig
index 8ea89b20a..24c8fa71c 100644
--- a/src/install/npm.zig
+++ b/src/install/npm.zig
@@ -25,7 +25,7 @@ const ArrayIdentityContext = @import("../identity_context.zig").ArrayIdentityCon
const SlicedString = Semver.SlicedString;
const FileSystem = @import("../fs.zig").FileSystem;
const Dependency = @import("./dependency.zig");
-
+const VersionedURL = @import("./versioned_url.zig");
const VersionSlice = @import("./install.zig").VersionSlice;
const ObjectPool = @import("../pool.zig").ObjectPool;
const Api = @import("../api/schema.zig").Api;
@@ -822,6 +822,7 @@ pub const PackageManifest = struct {
var dependency_sum: usize = 0;
var extern_string_count: usize = 0;
var extern_string_count_bin: usize = 0;
+ var tarball_urls_count: usize = 0;
get_versions: {
if (json.asProperty("versions")) |versions_q| {
if (versions_q.expr.data != .e_object) break :get_versions;
@@ -840,6 +841,16 @@ pub const PackageManifest = struct {
string_builder.count(version_name);
+ if (prop.value.?.asProperty("dist")) |dist_q| {
+ if (dist_q.expr.get("tarball")) |tarball_prop| {
+ if (tarball_prop.data == .e_string) {
+ const tarball = tarball_prop.data.e_string.slice(allocator);
+ string_builder.count(tarball);
+ tarball_urls_count += @as(usize, @boolToInt(tarball.len > 0));
+ }
+ }
+ }
+
bin: {
if (prop.value.?.asProperty("bin")) |bin| {
switch (bin.expr.data) {
@@ -925,10 +936,12 @@ pub const PackageManifest = struct {
var versioned_packages = try allocator.allocAdvanced(PackageVersion, null, release_versions_len + pre_versions_len, .exact);
var all_semver_versions = try allocator.allocAdvanced(Semver.Version, null, release_versions_len + pre_versions_len + dist_tags_count, .exact);
- var all_extern_strings = try allocator.allocAdvanced(ExternalString, null, extern_string_count, .exact);
+ var all_extern_strings = try allocator.allocAdvanced(ExternalString, null, extern_string_count + tarball_urls_count, .exact);
var version_extern_strings = try allocator.allocAdvanced(ExternalString, null, dependency_sum, .exact);
var extern_strings_bin_entries = try allocator.allocAdvanced(ExternalString, null, extern_string_count_bin, .exact);
var all_extern_strings_bin_entries = extern_strings_bin_entries;
+ var all_tarball_url_strings = try allocator.allocAdvanced(ExternalString, null, tarball_urls_count, .exact);
+ var tarball_url_strings = all_tarball_url_strings;
if (versioned_packages.len > 0) {
var versioned_packages_bytes = std.mem.sliceAsBytes(versioned_packages);
@@ -1159,6 +1172,14 @@ pub const PackageManifest = struct {
integrity: {
if (prop.value.?.asProperty("dist")) |dist| {
if (dist.expr.data == .e_object) {
+ if (dist.expr.asProperty("tarball")) |tarball_q| {
+ if (tarball_q.expr.data == .e_string and tarball_q.expr.data.e_string.len() > 0) {
+ package_version.tarball_url = string_builder.append(ExternalString, tarball_q.expr.data.e_string.slice(allocator));
+ tarball_url_strings[0] = package_version.tarball_url;
+ tarball_url_strings = tarball_url_strings[1..];
+ }
+ }
+
if (dist.expr.asProperty("fileCount")) |file_count_| {
if (file_count_.expr.data == .e_number) {
package_version.file_count = file_count_.expr.data.e_number.toU32();
@@ -1183,6 +1204,12 @@ pub const PackageManifest = struct {
package_version.integrity = Integrity.parseSHASum(shasum_str) catch Integrity{};
}
}
+
+ if (dist.expr.asProperty("shasum")) |shasum| {
+ if (shasum.expr.asString(allocator)) |shasum_str| {
+ package_version.integrity = Integrity.parseSHASum(shasum_str) catch Integrity{};
+ }
+ }
}
}
}
@@ -1435,7 +1462,14 @@ pub const PackageManifest = struct {
result.pkg.prereleases.keys = VersionSlice.init(all_semver_versions, all_prerelease_versions);
result.pkg.prereleases.values = PackageVersionList.init(versioned_packages, all_versioned_package_prereleases);
- if (extern_strings.len > 0) {
+ if (extern_strings.len + tarball_urls_count > 0) {
+ var src = std.mem.sliceAsBytes(all_tarball_url_strings[0 .. all_tarball_url_strings.len - tarball_url_strings.len]);
+ if (src.len > 0) {
+ var dst = std.mem.sliceAsBytes(all_extern_strings[all_extern_strings.len - extern_strings.len ..]);
+ std.debug.assert(dst.len >= src.len);
+ @memcpy(dst.ptr, src.ptr, src.len);
+ }
+
all_extern_strings = all_extern_strings[0 .. all_extern_strings.len - extern_strings.len];
}
diff --git a/src/install/resolution.zig b/src/install/resolution.zig
index ad9164c88..231ff3475 100644
--- a/src/install/resolution.zig
+++ b/src/install/resolution.zig
@@ -7,6 +7,7 @@ const Repository = @import("./repository.zig").Repository;
const string = @import("../string_types.zig").string;
const ExtractTarball = @import("./extract_tarball.zig");
const strings = @import("../string_immutable.zig");
+const VersionedURL = @import("./versioned_url.zig");
pub const Resolution = extern struct {
tag: Tag = Tag.uninitialized,
@@ -180,14 +181,7 @@ pub const Resolution = extern struct {
pub fn format(formatter: URLFormatter, comptime layout: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
switch (formatter.resolution.tag) {
- .npm => try ExtractTarball.buildURLWithWriter(
- @TypeOf(writer),
- writer,
- formatter.options.scope.url.href,
- strings.StringOrTinyString.init(formatter.package_name),
- formatter.resolution.value.npm,
- formatter.buf,
- ),
+ .npm => try writer.writeAll(formatter.resolution.value.npm.url.slice(formatter.buf)),
.local_tarball => try writer.writeAll(formatter.resolution.value.local_tarball.slice(formatter.buf)),
.git_ssh => try std.fmt.format(writer, "git+ssh://{s}", .{formatter.resolution.value.git_ssh.slice(formatter.buf)}),
.git_http => try std.fmt.format(writer, "https://{s}", .{formatter.resolution.value.git_http.slice(formatter.buf)}),
@@ -209,7 +203,7 @@ pub const Resolution = extern struct {
pub fn format(formatter: Formatter, comptime layout: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
switch (formatter.resolution.tag) {
- .npm => try formatter.resolution.value.npm.fmt(formatter.buf).format(layout, opts, writer),
+ .npm => try formatter.resolution.value.npm.version.fmt(formatter.buf).format(layout, opts, writer),
.local_tarball => try writer.writeAll(formatter.resolution.value.local_tarball.slice(formatter.buf)),
.git_ssh => try std.fmt.format(writer, "git+ssh://{s}", .{formatter.resolution.value.git_ssh.slice(formatter.buf)}),
.git_http => try std.fmt.format(writer, "https://{s}", .{formatter.resolution.value.git_http.slice(formatter.buf)}),
@@ -229,7 +223,7 @@ pub const Resolution = extern struct {
uninitialized: void,
root: void,
- npm: Semver.Version,
+ npm: VersionedURL,
/// File path to a tarball relative to the package root
local_tarball: String,
@@ -258,7 +252,6 @@ pub const Resolution = extern struct {
uninitialized = 0,
root = 1,
npm = 2,
-
folder = 4,
local_tarball = 8,
diff --git a/src/install/versioned_url.zig b/src/install/versioned_url.zig
new file mode 100644
index 000000000..c52a64d97
--- /dev/null
+++ b/src/install/versioned_url.zig
@@ -0,0 +1,31 @@
+const Semver = @import("./semver.zig");
+const String = @import("./semver.zig").String;
+
+const VersionedURL = @This();
+
+url: String,
+version: Semver.Version,
+
+pub fn eql(this: VersionedURL, other: VersionedURL) bool {
+ return this.version.eql(other.version);
+}
+
+pub fn order(this: VersionedURL, other: VersionedURL, lhs_buf: []const u8, rhs_buf: []const u8) @import("std").math.Order {
+ return this.version.order(other.version, lhs_buf, rhs_buf);
+}
+
+pub fn fmt(this: VersionedURL, buf: []const u8) Semver.Version.Formatter {
+ return this.version.fmt(buf);
+}
+
+pub fn count(this: VersionedURL, buf: []const u8, comptime Builder: type, builder: Builder) void {
+ this.version.count(buf, comptime Builder, builder);
+ builder.count(this.url.slice(buf));
+}
+
+pub fn clone(this: VersionedURL, buf: []const u8, comptime Builder: type, builder: Builder) VersionedURL {
+ return VersionedURL{
+ .version = this.version.clone(buf, Builder, builder),
+ .url = builder.append(String, this.url.slice(buf)),
+ };
+}