diff options
-rw-r--r-- | src/install/extract_tarball.zig | 95 | ||||
-rw-r--r-- | src/libarchive/libarchive.zig | 45 |
2 files changed, 76 insertions, 64 deletions
diff --git a/src/install/extract_tarball.zig b/src/install/extract_tarball.zig index 0e813605e..3447394a9 100644 --- a/src/install/extract_tarball.zig +++ b/src/install/extract_tarball.zig @@ -195,39 +195,74 @@ fn extract(this: *const ExtractTarball, tgz_bytes: []const u8) !Install.ExtractD ); Global.crash(); }; - _ = if (PackageManager.verbose_install) - try Archive.extractToDir( - zlib_pool.data.list.items, - extract_destination, - null, - void, - void{}, - // for npm packages, the root dir is always "package" - // for github tarballs, the root dir is always the commit id - 1, - true, - true, - ) - else - try Archive.extractToDir( - zlib_pool.data.list.items, - extract_destination, - null, - void, - void{}, - // for npm packages, the root dir is always "package" - // for github tarballs, the root dir is always the commit id - 1, - true, - false, - ); - switch (this.resolution.tag) { .github => { - resolved = try Archive.readFirstDirname(zlib_pool.data.list.items); - resolved = try this.package_manager.allocator.dupe(u8, resolved); + const DirnameReader = struct { + needs_first_dirname: bool = true, + outdirname: *[]const u8, + pub fn onFirstDirectoryName(dirname_reader: *@This(), first_dirname: []const u8) void { + std.debug.assert(dirname_reader.needs_first_dirname); + dirname_reader.needs_first_dirname = false; + dirname_reader.outdirname.* = FileSystem.DirnameStore.instance.append([]const u8, first_dirname) catch unreachable; + } + }; + var dirname_reader = DirnameReader{ .outdirname = &resolved }; + + _ = if (PackageManager.verbose_install) + try Archive.extractToDir( + zlib_pool.data.list.items, + extract_destination, + null, + *DirnameReader, + &dirname_reader, + // for npm packages, the root dir is always "package" + // for github tarballs, the root dir is always the commit id + 1, + true, + true, + ) + else + try Archive.extractToDir( + zlib_pool.data.list.items, + extract_destination, + null, + *DirnameReader, + &dirname_reader, + // for npm packages, the root dir is always "package" + // for github tarballs, the root dir is always the commit id + 1, + true, + false, + ); + }, + else => { + _ = if (PackageManager.verbose_install) + try Archive.extractToDir( + zlib_pool.data.list.items, + extract_destination, + null, + void, + void{}, + // for npm packages, the root dir is always "package" + // for github tarballs, the root dir is always the commit id + 1, + true, + true, + ) + else + try Archive.extractToDir( + zlib_pool.data.list.items, + extract_destination, + null, + void, + void{}, + // for npm packages, the root dir is always "package" + // for github tarballs, the root dir is always the commit id + 1, + true, + false, + ); }, - else => {}, } if (PackageManager.verbose_install) { diff --git a/src/libarchive/libarchive.zig b/src/libarchive/libarchive.zig index 26eb5c5a3..adf9cdb4a 100644 --- a/src/libarchive/libarchive.zig +++ b/src/libarchive/libarchive.zig @@ -468,42 +468,12 @@ pub const Archive = struct { } } - pub fn readFirstDirname( - file_buffer: []const u8, - ) !string { - var entry: *lib.archive_entry = undefined; - - var stream: BufferReadStream = undefined; - stream.init(file_buffer); - defer stream.deinit(); - _ = stream.openRead(); - var archive = stream.archive; - - return brk: { - while (true) { - const r = @intToEnum(Status, lib.archive_read_next_header(archive, &entry)); - - switch (r) { - Status.eof => break, - Status.retry => continue, - Status.failed, Status.fatal => return error.Fail, - else => { - var pathname: [:0]const u8 = std.mem.sliceTo(lib.archive_entry_pathname(entry).?, 0); - var tokenizer = std.mem.tokenize(u8, std.mem.span(pathname), std.fs.path.sep_str); - - if (tokenizer.next()) |name| break :brk name; - }, - } - } - }; - } - pub fn extractToDir( file_buffer: []const u8, dir_: std.fs.IterableDir, ctx: ?*Archive.Context, - comptime FilePathAppender: type, - appender: FilePathAppender, + comptime ContextType: type, + appender: ContextType, comptime depth_to_skip: usize, comptime close_handles: bool, comptime log: bool, @@ -527,7 +497,14 @@ pub const Archive = struct { Status.retry => continue :loop, Status.failed, Status.fatal => return error.Fail, else => { - var pathname: [:0]const u8 = std.mem.sliceTo(lib.archive_entry_pathname(entry).?, 0); + var pathname: [:0]const u8 = bun.sliceTo(lib.archive_entry_pathname(entry).?, 0); + + if (comptime ContextType != void and @hasDecl(std.meta.Child(ContextType), "onFirstDirectoryName")) { + if (appender.needs_first_dirname) { + appender.onFirstDirectoryName(strings.withoutTrailingSlash(std.mem.span(pathname))); + } + } + var tokenizer = std.mem.tokenize(u8, std.mem.span(pathname), std.fs.path.sep_str); comptime var depth_i: usize = 0; @@ -610,7 +587,7 @@ pub const Archive = struct { else @as(u64, 0); - if (comptime FilePathAppender != void) { + if (comptime ContextType != void and @hasDecl(std.meta.Child(ContextType), "appendMutable")) { var result = ctx.?.all_files.getOrPutAdapted(hash, Context.U64Context{}) catch unreachable; if (!result.found_existing) { result.value_ptr.* = (try appender.appendMutable(@TypeOf(slice), slice)).ptr; |