Skip to content

Commit 72bcc3b

Browse files
authored
std.tar: add writer (#19603)
Simplifies code in docs creation where we used `std.tar.output.Header`. Writer uses that Header internally and provides higher level interface. Updates checksum on write, handles long file names, allows setting mtime and file permission mode. Provides handy interface for passing `Dir.WalkerEntry`.
1 parent 708414a commit 72bcc3b

File tree

6 files changed

+517
-174
lines changed

6 files changed

+517
-174
lines changed

lib/compiler/std-docs.zig

+8-32
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,16 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
181181
},
182182
},
183183
});
184-
const w = response.writer();
185184

186185
var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true });
187186
defer std_dir.close();
188187

189188
var walker = try std_dir.walk(gpa);
190189
defer walker.deinit();
191190

191+
var archiver = std.tar.writer(response.writer());
192+
archiver.prefix = "std";
193+
192194
while (try walker.next()) |entry| {
193195
switch (entry.kind) {
194196
.file => {
@@ -199,47 +201,21 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
199201
},
200202
else => continue,
201203
}
202-
203-
var file = try std_dir.openFile(entry.path, .{});
204+
var file = try entry.dir.openFile(entry.basename, .{});
204205
defer file.close();
205-
206-
const stat = try file.stat();
207-
const padding = p: {
208-
const remainder = stat.size % 512;
209-
break :p if (remainder > 0) 512 - remainder else 0;
210-
};
211-
212-
var file_header = std.tar.output.Header.init();
213-
file_header.typeflag = .regular;
214-
try file_header.setPath("std", entry.path);
215-
try file_header.setSize(stat.size);
216-
try file_header.updateChecksum();
217-
try w.writeAll(std.mem.asBytes(&file_header));
218-
try w.writeFile(file);
219-
try w.writeByteNTimes(0, padding);
206+
try archiver.writeFile(entry.path, file);
220207
}
221208

222209
{
223210
// Since this command is JIT compiled, the builtin module available in
224211
// this source file corresponds to the user's host system.
225212
const builtin_zig = @embedFile("builtin");
226-
227-
var file_header = std.tar.output.Header.init();
228-
file_header.typeflag = .regular;
229-
try file_header.setPath("builtin", "builtin.zig");
230-
try file_header.setSize(builtin_zig.len);
231-
try file_header.updateChecksum();
232-
try w.writeAll(std.mem.asBytes(&file_header));
233-
try w.writeAll(builtin_zig);
234-
const padding = p: {
235-
const remainder = builtin_zig.len % 512;
236-
break :p if (remainder > 0) 512 - remainder else 0;
237-
};
238-
try w.writeByteNTimes(0, padding);
213+
archiver.prefix = "builtin";
214+
try archiver.writeFileBytes("builtin.zig", builtin_zig, .{});
239215
}
240216

241217
// intentionally omitting the pointless trailer
242-
//try w.writeByteNTimes(0, 512 * 2);
218+
//try archiver.finish();
243219
try response.end();
244220
}
245221

lib/std/Build/Fuzz/WebServer.zig

+5-25
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,6 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
456456
},
457457
},
458458
});
459-
const w = response.writer();
460459

461460
const DedupeTable = std.ArrayHashMapUnmanaged(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false);
462461
var dedupe_table: DedupeTable = .{};
@@ -490,40 +489,21 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
490489

491490
var cwd_cache: ?[]const u8 = null;
492491

492+
var archiver = std.tar.writer(response.writer());
493+
493494
for (deduped_paths) |joined_path| {
494495
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
495496
log.err("failed to open {}: {s}", .{ joined_path, @errorName(err) });
496497
continue;
497498
};
498499
defer file.close();
499500

500-
const stat = file.stat() catch |err| {
501-
log.err("failed to stat {}: {s}", .{ joined_path, @errorName(err) });
502-
continue;
503-
};
504-
if (stat.kind != .file)
505-
continue;
506-
507-
const padding = p: {
508-
const remainder = stat.size % 512;
509-
break :p if (remainder > 0) 512 - remainder else 0;
510-
};
511-
512-
var file_header = std.tar.output.Header.init();
513-
file_header.typeflag = .regular;
514-
try file_header.setPath(
515-
joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache),
516-
joined_path.sub_path,
517-
);
518-
try file_header.setSize(stat.size);
519-
try file_header.updateChecksum();
520-
try w.writeAll(std.mem.asBytes(&file_header));
521-
try w.writeFile(file);
522-
try w.writeByteNTimes(0, padding);
501+
archiver.prefix = joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache);
502+
try archiver.writeFile(joined_path.sub_path, file);
523503
}
524504

525505
// intentionally omitting the pointless trailer
526-
//try w.writeByteNTimes(0, 512 * 2);
506+
//try archiver.finish();
527507
try response.end();
528508
}
529509

lib/std/tar.zig

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const std = @import("std");
1919
const assert = std.debug.assert;
2020
const testing = std.testing;
2121

22-
pub const output = @import("tar/output.zig");
22+
pub const writer = @import("tar/writer.zig").writer;
2323

2424
/// Provide this to receive detailed error messages.
2525
/// When this is provided, some errors which would otherwise be returned
@@ -355,13 +355,13 @@ pub fn Iterator(comptime ReaderType: type) type {
355355
}
356356

357357
// Writes file content to writer.
358-
pub fn writeAll(self: File, writer: anytype) !void {
358+
pub fn writeAll(self: File, out_writer: anytype) !void {
359359
var buffer: [4096]u8 = undefined;
360360

361361
while (self.unread_bytes.* > 0) {
362362
const buf = buffer[0..@min(buffer.len, self.unread_bytes.*)];
363363
try self.parent_reader.readNoEof(buf);
364-
try writer.writeAll(buf);
364+
try out_writer.writeAll(buf);
365365
self.unread_bytes.* -= buf.len;
366366
}
367367
}

lib/std/tar/output.zig

-85
This file was deleted.

0 commit comments

Comments
 (0)