update-patches.zig 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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 ANSWERS_PATH = "answers";
  9. const PATCHES_PATH = "patches/patches";
  10. // Heals all the exercises.
  11. fn heal(alloc: Allocator) !void {
  12. try cwd.makePath(ANSWERS_PATH);
  13. const org_path = try cwd.realpathAlloc(alloc, EXERCISES_PATH);
  14. const patch_path = try cwd.realpathAlloc(alloc, PATCHES_PATH);
  15. const healed_path = try cwd.realpathAlloc(alloc, ANSWERS_PATH);
  16. var idir = try cwd.openIterableDir(EXERCISES_PATH, Dir.OpenDirOptions{});
  17. defer idir.close();
  18. var it = idir.iterate();
  19. while (try it.next()) |entry| {
  20. // create filenames
  21. const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
  22. const patch_file = try concat(alloc, &.{ patch_path, "/", try patch_name(alloc, entry.name) });
  23. // patch the file
  24. const result = try std.ChildProcess.exec(.{
  25. .allocator = alloc,
  26. .argv = &.{ "patch", "-i", patch_file, "-o", healed_file, entry.name },
  27. .cwd = org_path,
  28. });
  29. print("{s}", .{result.stderr});
  30. }
  31. }
  32. // Creates new patch files for every exercise
  33. fn update(alloc: Allocator) !void {
  34. const org_path = try cwd.realpathAlloc(alloc, EXERCISES_PATH);
  35. const healed_path = try cwd.realpathAlloc(alloc, ANSWERS_PATH);
  36. const patch_path = try cwd.realpathAlloc(alloc, PATCHES_PATH);
  37. var idir = try cwd.openIterableDir(EXERCISES_PATH, Dir.OpenDirOptions{});
  38. defer idir.close();
  39. var it = idir.iterate();
  40. while (try it.next()) |entry| {
  41. // create diff
  42. const org_file = try concat(alloc, &.{ org_path, "/", entry.name });
  43. const healed_file = try concat(alloc, &.{ healed_path, "/", entry.name });
  44. const result = try std.ChildProcess.exec(.{
  45. .allocator = alloc,
  46. .argv = &.{ "diff", org_file, healed_file },
  47. });
  48. std.debug.assert(result.term.Exited == 1);
  49. // write diff to file
  50. const patch_file = try concat(alloc, &.{ patch_path, "/", try patch_name(alloc, entry.name) });
  51. var file = try std.fs.cwd().createFile(patch_file, .{ .read = false });
  52. defer file.close();
  53. try file.writer().print("{s}", .{result.stdout});
  54. }
  55. }
  56. fn concat(alloc: Allocator, slices: []const string) !string {
  57. const buf = try std.mem.concat(alloc, u8, slices);
  58. return buf;
  59. }
  60. fn patch_name(alloc: Allocator, path: string) !string {
  61. var filename = path;
  62. const index = std.mem.lastIndexOfScalar(u8, path, '.') orelse return path;
  63. if (index > 0) filename = path[0..index];
  64. return try concat(alloc, &.{ filename, ".patch" });
  65. }
  66. pub fn main() !void {
  67. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  68. defer arena.deinit();
  69. const alloc = arena.allocator();
  70. try heal(alloc);
  71. try update(alloc);
  72. }