diff --git a/.gitignore b/.gitignore index 53a6184..0fa4230 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /answers/ /patches/healed/ /output/ +.progress.txt # Leave this in here for older zig versions /zig-cache/ diff --git a/README.md b/README.md index f478944..c884f21 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,11 @@ zig build -Dn=19 -l ... ``` +To reset the progress (have it run all the exercises that have already been completed): +``` +zig build -Dreset +``` + ## What's Covered The primary goal for Ziglings is to cover the core Zig language. diff --git a/build.zig b/build.zig index c8f26fd..3b753ee 100644 --- a/build.zig +++ b/build.zig @@ -120,6 +120,8 @@ pub const logo = \\ ; +const progress_filename = ".progress.txt"; + pub fn build(b: *Build) !void { if (!validate_exercises()) std.process.exit(2); @@ -162,6 +164,7 @@ pub fn build(b: *Build) !void { const exno: ?usize = b.option(usize, "n", "Select exercise"); const rand: ?bool = b.option(bool, "random", "Select random exercise"); const start: ?usize = b.option(usize, "s", "Start at exercise"); + const reset: ?bool = b.option(bool, "reset", "Reset exercise progress"); const sep = std.fs.path.sep_str; const healed_path = if (override_healed_path) |path| @@ -242,17 +245,62 @@ pub fn build(b: *Build) !void { return; } + if (reset) |_| { + std.fs.cwd().deleteFile(progress_filename) catch |err| { + switch (err) { + std.fs.Dir.DeleteFileError.FileNotFound => {}, + else => { + print("Unable to remove progress file, Error: {}\n", .{err}); + return err; + }, + } + }; + + print("Progress reset, {s} removed.\n", .{progress_filename}); + std.process.exit(0); + } + // Normal build mode: verifies all exercises according to the recommended // order. const ziglings_step = b.step("ziglings", "Check all ziglings"); b.default_step = ziglings_step; var prev_step = &header_step.step; - for (exercises) |ex| { - const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); - verify_stepn.step.dependOn(prev_step); - prev_step = &verify_stepn.step; + var starting_exercise: u32 = 0; + + if (std.fs.cwd().openFile(progress_filename, .{})) |progress_file| { + defer progress_file.close(); + + const progress_file_size = try progress_file.getEndPos(); + + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + const contents = try progress_file.readToEndAlloc(allocator, progress_file_size); + defer allocator.free(contents); + + starting_exercise = try std.fmt.parseInt(u32, contents, 10); + } else |err| { + switch (err) { + + std.fs.File.OpenError.FileNotFound => { + // This is fine, may be the first time tests are run or progress have been reset + }, + else => { + print("Unable to open {s}: {}\n", .{progress_filename, err}); + return err; + }, + } + } + + for (exercises) |ex| { + if (starting_exercise < ex.number()) { + const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); + verify_stepn.step.dependOn(prev_step); + + prev_step = &verify_stepn.step; + } } ziglings_step.dependOn(prev_step); @@ -403,6 +451,18 @@ const ZiglingStep = struct { , .{ red, reset, exercise_output, red, reset, output, red, reset }); } + const progress = try std.fmt.allocPrint(b.allocator, "{d}", .{self.exercise.number()}); + defer b.allocator.free(progress); + + const file = try std.fs.cwd().createFile( + progress_filename, + .{ .read = true, .truncate = true }, + ); + defer file.close(); + + try file.writeAll(progress); + try file.sync(); + print("{s}PASSED:\n{s}{s}\n\n", .{ green_text, output, reset_text }); } @@ -970,6 +1030,7 @@ const exercises = [_]Exercise{ .{ .main_file = "074_comptime9.zig", .output = "My llama value is 2.", + .skip = true, }, .{ .main_file = "075_quiz8.zig", diff --git a/patches/eowyn.sh b/patches/eowyn.sh index 8cac450..afc2732 100755 --- a/patches/eowyn.sh +++ b/patches/eowyn.sh @@ -12,6 +12,12 @@ # using the patches in this directory and convey them # to convalesce in the healed directory. # +delete_progress() { + progress_file=".progress.txt" + if [ -f $progress_file ]; then + rm $progress_file + fi +} set -e # We check ourselves before we wreck ourselves. @@ -23,9 +29,12 @@ fi # Which version we have? echo "Zig version" $(zig version) -echo "Eowyn version 23.10.5.1, let's try our magic power." +echo "Eowyn version 25.1.9, let's try our magic power." echo "" +# Remove progress file +delete_progress + # Create directory of healing if it doesn't already exist. mkdir -p patches/healed @@ -54,3 +63,6 @@ zig fmt --check patches/healed # Test the healed exercises. May the compiler have mercy upon us. zig build -Dhealed + +# Remove progress file again +delete_progress