diff options
Diffstat (limited to '')
| -rw-r--r-- | src/exe.zig | 216 |
1 files changed, 0 insertions, 216 deletions
diff --git a/src/exe.zig b/src/exe.zig deleted file mode 100644 index ad3a7aa..0000000 --- a/src/exe.zig +++ /dev/null @@ -1,216 +0,0 @@ -const std = @import("std"); - -const fs = @import("fs.zig"); -const Context = @import("main.zig").Context; - -const log = std.log.scoped(.exe); - -pub fn WaitPool( - comptime T: type, - comptime worker: anytype, -) type { - return struct { - const Self = @This(); - - pub fn work(ctx: *Context, items: []const T, args: anytype) !void { - var wg: std.Thread.WaitGroup = undefined; - wg.reset(); - - var pool: std.Thread.Pool = undefined; - try pool.init(.{ - .n_jobs = (try std.Thread.getCpuCount()) - 1, - .allocator = ctx.allocator(), - }); - defer pool.deinit(); - - for (items) |*item| { - // the inline struct trick is a workardoun for Thread.Pool::spawn not - // accepting functions that can error: - // https://github.com/ziglang/zig/issues/18810 - try pool.spawn(struct { - fn func( - wwg: *std.Thread.WaitGroup, - wctx: *Context, - witem: *const T, - wargs: anytype, - ) void { - wwg.start(); - defer wwg.finish(); - - const result = @call( - .auto, - worker, - .{ wctx, witem.* } ++ wargs, - ); - - result catch |err| - std.log.err("worker failed with: {}", .{err}); - } - }.func, .{ &wg, ctx, item, args }); - } - - pool.waitAndWork(&wg); - } - }; -} - -pub fn runPandoc(ctx: *Context) !void { - ctx.generated.clearRetainingCapacity(); - - ctx.progress_start("Processing markdown files", true); - defer ctx.progress_end(); - - var md = try std.ArrayList([]const u8).initCapacity(ctx.allocator(), 1); - defer md.deinit(ctx.allocator()); - - // TODO: support more than one site - for (ctx.sites.getLast().pages.items) |p| - if (p.kind == .Markdown) try md.append(ctx.allocator(), p.path); - - // TODO: check if pandoc is installed and exit gracefully - try WaitPool( - []const u8, - pandocWorker, - ).work(ctx, md.items, .{}); - - log.info("Processed {d} markdown files.", .{md.items.len}); -} - -fn pandocWorker(ctx: *Context, page: []const u8) !void { - ctx.progress_start(page, true); - defer ctx.progress_end(); - - const source_path = try std.fs.path.join(ctx.allocator(), &.{ Context.params.PAGE_PATH, page }); - defer ctx.allocator().free(source_path); - const target_path = try fs.replaceExtension(ctx.allocator(), source_path, "htm"); - defer ctx.allocator().free(target_path); - - // get mtime of the source document - const mtime = try fs.getLastEdit(source_path); - const mtime_str = try fs.formatTimespec(ctx.allocator(), mtime, "%s"); - defer ctx.allocator().free(mtime_str); - - const f = try fs.FileSwapper.createAt(ctx.allocator(), target_path); - - var buffer: [1024]u8 = undefined; - var w = f.writer(&buffer); - - // open new scope to close the file swapper when we're done writing - try w.interface.print( - \\<!-- Generated file, you may edit and discard {s} :) --> - \\ - , - .{page}, - ); - - // make pandoc runs reproducable - var env_map = std.process.EnvMap.init(ctx.allocator()); - defer env_map.deinit(); - try env_map.put("SOURCE_DATE_EPOCH", mtime_str); - - try captureStdout(ctx, &.{ - Context.params.PANDOC, - "--from", - "markdown+wikilinks_title_after_pipe+autolink_bare_uris", - "--to", - "html5", - "--lua-filter", - // TODO: embed the preproc filter - Context.params.PANDOC_PREPROC, - "--strip-comments", - "--output=-", - source_path, - }, &env_map, &w.interface); - - f.close(); - - if (f.swapped.*) { - try ctx.generated.append( - ctx.allocator(), - try ctx.allocator().dupe(u8, target_path), - ); - } -} - -pub fn commit(ctx: *Context, paths: []const []const u8) !void { - // skip early if we have nothing to do - if (paths.len == 0) return; - - // skip if staging is unclean - shell(ctx, - \\git diff --cached --exit-code - , null) catch |e| switch (e) { - error.NonZeroExitCode => return, - else => return e, - }; - - for (paths) |f| { - const cmd = try std.fmt.allocPrint(ctx.allocator(), "git add {s}", .{f}); - defer ctx.allocator().free(cmd); - - try shell(ctx, cmd, null); - } - - try shell(ctx, - \\GIT_COMMITTER_NAME=rbc git commit --quiet --message=* - , null); - - try shell(ctx, - \\git show --stat --pretty=oneline - , null); - - log.info("Committed {d} paths", .{paths.len}); -} - -pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.process.EnvMap, w: *std.Io.Writer) !void { - const command = try std.mem.join(ctx.allocator(), " ", argv); - defer ctx.allocator().free(command); - const label = try std.fmt.allocPrint(ctx.allocator(), "running {s}", .{command}); - defer ctx.allocator().free(label); - - ctx.progress_start(label, true); - defer ctx.progress_end(); - - log.debug("running {s}", .{command}); - - var p = std.process.Child.init(argv, std.heap.page_allocator); - p.stdin_behavior = .Ignore; - p.stdout_behavior = .Pipe; - p.stderr_behavior = .Ignore; - p.progress_node = ctx.progress_nodes.getLast(); - p.env_map = env_map; - - try p.spawn(); - - var buffer: [1024]u8 = undefined; - var r = p.stdout.?.readerStreaming(&buffer); - - _ = try w.sendFileAll(&r, .unlimited); - try w.flush(); - - const result = try p.wait(); - if (result.Exited != 0) return error.NonZeroExitCode; -} - -pub fn shell(ctx: *Context, command: []const u8, env_map: ?*std.process.EnvMap) !void { - const label = try std.fmt.allocPrint(ctx.allocator(), "running {s}", .{command}); - defer ctx.allocator().free(label); - - ctx.progress_start(label, true); - defer ctx.progress_end(); - - var p = std.process.Child.init(&.{ - "sh", - "-c", - command, - }, std.heap.page_allocator); - - p.stdout_behavior = .Inherit; - p.stderr_behavior = .Inherit; - p.progress_node = ctx.progress_nodes.getLast(); - p.env_map = env_map; - - try p.spawn(); - const result = try p.wait(); - if (result.Exited != 0) return error.NonZeroExitCode; -} |