Browse Source

replaced check-exercises.pu with check-exercises.zig

Chris Boesch 2 years ago
parent
commit
cffbbff8bd
2 changed files with 108 additions and 97 deletions
  1. 0 97
      tools/check-exercises.py
  2. 108 0
      tools/check-exercises.zig

+ 0 - 97
tools/check-exercises.py

@@ -1,97 +0,0 @@
-#!/usr/bin/env python
-
-import difflib
-import io
-import os
-import os.path
-import subprocess
-import sys
-
-
-IGNORE = subprocess.DEVNULL
-PIPE = subprocess.PIPE
-
-EXERCISES_PATH = "exercises"
-HEALED_PATH = "patches/healed"
-PATCHES_PATH = "patches/patches"
-
-
-# Heals all the exercises.
-def heal():
-    maketree(HEALED_PATH)
-
-    with os.scandir(EXERCISES_PATH) as it:
-        for entry in it:
-            name = entry.name
-
-            original_path = entry.path
-            patch_path = os.path.join(PATCHES_PATH, patch_name(name))
-            output_path = os.path.join(HEALED_PATH, name)
-
-            patch(original_path, patch_path, output_path)
-
-
-# Yields all the healed exercises that are not correctly formatted.
-def check_healed():
-    term = subprocess.run(
-        ["zig", "fmt", "--check", HEALED_PATH], stdout=PIPE, text=True
-    )
-    if term.stdout == "" and term.returncode != 0:
-        term.check_returncode()
-
-    stream = io.StringIO(term.stdout)
-    for line in stream:
-        yield line.strip()
-
-
-def main():
-    heal()
-
-    # Show the unified diff between the original example and the correctly
-    # formatted one.
-    for i, original in enumerate(check_healed()):
-        if i > 0:
-            print()
-
-        name = os.path.basename(original)
-        print(f"checking exercise {name}...\n")
-
-        from_file = open(original)
-        to_file = zig_fmt_file(original)
-
-        diff = difflib.unified_diff(
-            from_file.readlines(), to_file.readlines(), name, name + "-fmt"
-        )
-        sys.stderr.writelines(diff)
-
-
-def maketree(path):
-    return os.makedirs(path, exist_ok=True)
-
-
-# Returns path with the patch extension.
-def patch_name(path):
-    name, _ = os.path.splitext(path)
-
-    return name + ".patch"
-
-
-# Applies patch to original, and write the file to output.
-def patch(original, patch, output):
-    subprocess.run(
-        ["patch", "-i", patch, "-o", output, original], stdout=IGNORE, check=True
-    )
-
-
-# Formats the Zig file at path, and returns the possibly reformatted file as a
-# file object.
-def zig_fmt_file(path):
-    with open(path) as stdin:
-        term = subprocess.run(
-            ["zig", "fmt", "--stdin"], stdin=stdin, stdout=PIPE, check=True, text=True
-        )
-
-        return io.StringIO(term.stdout)
-
-
-main()

+ 108 - 0
tools/check-exercises.zig

@@ -0,0 +1,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);
+}