MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add error propagation in interleaved extraction context

+62 -15
+12 -4
src/pkg/extractor.zig
··· 106 106 return true; 107 107 } 108 108 109 - pub fn getName(self: *const TarHeader, buf: []u8) []const u8 { 109 + pub fn getName(self: *const TarHeader, buf: []u8) ![]const u8 { 110 110 const prefix_len = std.mem.indexOfScalar(u8, &self.prefix, 0) orelse self.prefix.len; 111 111 const name_len = std.mem.indexOfScalar(u8, &self.name, 0) orelse self.name.len; 112 112 113 113 if (prefix_len > 0) { 114 + const total_len = prefix_len + 1 + name_len; 115 + if (total_len > buf.len) return error.InvalidPath; 114 116 @memcpy(buf[0..prefix_len], self.prefix[0..prefix_len]); 115 117 buf[prefix_len] = '/'; 116 118 @memcpy(buf[prefix_len + 1 ..][0..name_len], self.name[0..name_len]); ··· 280 282 281 283 if (self.header.isZero()) { 282 284 return .{ .kind = .end_of_archive, .consumed = to_copy }; 283 - } var path = self.header.getName(&self.path_buf); 285 + } var path = self.header.getName(&self.path_buf) catch { 286 + return .{ .kind = .{ .err = ExtractError.InvalidPath }, .consumed = to_copy }; 287 + }; 284 288 285 289 if (!self.prefix_detected and self.header.isDirectory()) { 286 - const prefix_len = @min(path.len, 128); 290 + var prefix_len = @min(path.len, 127); 287 291 @memcpy(self.strip_prefix[0..prefix_len], path[0..prefix_len]); 292 + if (prefix_len > 0 and self.strip_prefix[prefix_len - 1] != '/') { 293 + self.strip_prefix[prefix_len] = '/'; 294 + prefix_len += 1; 295 + } 288 296 self.strip_prefix_len = prefix_len; 289 297 self.prefix_detected = true; 290 298 } ··· 451 459 switch (entry.entry_type) { 452 460 .directory => self.output_dir.makePath(entry.path) catch {}, 453 461 .file => try self.createFile(entry), 454 - .symlink => try self.createSymlink(entry), 462 + .symlink => self.createSymlink(entry) catch {}, 455 463 } 456 464 } 457 465
+49 -11
src/pkg/linker.zig
··· 180 180 try self.allocator.dupe(u8, pkg.name); 181 181 defer self.allocator.free(install_path); 182 182 183 - const d = node_modules.openDir(install_path, .{}) catch null; 184 - if (d) |dir| { 185 - var dd = dir; 186 - defer dd.close(); 187 - if (dd.statFile("package.json")) |_| { 188 - _ = self.stats.packages_skipped.fetchAdd(1, .release); 189 - return; 190 - } else |_| {} 191 - } 192 - 193 183 var source_dir = std.fs.cwd().openDir(pkg.cache_path, .{ .iterate = true }) catch { 194 184 return error.PathNotFound; 195 185 }; 196 186 defer source_dir.close(); 197 187 188 + const source_version = readPackageVersion(self.allocator, source_dir); 189 + defer if (source_version) |v| self.allocator.free(v); 190 + 191 + var should_skip = false; 192 + var has_existing_install = false; 193 + 194 + { 195 + const existing = node_modules.openDir(install_path, .{}) catch null; 196 + if (existing) |dir| { 197 + has_existing_install = true; 198 + var installed_dir = dir; 199 + defer installed_dir.close(); 200 + 201 + const installed_version = readPackageVersion(self.allocator, installed_dir); 202 + defer if (installed_version) |v| self.allocator.free(v); 203 + should_skip = packageVersionsMatch(source_version, installed_version); 204 + } 205 + } 206 + 207 + if (should_skip) { 208 + _ = self.stats.packages_skipped.fetchAdd(1, .release); 209 + return; 210 + } 211 + 212 + if (has_existing_install) { 213 + node_modules.deleteTree(install_path) catch return error.IoError; 214 + } 215 + 198 216 node_modules.makePath(install_path) catch |err| switch (err) { 199 217 error.PathAlreadyExists => {}, 200 218 else => return error.IoError, ··· 241 259 pkg_name; 242 260 self.createBinSymlink(pkg_name, simple_name, bin_path, bin_dir) catch {}; 243 261 } 262 + } 263 + 264 + fn readPackageVersion(allocator: std.mem.Allocator, dir: std.fs.Dir) ?[]const u8 { 265 + const pkg_json = dir.openFile("package.json", .{}) catch return null; 266 + defer pkg_json.close(); 267 + 268 + const content = pkg_json.readToEndAlloc(allocator, 256 * 1024) catch return null; 269 + defer allocator.free(content); 270 + 271 + var doc = json.JsonDoc.parse(content) catch return null; 272 + defer doc.deinit(); 273 + 274 + const version = doc.root().getString("version") orelse return null; 275 + return allocator.dupe(u8, version) catch null; 276 + } 277 + 278 + fn packageVersionsMatch(source_version: ?[]const u8, installed_version: ?[]const u8) bool { 279 + const src = source_version orelse return false; 280 + const dst = installed_version orelse return false; 281 + return std.mem.eql(u8, src, dst); 244 282 } 245 283 246 284 fn createBinSymlink(self: *Linker, pkg_name: []const u8, cmd_name: []const u8, bin_path: []const u8, bin_dir: std.fs.Dir) !void { ··· 557 595 pub fn getStats(self: *const Linker) StatsSnapshot { 558 596 return self.stats.snapshot(); 559 597 } 560 - }; 598 + };
+1
src/pkg/root.zig
··· 902 902 struct { 903 903 fn onData(data: []const u8, ud: ?*anyopaque) void { 904 904 const c: *InterleavedExtractCtx = @ptrCast(@alignCast(ud)); 905 + if (c.has_error) return; 905 906 c.ext.feedCompressed(data) catch { c.has_error = true; }; 906 907 } 907 908 }.onData,