Skip to content

Commit 87189e9

Browse files
feat(patch): implement patch system
- iterate dirs - diff exercise and solution file - write stdout to file - run entrypoint
1 parent ec75f87 commit 87189e9

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

src/cli/patch.zig

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const STD = @import("std");
2+
const CLI = @import("cli.zig");
3+
const STYLES = @import("styles.zig");
4+
5+
const PatchSystem = struct {
6+
list_of_exercises: STD.ArrayList([]const u8) = .empty,
7+
list_of_solutions: STD.ArrayList([]const u8) = .empty,
8+
};
9+
10+
fn iterateDirs(allocator: STD.mem.Allocator, patch_system: *PatchSystem) !void {
11+
patch_system.*.list_of_exercises = try CLI.iterateDirectory(allocator, .{
12+
.dir_path = "exercises",
13+
});
14+
15+
patch_system.*.list_of_solutions = try CLI.iterateDirectory(allocator, .{
16+
.dir_path = ".patches/solutions",
17+
});
18+
}
19+
20+
fn generatePatches(allocator: STD.mem.Allocator, patch_system: *PatchSystem) !void {
21+
for (patch_system.list_of_exercises.items, patch_system.list_of_solutions.items) |exercise, solution| {
22+
const BUFFER_SIZE = comptime STD.math.pow(usize, 2, 16);
23+
24+
var current_solution_filepath_iterator = STD.mem.splitAny(u8, solution, "/");
25+
var current_solution_filepath_list: STD.ArrayList([]const u8) = .empty;
26+
27+
while (current_solution_filepath_iterator.next()) |current_solution_filepath_slice_element| {
28+
try current_solution_filepath_list.append(allocator, current_solution_filepath_slice_element);
29+
}
30+
31+
const TOP_LEVEL_DIR = current_solution_filepath_list.items[0];
32+
const CHAPTER_DIR = current_solution_filepath_list.items[2];
33+
const SOLUTION_FILENAME = current_solution_filepath_list.items[3];
34+
35+
const OUTPUT_FILENAME = try STD.mem.replaceOwned(u8, allocator, SOLUTION_FILENAME, ".cpp", ".patch");
36+
37+
const OUTPUT_FILEPATH = try STD.fs.path.join(allocator, &[_][]const u8{ TOP_LEVEL_DIR, "patches", CHAPTER_DIR, OUTPUT_FILENAME });
38+
39+
STD.debug.print("diff {s} {s} --> {s}{s}{s}\n", .{
40+
exercise,
41+
solution,
42+
STYLES.ASCII_STYLES.underline,
43+
OUTPUT_FILEPATH,
44+
STYLES.ASCII_STYLES.clear_style,
45+
});
46+
47+
var process_args: STD.ArrayList([]const u8) = .empty;
48+
49+
try process_args.appendSlice(allocator, &[_][]const u8{ "diff", "-u", exercise, solution });
50+
var process = STD.process.Child.init(process_args.items, allocator);
51+
52+
process.stderr_behavior = .Pipe;
53+
process.stdout_behavior = .Pipe;
54+
55+
var process_stdout_buffer: STD.ArrayList(u8) = .empty;
56+
var process_stderr_buffer: STD.ArrayList(u8) = .empty;
57+
58+
process.spawn() catch {
59+
STD.debug.print("{s}Failed to generate patches!\n{s}", .{
60+
STYLES.ASCII_STYLES.red,
61+
STYLES.ASCII_STYLES.clear_style,
62+
});
63+
return;
64+
};
65+
66+
try process.collectOutput(allocator, &process_stdout_buffer, &process_stderr_buffer, BUFFER_SIZE);
67+
68+
try STD.fs.cwd().writeFile(.{ .sub_path = OUTPUT_FILEPATH, .data = process_stdout_buffer.items });
69+
}
70+
71+
STD.debug.print("\n{s}Generated patches -> {s}./patches/patches{s}\n", .{ STYLES.ASCII_STYLES.bold, STYLES.ASCII_STYLES.underline, STYLES.ASCII_STYLES.clear_style });
72+
}
73+
74+
// TODO: implement patch function
75+
pub fn patch() !void {}
76+
77+
pub fn run(allocator: STD.mem.Allocator) !void {
78+
STD.debug.print("{s}\n\n", .{CLI.ASCII_ART});
79+
80+
STD.debug.print("Creating patch system...\n", .{});
81+
const patch_system: *PatchSystem = try allocator.create(PatchSystem);
82+
defer allocator.destroy(patch_system);
83+
84+
STD.debug.print("Iterating exercises...\n", .{});
85+
try iterateDirs(allocator, patch_system);
86+
87+
STD.debug.print("Generating patches...\n", .{});
88+
try generatePatches(allocator, patch_system);
89+
}
90+

0 commit comments

Comments
 (0)