Socialify

Folder ..

Viewing check-exercises.zig
108 lines (86 loc) • 3.4 KB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
const std = @import("std");
const print = std.debug.print;
const string = []const u8;

const cwd = std.fs.cwd();
const Dir = std.fs.Dir;
const Allocator = std.mem.Allocator;

const EXERCISES_PATH = "exercises";
const HEALED_PATH = "patches/healed";
const TEMP_PATH = "patches/healed/tmp";
const PATCHES_PATH = "patches/patches";

// Heals all the exercises.
fn heal(alloc: Allocator) !void {
    try cwd.makePath(HEALED_PATH);

    const org_path = try cwd.realpathAlloc(alloc, EXERCISES_PATH);
    const patch_path = try cwd.realpathAlloc(alloc, PATCHES_PATH);
    const healed_path = try cwd.realpathAlloc(alloc, HEALED_PATH);

    var idir = try cwd.openIterableDir(EXERCISES_PATH, Dir.OpenDirOptions{});
    defer idir.close();

    var it = idir.iterate();
    while (try it.next()) |entry| {

        // create filenames
        const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
        const patch_file = try concat(alloc, &.{ patch_path, "/", try patch_name(alloc, entry.name) });

        // patch file
        const result = try std.ChildProcess.exec(.{
            .allocator = alloc,
            .argv = &.{ "patch", "-i", patch_file, "-o", healed_file, entry.name },
            .cwd = org_path,
        });

        print("{s}", .{result.stderr});
    }
}

// Yields all the healed exercises that are not correctly formatted.
fn check_healed(alloc: Allocator) !void {
    try cwd.makePath(TEMP_PATH);

    const temp_path = try cwd.realpathAlloc(alloc, TEMP_PATH);
    const healed_path = try cwd.realpathAlloc(alloc, HEALED_PATH);

    var idir = try cwd.openIterableDir(HEALED_PATH, Dir.OpenDirOptions{});
    defer idir.close();

    var it = idir.iterate();
    while (try it.next()) |entry| {

        // Check the healed file
        const result = try std.ChildProcess.exec(.{
            .allocator = alloc,
            .argv = &.{ "zig", "fmt", "--check", entry.name },
            .cwd = healed_path,
        });

        // Is there something to fix?
        if (result.stdout.len > 0) {
            const temp_file = try concat(alloc, &.{ temp_path, "/", entry.name });
            const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
            try std.fs.copyFileAbsolute(healed_file, temp_file, std.fs.CopyFileOptions{});

            // Formats the temp file
            _ = try std.ChildProcess.exec(.{
                .allocator = alloc,
                .argv = &.{ "zig", "fmt", entry.name },
                .cwd = temp_path,
            });

            // Show the differences
            const diff = try std.ChildProcess.exec(.{
                .allocator = alloc,
                .argv = &.{ "diff", "-c", healed_file, entry.name },
                .cwd = temp_path,
            });

            print("{s}", .{diff.stdout});
            try std.fs.deleteFileAbsolute(temp_file);
        }
    }
}

fn concat(alloc: Allocator, slices: []const string) !string {
    const buf = try std.mem.concat(alloc, u8, slices);
    return buf;
}

fn patch_name(alloc: Allocator, path: string) !string {
    var filename = path;
    const index = std.mem.lastIndexOfScalar(u8, path, '.') orelse return path;
    if (index > 0) filename = path[0..index];
    return try concat(alloc, &.{ filename, ".patch" });
}

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const alloc = arena.allocator();

    try heal(alloc);
    try check_healed(alloc);
}