about summary refs log tree commit diff
path: root/src/fs.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs.zig')
-rw-r--r--src/fs.zig239
1 files changed, 0 insertions, 239 deletions
diff --git a/src/fs.zig b/src/fs.zig
deleted file mode 100644
index f139653..0000000
--- a/src/fs.zig
+++ /dev/null
@@ -1,239 +0,0 @@
-const std = @import("std");
-const c = @cImport({
-    @cInclude("stdlib.h");
-    @cInclude("time.h");
-});
-
-const exe = @import("exe.zig");
-
-const log = std.log.scoped(.fs);
-
-pub const FileSwapper = struct {
-    allocator: std.mem.Allocator,
-    target_path: []const u8,
-    tmp_path: []const u8,
-    tmp: std.fs.File,
-    swapped: *bool,
-
-    pub fn createAt(alloc: std.mem.Allocator, path: []const u8) !FileSwapper {
-        const target_dir = std.fs.path.dirname(path) orelse ".";
-        const target_name = std.fs.path.basename(path);
-
-        const tmp_name = try std.fmt.allocPrint(
-            alloc,
-            ".{s}",
-            .{target_name},
-        );
-        defer alloc.free(tmp_name);
-
-        const tmp_path = try std.fs.path.join(
-            alloc,
-            &.{ target_dir, tmp_name },
-        );
-
-        const f = try std.fs.cwd().createFile(tmp_path, .{});
-
-        const swapped = try alloc.create(bool);
-        swapped.* = false;
-
-        return .{
-            .allocator = alloc,
-            .target_path = path,
-            .tmp_path = tmp_path,
-            .tmp = f,
-            .swapped = swapped,
-        };
-    }
-
-    pub fn file(self: FileSwapper) std.fs.File {
-        return self.tmp;
-    }
-
-    pub fn writer(self: FileSwapper, buffer: []u8) std.fs.File.Writer {
-        return self.tmp.writer(buffer);
-    }
-
-    pub fn swap(self: FileSwapper) !void {
-        std.log.debug("swapping {s} -> {s}", .{ self.tmp_path, self.target_path });
-
-        // flush writes
-        self.tmp.sync() catch
-            @panic("sync tmp file");
-
-        // swap file into final location
-        // NOTE: the tmp fd is still valid after this
-        try std.fs.rename(
-            std.fs.cwd(),
-            self.tmp_path,
-            std.fs.cwd(),
-            self.target_path,
-        );
-
-        self.swapped.* = true;
-    }
-
-    pub fn close(self: FileSwapper) void {
-        var found = true;
-        std.fs.cwd().access(self.tmp_path, .{}) catch |e| switch (e) {
-            error.FileNotFound => found = false,
-            else => @panic("access tmp path"),
-        };
-
-        defer self.allocator.free(self.tmp_path);
-        defer self.allocator.destroy(self.swapped);
-        defer self.tmp.close();
-
-        if (found) {
-            const changed = diff(self.tmp_path, self.target_path) catch
-                @panic("failed to diff tmp and target file");
-
-            if (changed) {
-                self.swap() catch
-                    @panic("failed to swap target file");
-            } else {
-                log.debug("{s} no changes, skipping", .{ self.target_path });
-                std.posix.unlink(self.tmp_path) catch
-                    @panic("failed to cleanup tmp file");
-            }
-        }
-    }
-};
-
-pub fn replaceExtension(alloc: std.mem.Allocator, p: []const u8, new: []const u8) ![]const u8 {
-    const dirname = std.fs.path.dirname(p) orelse ".";
-    const basename = try stripExtension(std.fs.path.basename(p));
-    return try joinPathAndFilename(
-        alloc,
-        &.{dirname},
-        &.{ basename, ".", new },
-    );
-}
-
-// also trims off base paths
-pub fn stripExtension(path: []const u8) ![]const u8 {
-    const ext = std.fs.path.extension(path);
-    const ext_idx = std.mem.indexOfPosLinear(u8, path, 0, ext);
-    std.debug.assert(ext_idx != null);
-    return path[0..ext_idx.?];
-}
-
-pub fn joinPathAndFilename(alloc: std.mem.Allocator, paths: []const []const u8, filename_parts: []const []const u8) ![]const u8 {
-    var buf: [std.os.linux.PATH_MAX]u8 = undefined;
-    var fba = std.heap.FixedBufferAllocator.init(&buf);
-
-    const filename = try std.mem.concat(fba.allocator(), u8, filename_parts);
-
-    var p = try std.ArrayList([]const u8).initCapacity(fba.allocator(), paths.len + 1);
-    p.appendSliceAssumeCapacity(paths);
-    p.appendAssumeCapacity(filename);
-
-    std.debug.assert(paths.len + 1 == p.items.len);
-    return try std.fs.path.join(alloc, p.items);
-}
-
-// pub fn getGitTime(path: []const u8) !std.posix.timespec {
-//     var buf = std.mem.zeroes([12]u8);
-//
-//     var p = std.process.Child.init(
-//         &.{ "git", "log", "-1", "--pretty=format:%at", "-z", "--", path },
-//         std.heap.page_allocator,
-//     );
-//     p.stdout_behavior = .Pipe;
-//     try p.spawn();
-//     _ = try p.stdout.?.readAll(&buf);
-//     const result = try p.wait();
-//
-//     std.debug.assert(result == .Exited and result.Exited == 0);
-//
-//     // parse result as ulong
-//     const gitAuthorDate: c_ulong = c.strtoul(&buf, null, 10);
-//     if (gitAuthorDate == 0) return error.NoGitTime;
-//
-//     // calculate timespec
-//     return .{
-//         .sec = std.math.cast(isize, gitAuthorDate) orelse std.math.maxInt(isize),
-//         .nsec = 0,
-//     };
-// }
-
-pub fn getMtime(path: []const u8) !std.posix.timespec {
-    const fd = try std.fs.cwd().openFile(path, .{ .mode = .read_only });
-    defer fd.close();
-
-    const meta = try fd.stat();
-    const mtime = meta.mtime;
-
-    return .{
-        .sec = std.math.cast(isize, @divFloor(mtime, std.time.ns_per_s)) orelse std.math.maxInt(isize),
-        .nsec = std.math.cast(isize, @mod(mtime, std.time.ns_per_s)) orelse std.math.maxInt(isize),
-    };
-}
-
-pub fn getLastEdit(path: []const u8) !std.posix.timespec {
-    std.fs.cwd().access(path, .{}) catch |e| switch (e) {
-        error.FileNotFound => return .{
-            .sec = 0,
-            .nsec = 0,
-        },
-        else => return e,
-    };
-    return getMtime(path);
-}
-
-pub fn setMtime(path: []const u8, ts: std.posix.timespec) !void {
-    const fd = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
-    defer fd.close();
-
-    try std.posix.futimens(
-        fd.handle,
-        &[2]std.os.linux.timespec{ ts, ts },
-    );
-}
-
-// use libc strftime to format time string
-pub fn formatTimespec(alloc: std.mem.Allocator, timespec: std.posix.timespec, fmt: [*c]const u8) ![]const u8 {
-    const mtime_str = try alloc.alloc(u8, std.os.linux.PATH_MAX);
-    var tm: c.struct_tm = undefined;
-    _ = c.localtime_r(&timespec.sec, &tm);
-    const rc = c.strftime(
-        mtime_str.ptr,
-        mtime_str.len,
-        fmt,
-        &tm,
-    );
-    switch (std.posix.errno(rc)) {
-        .SUCCESS => {},
-        else => |err| return std.posix.unexpectedErrno(err),
-    }
-    return try alloc.realloc(mtime_str, rc);
-}
-
-pub fn diff(a: []const u8, b: []const u8) !bool {
-    std.fs.cwd().access(a, .{}) catch |e| switch (e) {
-        error.FileNotFound => return true,
-        else => return e,
-    };
-    std.fs.cwd().access(b, .{}) catch |e| switch (e) {
-        error.FileNotFound => return true,
-        else => return e,
-    };
-
-    var p = std.process.Child.init(&.{
-        "diff",
-        "-q",
-        a,
-        b,
-    }, std.heap.page_allocator);
-    p.stdin_behavior = .Close;
-    p.stderr_behavior = .Ignore;
-    p.stdout_behavior = .Ignore;
-    try p.spawn();
-    switch (try p.wait()) {
-        .Exited => |exit_code| switch (exit_code) {
-            0 => return false,
-            1 => return true,
-            else => return error.UnknownDiffError,
-        },
-        else => return error.UnknownDiffError,
-    }
-}