Check the file size, mtime, and permissions of source_path and dest_path. If
they are equal, does nothing. Otherwise, atomically copies source_path to
dest_path, creating the parent directory hierarchy as needed. The
destination file gains the mtime, atime, and permissions of the source file so
that the next call to updateFile will not need a copy.
Returns the previous status of the file before updating.
pub fn updateFile(
source_dir: Dir,
io: Io,
source_path: []const u8,
dest_dir: Dir,
/// If directories in this path do not exist, they are created.
dest_path: []const u8,
options: CopyFileOptions,
) !PrevStatus
pub fn updateFile(
source_dir: Dir,
io: Io,
source_path: []const u8,
dest_dir: Dir,
/// If directories in this path do not exist, they are created.
dest_path: []const u8,
options: CopyFileOptions,
) !PrevStatus {
var src_file = try source_dir.openFile(io, source_path, .{});
defer src_file.close(io);
const src_stat = try src_file.stat(io);
const actual_permissions = options.permissions orelse src_stat.permissions;
check_dest_stat: {
const dest_stat = blk: {
var dest_file = dest_dir.openFile(io, dest_path, .{}) catch |err| switch (err) {
error.FileNotFound => break :check_dest_stat,
else => |e| return e,
};
defer dest_file.close(io);
break :blk try dest_file.stat(io);
};
if (src_stat.size == dest_stat.size and
src_stat.mtime.nanoseconds == dest_stat.mtime.nanoseconds and
actual_permissions == dest_stat.permissions)
{
return .fresh;
}
}
var atomic_file = try dest_dir.createFileAtomic(io, dest_path, .{
.permissions = actual_permissions,
.make_path = true,
.replace = true,
});
defer atomic_file.deinit(io);
var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available.
var file_writer = atomic_file.file.writer(io, &buffer);
var src_reader: File.Reader = .initSize(src_file, io, &.{}, src_stat.size);
const dest_writer = &file_writer.interface;
_ = dest_writer.sendFileAll(&src_reader, .unlimited) catch |err| switch (err) {
error.ReadFailed => return src_reader.err.?,
error.WriteFailed => return file_writer.err.?,
};
try file_writer.flush();
try file_writer.file.setTimestamps(io, .{
.access_timestamp = .init(src_stat.atime),
.modify_timestamp = .init(src_stat.mtime),
});
try atomic_file.replace(io);
return .stale;
}