diff options
Diffstat (limited to '')
| -rw-r--r-- | src/bun.zig | 23 | ||||
| -rw-r--r-- | src/install/install.zig | 40 | ||||
| -rw-r--r-- | src/install/lockfile.zig | 46 | 
3 files changed, 95 insertions, 14 deletions
| diff --git a/src/bun.zig b/src/bun.zig index 790ec5d04..c7b15340e 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -1841,3 +1841,26 @@ pub fn fdi32(fd_: anytype) i32 {  }  pub const OSPathSlice = if (Environment.isWindows) [:0]const u16 else [:0]const u8; +pub const LazyBoolValue = enum { +    unknown, +    no, +    yes, +}; +/// Create a lazily computed boolean value. +/// Getter must be a function that takes a pointer to the parent struct and returns a boolean. +/// Parent must be a type which contains the field we are getting. +pub fn LazyBool(comptime Getter: anytype, comptime Parent: type, comptime field: string) type { +    return struct { +        value: LazyBoolValue = .unknown, +        pub fn get(self: *@This()) bool { +            if (self.value == .unknown) { +                self.value = switch (Getter(@fieldParentPtr(Parent, field, self))) { +                    true => .yes, +                    false => .no, +                }; +            } + +            return self.value == .yes; +        } +    }; +} diff --git a/src/install/install.zig b/src/install/install.zig index 3757a6980..28a96643d 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -1697,6 +1697,7 @@ pub const PackageManager = struct {      wait_count: std.atomic.Atomic(usize) = std.atomic.Atomic(usize).init(0),      onWake: WakeHandler = .{}, +    ci_mode: bun.LazyBool(computeIsContinuousIntegration, @This(), "ci_mode") = .{},      const PreallocatedNetworkTasks = std.BoundedArray(NetworkTask, 1024);      const NetworkTaskQueue = std.HashMapUnmanaged(u64, void, IdentityContext(u64), 80); @@ -1717,6 +1718,14 @@ pub const PackageManager = struct {          return this.env.getTLSRejectUnauthorized();      } +    pub fn computeIsContinuousIntegration(this: *PackageManager) bool { +        return this.env.isCI(); +    } + +    pub inline fn isContinuousIntegration(this: *PackageManager) bool { +        return this.ci_mode.get(); +    } +      pub const WakeHandler = struct {          // handler: fn (ctx: *anyopaque, pm: *PackageManager) void = undefined,          // onDependencyError: fn (ctx: *anyopaque, Dependency, PackageID, anyerror) void = undefined, @@ -1886,6 +1895,37 @@ pub const PackageManager = struct {          @memset(this.preinstall_state.items[offset..], PreinstallState.unknown);      } +    pub fn laterVersionInCache(this: *PackageManager, name: []const u8, name_hash: PackageNameHash, resolution: Resolution) ?Semver.Version { +        switch (resolution.tag) { +            Resolution.Tag.npm => { +                if (resolution.value.npm.version.tag.hasPre()) +                    // TODO: +                    return null; + +                const manifest: *const Npm.PackageManifest = this.manifests.getPtr(name_hash) orelse brk: { +                    // We skip this in CI because we don't want any performance impact in an environment you'll probably never use +                    if (this.isContinuousIntegration()) +                        return null; + +                    if (Npm.PackageManifest.Serializer.load(this.allocator, this.getCacheDirectory(), name) catch null) |manifest_| { +                        this.manifests.put(this.allocator, name_hash, manifest_) catch return null; +                        break :brk this.manifests.getPtr(name_hash).?; +                    } + +                    return null; +                }; + +                if (manifest.findByDistTag("latest")) |latest_version| { +                    if (latest_version.version.order(resolution.value.npm.version, this.lockfile.buffers.string_bytes.items, this.lockfile.buffers.string_bytes.items) != .gt) return null; +                    return latest_version.version; +                } + +                return null; +            }, +            else => return null, +        } +    } +      pub fn setPreinstallState(this: *PackageManager, package_id: PackageID, lockfile: *Lockfile, value: PreinstallState) void {          this.ensurePreinstallStateListCapacity(lockfile.packages.len) catch return;          this.preinstall_state.items[package_id] = value; diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index a3e51f59f..fd742d559 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -1057,21 +1057,39 @@ pub const Printer = struct {                      if (!installed.isSet(package_id)) continue; -                    const fmt = comptime brk: { -                        if (enable_ansi_colors) { -                            break :brk Output.prettyFmt("<r> <green>+<r> <b>{s}<r><d>@{}<r>\n", enable_ansi_colors); -                        } else { -                            break :brk Output.prettyFmt("<r> + {s}<r><d>@{}<r>\n", enable_ansi_colors); -                        } -                    }; +                    if (PackageManager.instance.laterVersionInCache(package_name, dependency.name_hash, resolved[package_id])) |later_version| { +                        const fmt = comptime brk: { +                            if (enable_ansi_colors) { +                                break :brk Output.prettyFmt("<r> <green>+<r> <b>{s}<r><d>@{}<r> <d>(<blue>v{} available<r><d>)<r>\n", enable_ansi_colors); +                            } else { +                                break :brk Output.prettyFmt("<r> + {s}<r><d>@{}<r> <d>(v{} available)<r>\n", enable_ansi_colors); +                            } +                        }; +                        try writer.print( +                            fmt, +                            .{ +                                package_name, +                                resolved[package_id].fmt(string_buf), +                                later_version.fmt(string_buf), +                            }, +                        ); +                    } else { +                        const fmt = comptime brk: { +                            if (enable_ansi_colors) { +                                break :brk Output.prettyFmt("<r> <green>+<r> <b>{s}<r><d>@{}<r>\n", enable_ansi_colors); +                            } else { +                                break :brk Output.prettyFmt("<r> + {s}<r><d>@{}<r>\n", enable_ansi_colors); +                            } +                        }; -                    try writer.print( -                        fmt, -                        .{ -                            package_name, -                            resolved[package_id].fmt(string_buf), -                        }, -                    ); +                        try writer.print( +                            fmt, +                            .{ +                                package_name, +                                resolved[package_id].fmt(string_buf), +                            }, +                        ); +                    }                  }              } else {                  outer: for (dependencies_buffer, resolutions_buffer, 0..) |dependency, package_id, dep_id| { | 
