mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
build runner compiling
This commit is contained in:
parent
716b4489be
commit
f3be721785
@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(
|
||||
src_builder: *Build,
|
||||
asking_step: ?*Step,
|
||||
) anyerror!void {
|
||||
var buffered_writer = stderr.unbufferedWriter();
|
||||
var buffered_writer = stderr.writer().unbuffered();
|
||||
const w = &buffered_writer;
|
||||
try w.print(
|
||||
\\getPath() was called on a GeneratedFile that wasn't built yet.
|
||||
|
||||
@ -522,7 +522,8 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
|
||||
|
||||
var cwd_cache: ?[]const u8 = null;
|
||||
|
||||
var archiver = std.tar.writer(response.writer());
|
||||
var response_writer = response.writer().unbuffered();
|
||||
var archiver: std.tar.Writer = .{ .underlying_writer = &response_writer };
|
||||
|
||||
for (deduped_paths) |joined_path| {
|
||||
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
|
||||
|
||||
@ -287,7 +287,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
|
||||
|
||||
/// For debugging purposes, prints identifying information about this Step.
|
||||
pub fn dump(step: *Step, file: std.fs.File) void {
|
||||
var bw = file.unbufferedWriter();
|
||||
var bw = file.writer().unbuffered();
|
||||
const tty_config = std.io.tty.detectConfig(file);
|
||||
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
||||
bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
|
||||
|
||||
@ -55,14 +55,14 @@ fn printType(
|
||||
switch (T) {
|
||||
[]const []const u8 => {
|
||||
if (name) |payload| {
|
||||
try out.print(gpa, "pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
|
||||
try out.print(gpa, "pub const {f}: []const []const u8 = ", .{std.zig.fmtId(payload)});
|
||||
}
|
||||
|
||||
try out.appendSlice(gpa, "&[_][]const u8{\n");
|
||||
|
||||
for (value) |slice| {
|
||||
try out.appendNTimes(gpa, ' ', indent);
|
||||
try out.print(gpa, " \"{}\",\n", .{std.zig.fmtEscapes(slice)});
|
||||
try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtEscapes(slice)});
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
@ -75,7 +75,9 @@ fn printType(
|
||||
},
|
||||
[]const u8 => {
|
||||
if (name) |some| {
|
||||
try out.print(gpa, "pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
|
||||
try out.print(gpa, "pub const {f}: []const u8 = \"{f}\";", .{
|
||||
std.zig.fmtId(some), std.zig.fmtEscapes(value),
|
||||
});
|
||||
} else {
|
||||
try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
|
||||
}
|
||||
@ -293,7 +295,7 @@ fn printEnum(
|
||||
|
||||
inline for (val.fields) |field| {
|
||||
try out.appendNTimes(gpa, ' ', indent);
|
||||
try out.print(gpa, " {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
|
||||
try out.print(gpa, " {fp} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
|
||||
}
|
||||
|
||||
if (!val.is_exhaustive) {
|
||||
|
||||
@ -305,8 +305,8 @@ pub const Os = struct {
|
||||
ver: WindowsVersion,
|
||||
comptime fmt_str: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
writer: *std.io.BufferedWriter,
|
||||
) anyerror!void {
|
||||
const maybe_name = std.enums.tagName(WindowsVersion, ver);
|
||||
if (comptime std.mem.eql(u8, fmt_str, "s")) {
|
||||
if (maybe_name) |name|
|
||||
|
||||
@ -212,7 +212,7 @@ pub fn unlockStdErr() void {
|
||||
/// in fact unbuffered and does not need to be flushed.
|
||||
pub fn lockStdErr2() std.io.BufferedWriter {
|
||||
std.Progress.lockStdErr();
|
||||
return io.getStdErr().unbufferedWriter();
|
||||
return io.getStdErr().writer().unbuffered();
|
||||
}
|
||||
|
||||
/// Print to stderr, unbuffered, and silently returning on failure. Intended
|
||||
@ -1468,7 +1468,7 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
|
||||
}
|
||||
|
||||
fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
|
||||
var stderr = io.getStdErr().unbufferedWriter();
|
||||
var stderr = io.getStdErr().writer().unbuffered();
|
||||
_ = switch (sig) {
|
||||
posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
|
||||
// x86_64 doesn't have a full 64-bit virtual address space.
|
||||
@ -1564,7 +1564,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
|
||||
}
|
||||
|
||||
fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
|
||||
var stderr = io.getStdErr().unbufferedWriter();
|
||||
var stderr = io.getStdErr().writer().unbuffered();
|
||||
_ = switch (msg) {
|
||||
0 => stderr.print("{s}\n", .{label.?}),
|
||||
1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
|
||||
|
||||
@ -853,7 +853,7 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
|
||||
/// Count the characters needed for format.
|
||||
pub fn count(comptime fmt: []const u8, args: anytype) u64 {
|
||||
var counting_writer: std.io.CountingWriter = .{ .child_writer = std.io.null_writer };
|
||||
var bw = counting_writer.unbufferedWriter();
|
||||
var bw = counting_writer.writer().unbuffered();
|
||||
bw.print(fmt, args) catch unreachable;
|
||||
return counting_writer.bytes_written;
|
||||
}
|
||||
|
||||
@ -1602,13 +1602,6 @@ pub fn writer(file: File) std.io.Writer {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unbufferedWriter(file: File) std.io.BufferedWriter {
|
||||
return .{
|
||||
.buffer = &.{},
|
||||
.unbuffered_writer = writer(file),
|
||||
};
|
||||
}
|
||||
|
||||
const interface = struct {
|
||||
/// Number of slices to store on the stack, when trying to send as many byte
|
||||
/// vectors through the underlying write calls as possible.
|
||||
|
||||
@ -620,13 +620,14 @@ pub fn printValue(
|
||||
}
|
||||
|
||||
if (std.meta.hasMethod(T, "format")) {
|
||||
if (fmt.len == 0) {
|
||||
// @deprecated()
|
||||
// After 0.14.0 is tagged, uncomment this next line:
|
||||
//@compileError("ambiguous format string; specify {f} to call print method, or {any} to skip it");
|
||||
return value.format(fmt, options, bw);
|
||||
} else if (fmt[0] == 'f') {
|
||||
if (fmt.len > 0 and fmt[0] == 'f') {
|
||||
return value.format(fmt[1..], options, bw);
|
||||
} else {
|
||||
//@deprecated();
|
||||
// After 0.14.0 is tagged, uncomment this next line:
|
||||
//@compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
|
||||
//and then delete the `hasMethod` condition
|
||||
return value.format(fmt, options, bw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,13 +22,6 @@ pub fn writer(cw: *CountingWriter) Writer {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unbufferedWriter(cw: *CountingWriter) std.io.BufferedWriter {
|
||||
return .{
|
||||
.buffer = &.{},
|
||||
.unbuffered_writer = writer(cw),
|
||||
};
|
||||
}
|
||||
|
||||
fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
|
||||
const cw: *CountingWriter = @alignCast(@ptrCast(context));
|
||||
const n = try cw.child_writer.writeSplat(data, splat);
|
||||
@ -52,7 +45,7 @@ fn passthru_writeFile(
|
||||
|
||||
test CountingWriter {
|
||||
var cw: CountingWriter = .{ .child_writer = std.io.null_writer };
|
||||
var bw = cw.unbufferedWriter();
|
||||
var bw = cw.writer().unbuffered();
|
||||
const bytes = "yay";
|
||||
try bw.writeAll(bytes);
|
||||
try testing.expect(cw.bytes_written == bytes.len);
|
||||
|
||||
@ -86,12 +86,6 @@ pub fn writeAll(w: Writer, bytes: []const u8) anyerror!void {
|
||||
while (index < bytes.len) index += try w.vtable.writeSplat(w.context, &.{bytes[index..]}, 1);
|
||||
}
|
||||
|
||||
///// Directly calls `writeAll` many times to render the formatted text. To
|
||||
///// enable buffering, call `std.io.BufferedWriter.print` instead.
|
||||
//pub fn unbufferedPrint(w: Writer, comptime format: []const u8, args: anytype) anyerror!void {
|
||||
// return std.fmt.format(w, format, args);
|
||||
//}
|
||||
|
||||
/// The `data` parameter is mutable because this function needs to mutate the
|
||||
/// fields in order to handle partial writes from `VTable.writev`.
|
||||
pub fn writevAll(w: Writer, data: [][]const u8) anyerror!void {
|
||||
@ -106,3 +100,10 @@ pub fn writevAll(w: Writer, data: [][]const u8) anyerror!void {
|
||||
data[i] = data[i][n..];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unbuffered(w: Writer) std.io.BufferedWriter {
|
||||
return .{
|
||||
.buffer = &.{},
|
||||
.unbuffered_writer = w,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1004,7 +1004,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
|
||||
|
||||
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
||||
const file: File = .{ .handle = fd };
|
||||
var bw = file.unbufferedWriter();
|
||||
var bw = file.writer().unbuffered();
|
||||
bw.writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
|
||||
pub const writer = @import("tar/writer.zig").writer;
|
||||
pub const Writer = @import("tar/Writer.zig");
|
||||
|
||||
/// Provide this to receive detailed error messages.
|
||||
/// When this is provided, some errors which would otherwise be returned
|
||||
@ -604,7 +604,7 @@ fn PaxIterator(comptime ReaderType: type) type {
|
||||
}
|
||||
|
||||
fn readUntil(self: *Self, delimiter: u8) ![]const u8 {
|
||||
var fbs = std.io.fixedBufferStream(&self.scratch);
|
||||
var fbs: std.io.FixedBufferStream = .{ .buffer = &self.scratch };
|
||||
try self.reader.streamUntilDelimiter(fbs.writer(), delimiter, null);
|
||||
return fbs.getWritten();
|
||||
}
|
||||
@ -855,7 +855,7 @@ test PaxIterator {
|
||||
|
||||
test {
|
||||
_ = @import("tar/test.zig");
|
||||
_ = @import("tar/writer.zig");
|
||||
_ = Writer;
|
||||
_ = Diagnostics;
|
||||
}
|
||||
|
||||
|
||||
@ -1,177 +1,176 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const Writer = @This();
|
||||
|
||||
pub const Writer = struct {
|
||||
const block_size = @sizeOf(Header);
|
||||
const empty_block: [block_size]u8 = [_]u8{0} ** block_size;
|
||||
const block_size = @sizeOf(Header);
|
||||
const empty_block: [block_size]u8 = [_]u8{0} ** block_size;
|
||||
|
||||
/// Options for writing file/dir/link. If left empty 0o664 is used for
|
||||
/// file mode and current time for mtime.
|
||||
pub const Options = struct {
|
||||
/// File system permission mode.
|
||||
mode: u32 = 0,
|
||||
/// File system modification time.
|
||||
mtime: u64 = 0,
|
||||
};
|
||||
const Self = @This();
|
||||
/// Options for writing file/dir/link. If left empty 0o664 is used for
|
||||
/// file mode and current time for mtime.
|
||||
pub const Options = struct {
|
||||
/// File system permission mode.
|
||||
mode: u32 = 0,
|
||||
/// File system modification time.
|
||||
mtime: u64 = 0,
|
||||
};
|
||||
const Self = @This();
|
||||
|
||||
underlying_writer: *std.io.BufferedWriter,
|
||||
prefix: []const u8 = "",
|
||||
mtime_now: u64 = 0,
|
||||
underlying_writer: *std.io.BufferedWriter,
|
||||
prefix: []const u8 = "",
|
||||
mtime_now: u64 = 0,
|
||||
|
||||
/// Sets prefix for all other write* method paths.
|
||||
pub fn setRoot(self: *Self, root: []const u8) !void {
|
||||
if (root.len > 0)
|
||||
try self.writeDir(root, .{});
|
||||
/// Sets prefix for all other write* method paths.
|
||||
pub fn setRoot(self: *Self, root: []const u8) !void {
|
||||
if (root.len > 0)
|
||||
try self.writeDir(root, .{});
|
||||
|
||||
self.prefix = root;
|
||||
self.prefix = root;
|
||||
}
|
||||
|
||||
/// Writes directory.
|
||||
pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.directory, sub_path, "", 0, opt);
|
||||
}
|
||||
|
||||
/// Writes file system file.
|
||||
pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
|
||||
const stat = try file.stat();
|
||||
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
|
||||
|
||||
var header = Header{};
|
||||
try self.setPath(&header, sub_path);
|
||||
try header.setSize(stat.size);
|
||||
try header.setMtime(mtime);
|
||||
try header.write(self.underlying_writer);
|
||||
|
||||
try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) });
|
||||
try self.writePadding(stat.size);
|
||||
}
|
||||
|
||||
/// Writes file reading file content from `reader`. Number of bytes in
|
||||
/// reader must be equal to `size`.
|
||||
pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void {
|
||||
try self.writeHeader(.regular, sub_path, "", @intCast(size), opt);
|
||||
|
||||
var counting_reader = std.io.countingReader(reader);
|
||||
var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
|
||||
try fifo.pump(counting_reader.reader(), self.underlying_writer);
|
||||
if (counting_reader.bytes_read != size) return error.WrongReaderSize;
|
||||
try self.writePadding(size);
|
||||
}
|
||||
|
||||
/// Writes file using bytes buffer `content` for size and file content.
|
||||
pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt);
|
||||
try self.underlying_writer.writeAll(content);
|
||||
try self.writePadding(content.len);
|
||||
}
|
||||
|
||||
/// Writes symlink.
|
||||
pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt);
|
||||
}
|
||||
|
||||
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
|
||||
/// default for entry mode .
|
||||
pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void {
|
||||
switch (entry.kind) {
|
||||
.directory => {
|
||||
try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) });
|
||||
},
|
||||
.file => {
|
||||
var file = try entry.dir.openFile(entry.basename, .{});
|
||||
defer file.close();
|
||||
try self.writeFile(entry.path, file);
|
||||
},
|
||||
.sym_link => {
|
||||
var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
|
||||
try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
|
||||
},
|
||||
else => {
|
||||
return error.UnsupportedWalkerEntryKind;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes directory.
|
||||
pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.directory, sub_path, "", 0, opt);
|
||||
}
|
||||
|
||||
/// Writes file system file.
|
||||
pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
|
||||
const stat = try file.stat();
|
||||
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
|
||||
|
||||
var header = Header{};
|
||||
try self.setPath(&header, sub_path);
|
||||
try header.setSize(stat.size);
|
||||
try header.setMtime(mtime);
|
||||
try header.write(self.underlying_writer);
|
||||
|
||||
try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) });
|
||||
try self.writePadding(stat.size);
|
||||
}
|
||||
|
||||
/// Writes file reading file content from `reader`. Number of bytes in
|
||||
/// reader must be equal to `size`.
|
||||
pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void {
|
||||
try self.writeHeader(.regular, sub_path, "", @intCast(size), opt);
|
||||
|
||||
var counting_reader = std.io.countingReader(reader);
|
||||
var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
|
||||
try fifo.pump(counting_reader.reader(), self.underlying_writer);
|
||||
if (counting_reader.bytes_read != size) return error.WrongReaderSize;
|
||||
try self.writePadding(size);
|
||||
}
|
||||
|
||||
/// Writes file using bytes buffer `content` for size and file content.
|
||||
pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt);
|
||||
try self.underlying_writer.writeAll(content);
|
||||
try self.writePadding(content.len);
|
||||
}
|
||||
|
||||
/// Writes symlink.
|
||||
pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void {
|
||||
try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt);
|
||||
}
|
||||
|
||||
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
|
||||
/// default for entry mode .
|
||||
pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void {
|
||||
switch (entry.kind) {
|
||||
.directory => {
|
||||
try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) });
|
||||
},
|
||||
.file => {
|
||||
var file = try entry.dir.openFile(entry.basename, .{});
|
||||
defer file.close();
|
||||
try self.writeFile(entry.path, file);
|
||||
},
|
||||
.sym_link => {
|
||||
var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
|
||||
try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
|
||||
},
|
||||
else => {
|
||||
return error.UnsupportedWalkerEntryKind;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn writeHeader(
|
||||
self: *Self,
|
||||
typeflag: Header.FileType,
|
||||
sub_path: []const u8,
|
||||
link_name: []const u8,
|
||||
size: u64,
|
||||
opt: Options,
|
||||
) !void {
|
||||
var header = Header.init(typeflag);
|
||||
try self.setPath(&header, sub_path);
|
||||
try header.setSize(size);
|
||||
try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow());
|
||||
if (opt.mode != 0)
|
||||
try header.setMode(opt.mode);
|
||||
if (typeflag == .symbolic_link)
|
||||
header.setLinkname(link_name) catch |err| switch (err) {
|
||||
error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}),
|
||||
else => return err,
|
||||
};
|
||||
try header.write(self.underlying_writer);
|
||||
}
|
||||
|
||||
fn mtimeNow(self: *Self) u64 {
|
||||
if (self.mtime_now == 0)
|
||||
self.mtime_now = @intCast(std.time.timestamp());
|
||||
return self.mtime_now;
|
||||
}
|
||||
|
||||
fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 {
|
||||
const stat = try entry.dir.statFile(entry.basename);
|
||||
return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
|
||||
}
|
||||
|
||||
/// Writes path in posix header, if don't fit (in name+prefix; 100+155
|
||||
/// bytes) writes it in gnu extended header.
|
||||
fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void {
|
||||
header.setPath(self.prefix, sub_path) catch |err| switch (err) {
|
||||
error.NameTooLong => {
|
||||
// write extended header
|
||||
const buffers: []const []const u8 = if (self.prefix.len == 0)
|
||||
&.{sub_path}
|
||||
else
|
||||
&.{ self.prefix, "/", sub_path };
|
||||
try self.writeExtendedHeader(.gnu_long_name, buffers);
|
||||
},
|
||||
fn writeHeader(
|
||||
self: *Self,
|
||||
typeflag: Header.FileType,
|
||||
sub_path: []const u8,
|
||||
link_name: []const u8,
|
||||
size: u64,
|
||||
opt: Options,
|
||||
) !void {
|
||||
var header = Header.init(typeflag);
|
||||
try self.setPath(&header, sub_path);
|
||||
try header.setSize(size);
|
||||
try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow());
|
||||
if (opt.mode != 0)
|
||||
try header.setMode(opt.mode);
|
||||
if (typeflag == .symbolic_link)
|
||||
header.setLinkname(link_name) catch |err| switch (err) {
|
||||
error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}),
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
try header.write(self.underlying_writer);
|
||||
}
|
||||
|
||||
/// Writes gnu extended header: gnu_long_name or gnu_long_link.
|
||||
fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void {
|
||||
var len: usize = 0;
|
||||
for (buffers) |buf|
|
||||
len += buf.len;
|
||||
fn mtimeNow(self: *Self) u64 {
|
||||
if (self.mtime_now == 0)
|
||||
self.mtime_now = @intCast(std.time.timestamp());
|
||||
return self.mtime_now;
|
||||
}
|
||||
|
||||
var header = Header.init(typeflag);
|
||||
try header.setSize(len);
|
||||
try header.write(self.underlying_writer);
|
||||
for (buffers) |buf|
|
||||
try self.underlying_writer.writeAll(buf);
|
||||
try self.writePadding(len);
|
||||
}
|
||||
fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 {
|
||||
const stat = try entry.dir.statFile(entry.basename);
|
||||
return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
|
||||
}
|
||||
|
||||
fn writePadding(self: *Self, bytes: u64) !void {
|
||||
const pos: usize = @intCast(bytes % block_size);
|
||||
if (pos == 0) return;
|
||||
try self.underlying_writer.writeAll(empty_block[pos..]);
|
||||
}
|
||||
/// Writes path in posix header, if don't fit (in name+prefix; 100+155
|
||||
/// bytes) writes it in gnu extended header.
|
||||
fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void {
|
||||
header.setPath(self.prefix, sub_path) catch |err| switch (err) {
|
||||
error.NameTooLong => {
|
||||
// write extended header
|
||||
const buffers: []const []const u8 = if (self.prefix.len == 0)
|
||||
&.{sub_path}
|
||||
else
|
||||
&.{ self.prefix, "/", sub_path };
|
||||
try self.writeExtendedHeader(.gnu_long_name, buffers);
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
|
||||
/// Tar should finish with two zero blocks, but 'reasonable system must
|
||||
/// not assume that such a block exists when reading an archive' (from
|
||||
/// reference). In practice it is safe to skip this finish.
|
||||
pub fn finish(self: *Self) !void {
|
||||
try self.underlying_writer.writeAll(&empty_block);
|
||||
try self.underlying_writer.writeAll(&empty_block);
|
||||
}
|
||||
};
|
||||
/// Writes gnu extended header: gnu_long_name or gnu_long_link.
|
||||
fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void {
|
||||
var len: usize = 0;
|
||||
for (buffers) |buf|
|
||||
len += buf.len;
|
||||
|
||||
var header = Header.init(typeflag);
|
||||
try header.setSize(len);
|
||||
try header.write(self.underlying_writer);
|
||||
for (buffers) |buf|
|
||||
try self.underlying_writer.writeAll(buf);
|
||||
try self.writePadding(len);
|
||||
}
|
||||
|
||||
fn writePadding(self: *Self, bytes: u64) !void {
|
||||
const pos: usize = @intCast(bytes % block_size);
|
||||
if (pos == 0) return;
|
||||
try self.underlying_writer.writeAll(empty_block[pos..]);
|
||||
}
|
||||
|
||||
/// Tar should finish with two zero blocks, but 'reasonable system must
|
||||
/// not assume that such a block exists when reading an archive' (from
|
||||
/// reference). In practice it is safe to skip this finish.
|
||||
pub fn finish(self: *Self) !void {
|
||||
try self.underlying_writer.writeAll(&empty_block);
|
||||
try self.underlying_writer.writeAll(&empty_block);
|
||||
}
|
||||
|
||||
/// A struct that is exactly 512 bytes and matches tar file format. This is
|
||||
/// intended to be used for outputting tar files; for parsing there is
|
||||
@ -320,7 +319,7 @@ const Header = extern struct {
|
||||
assert(@sizeOf(Header) == 512);
|
||||
}
|
||||
|
||||
test setPath {
|
||||
test "setPath" {
|
||||
const cases = [_]struct {
|
||||
in: []const []const u8,
|
||||
out: []const []const u8,
|
||||
@ -416,7 +416,7 @@ fn formatId(
|
||||
bytes: []const u8,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.io.BufferedWriter,
|
||||
) !void {
|
||||
const allow_primitive, const allow_underscore = comptime parse_fmt: {
|
||||
var allow_primitive = false;
|
||||
|
||||
@ -194,7 +194,7 @@ fn renderErrorMessageToWriter(
|
||||
) anyerror!void {
|
||||
const ttyconf = options.ttyconf;
|
||||
var counting_writer: std.io.CountingWriter = .{ .child_writer = bw.writer() };
|
||||
var counting_bw = counting_writer.unbufferedWriter();
|
||||
var counting_bw = counting_writer.writer().unbuffered();
|
||||
const err_msg = eb.getErrorMessage(err_msg_index);
|
||||
if (err_msg.src_loc != .none) {
|
||||
const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user