check-exercises.zig 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const std = @import("std");
  2. const print = std.debug.print;
  3. const string = []const u8;
  4. const cwd = std.fs.cwd();
  5. const Dir = std.fs.Dir;
  6. const Allocator = std.mem.Allocator;
  7. const EXERCISES_PATH = "exercises";
  8. const HEALED_PATH = "patches/healed";
  9. const TEMP_PATH = "patches/healed/tmp";
  10. const PATCHES_PATH = "patches/patches";
  11. // Heals all the exercises.
  12. fn heal(alloc: Allocator) !void {
  13. try cwd.makePath(HEALED_PATH);
  14. const org_path = try cwd.realpathAlloc(alloc, EXERCISES_PATH);
  15. const patch_path = try cwd.realpathAlloc(alloc, PATCHES_PATH);
  16. const healed_path = try cwd.realpathAlloc(alloc, HEALED_PATH);
  17. var idir = try cwd.openIterableDir(EXERCISES_PATH, Dir.OpenDirOptions{});
  18. defer idir.close();
  19. var it = idir.iterate();
  20. while (try it.next()) |entry| {
  21. // create filenames
  22. const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
  23. const patch_file = try concat(alloc, &.{ patch_path, "/", try patch_name(alloc, entry.name) });
  24. // patch file
  25. const result = try std.ChildProcess.exec(.{
  26. .allocator = alloc,
  27. .argv = &.{ "patch", "-i", patch_file, "-o", healed_file, entry.name },
  28. .cwd = org_path,
  29. });
  30. print("{s}", .{result.stderr});
  31. }
  32. }
  33. // Yields all the healed exercises that are not correctly formatted.
  34. fn check_healed(alloc: Allocator) !void {
  35. try cwd.makePath(TEMP_PATH);
  36. const temp_path = try cwd.realpathAlloc(alloc, TEMP_PATH);
  37. const healed_path = try cwd.realpathAlloc(alloc, HEALED_PATH);
  38. var idir = try cwd.openIterableDir(HEALED_PATH, Dir.OpenDirOptions{});
  39. defer idir.close();
  40. var it = idir.iterate();
  41. while (try it.next()) |entry| {
  42. // Check the healed file
  43. const result = try std.ChildProcess.exec(.{
  44. .allocator = alloc,
  45. .argv = &.{ "zig", "fmt", "--check", entry.name },
  46. .cwd = healed_path,
  47. });
  48. // Is there something to fix?
  49. if (result.stdout.len > 0) {
  50. const temp_file = try concat(alloc, &.{ temp_path, "/", entry.name });
  51. const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
  52. try std.fs.copyFileAbsolute(healed_file, temp_file, std.fs.CopyFileOptions{});
  53. // Formats the temp file
  54. _ = try std.ChildProcess.exec(.{
  55. .allocator = alloc,
  56. .argv = &.{ "zig", "fmt", entry.name },
  57. .cwd = temp_path,
  58. });
  59. // Show the differences
  60. const diff = try std.ChildProcess.exec(.{
  61. .allocator = alloc,
  62. .argv = &.{ "diff", "-c", healed_file, entry.name },
  63. .cwd = temp_path,
  64. });
  65. print("{s}", .{diff.stdout});
  66. try std.fs.deleteFileAbsolute(temp_file);
  67. }
  68. }
  69. }
  70. fn concat(alloc: Allocator, slices: []const string) !string {
  71. const buf = try std.mem.concat(alloc, u8, slices);
  72. return buf;
  73. }
  74. fn patch_name(alloc: Allocator, path: string) !string {
  75. var filename = path;
  76. const index = std.mem.lastIndexOfScalar(u8, path, '.') orelse return path;
  77. if (index > 0) filename = path[0..index];
  78. return try concat(alloc, &.{ filename, ".patch" });
  79. }
  80. pub fn main() !void {
  81. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  82. defer arena.deinit();
  83. const alloc = arena.allocator();
  84. try heal(alloc);
  85. try check_healed(alloc);
  86. }