mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 03:48:56 +00:00
### What does this PR do? fixes #22679 * includes a better error if a package cant be met because of the age (but would normally) * logs the resolved one in --verbose (which can be helpful in debugging to show it does know latest but couldn't use) * makes bun outdated show in the table when the package isn't true latest * includes a rudimentary "stability" check if a later version is in blacked out time (but only up to 7 days as it goes back to latest with min age) For extended security we could also Last-Modified header of the tgz download and then abort if too new (just like the hash) | install error with no recent version | bun outdated respecting the rule | | --- | --- | <img width="838" height="119" alt="image" src="https://github.com/user-attachments/assets/b60916a8-27f6-4405-bfb6-57f9fa8bb0d6" /> | <img width="609" height="314" alt="image" src="https://github.com/user-attachments/assets/d8869ff4-8e16-492c-8e4c-9ac1dfa302ba" /> | For stable release we will make it use `3d` type syntax instead of magic second numbers. ### How did you verify your code works? tests & manual --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
125 lines
4.4 KiB
Zig
125 lines
4.4 KiB
Zig
hash_map: HashMap = .{},
|
|
|
|
const Value = union(enum) {
|
|
expired: Npm.PackageManifest,
|
|
manifest: Npm.PackageManifest,
|
|
|
|
// Avoid checking the filesystem again.
|
|
not_found: void,
|
|
};
|
|
const HashMap = std.HashMapUnmanaged(PackageNameHash, Value, IdentityContext(PackageNameHash), 80);
|
|
|
|
pub fn byName(this: *PackageManifestMap, pm: *PackageManager, scope: *const Npm.Registry.Scope, name: []const u8, cache_behavior: CacheBehavior, needs_extended_manifest: bool) ?*Npm.PackageManifest {
|
|
return this.byNameHash(pm, scope, String.Builder.stringHash(name), cache_behavior, needs_extended_manifest);
|
|
}
|
|
|
|
pub fn insert(this: *PackageManifestMap, name_hash: PackageNameHash, manifest: *const Npm.PackageManifest) !void {
|
|
try this.hash_map.put(bun.default_allocator, name_hash, .{ .manifest = manifest.* });
|
|
}
|
|
|
|
pub fn byNameHash(this: *PackageManifestMap, pm: *PackageManager, scope: *const Npm.Registry.Scope, name_hash: PackageNameHash, cache_behavior: CacheBehavior, needs_extended_manifest: bool) ?*Npm.PackageManifest {
|
|
return byNameHashAllowExpired(this, pm, scope, name_hash, null, cache_behavior, needs_extended_manifest);
|
|
}
|
|
|
|
pub fn byNameAllowExpired(this: *PackageManifestMap, pm: *PackageManager, scope: *const Npm.Registry.Scope, name: string, is_expired: ?*bool, cache_behavior: CacheBehavior, needs_extended_manifest: bool) ?*Npm.PackageManifest {
|
|
return byNameHashAllowExpired(this, pm, scope, String.Builder.stringHash(name), is_expired, cache_behavior, needs_extended_manifest);
|
|
}
|
|
|
|
pub const CacheBehavior = enum {
|
|
load_from_memory,
|
|
load_from_memory_fallback_to_disk,
|
|
};
|
|
|
|
pub fn byNameHashAllowExpired(
|
|
this: *PackageManifestMap,
|
|
pm: *PackageManager,
|
|
scope: *const Npm.Registry.Scope,
|
|
name_hash: PackageNameHash,
|
|
is_expired: ?*bool,
|
|
cache_behavior: CacheBehavior,
|
|
needs_extended_manifest: bool,
|
|
) ?*Npm.PackageManifest {
|
|
if (cache_behavior == .load_from_memory) {
|
|
const entry = this.hash_map.getPtr(name_hash) orelse return null;
|
|
return switch (entry.*) {
|
|
.manifest => &entry.manifest,
|
|
.expired => if (is_expired) |expiry| {
|
|
expiry.* = true;
|
|
return &entry.expired;
|
|
} else null,
|
|
.not_found => null,
|
|
};
|
|
}
|
|
|
|
const entry = bun.handleOom(this.hash_map.getOrPut(bun.default_allocator, name_hash));
|
|
if (entry.found_existing) {
|
|
if (entry.value_ptr.* == .manifest) {
|
|
if (needs_extended_manifest and !entry.value_ptr.manifest.pkg.has_extended_manifest) {
|
|
entry.value_ptr.* = .{ .expired = entry.value_ptr.manifest };
|
|
} else {
|
|
return &entry.value_ptr.manifest;
|
|
}
|
|
}
|
|
|
|
if (is_expired) |expiry| {
|
|
if (entry.value_ptr.* == .expired) {
|
|
expiry.* = true;
|
|
return &entry.value_ptr.expired;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
if (pm.options.enable.manifest_cache) {
|
|
if (Npm.PackageManifest.Serializer.loadByFileID(
|
|
pm.allocator,
|
|
scope,
|
|
pm.getCacheDirectory(),
|
|
name_hash,
|
|
) catch null) |manifest| {
|
|
if (needs_extended_manifest and !manifest.pkg.has_extended_manifest) {
|
|
entry.value_ptr.* = .{ .expired = manifest };
|
|
if (is_expired) |expiry| {
|
|
expiry.* = true;
|
|
return &entry.value_ptr.expired;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
if (pm.options.enable.manifest_cache_control and manifest.pkg.public_max_age > pm.timestamp_for_manifest_cache_control) {
|
|
entry.value_ptr.* = .{ .manifest = manifest };
|
|
return &entry.value_ptr.manifest;
|
|
} else {
|
|
entry.value_ptr.* = .{ .expired = manifest };
|
|
|
|
if (is_expired) |expiry| {
|
|
expiry.* = true;
|
|
return &entry.value_ptr.expired;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
entry.value_ptr.* = .{ .not_found = {} };
|
|
return null;
|
|
}
|
|
|
|
const string = []const u8;
|
|
|
|
const std = @import("std");
|
|
|
|
const install = @import("./install.zig");
|
|
const Npm = install.Npm;
|
|
const PackageManager = install.PackageManager;
|
|
const PackageManifestMap = install.PackageManifestMap;
|
|
const PackageNameHash = install.PackageNameHash;
|
|
|
|
const bun = @import("bun");
|
|
const IdentityContext = bun.IdentityContext;
|
|
|
|
const Semver = bun.Semver;
|
|
const String = Semver.String;
|