const std = @import("std"); const Makko = @import("Makko.zig"); const Data = @import("Data.zig"); const helper = @import("helper.zig"); const network = @import("network.zig"); const MakkoWatcher = zm.Watcher(*Makko); const zm = @import("zigmon"); var mutex: std.Thread.Mutex = .{}; var server: *network.Server = undefined; fn onTemplateChange( watcher: MakkoWatcher, _: zm.Action, path: []const u8, _: ?[]const u8, ) void { const makko = watcher.data; const log = makko.log; if (std.mem.containsAtLeast(u8, path, 1, "..")) return; if (std.mem.containsAtLeast(u8, path, 1, std.fs.path.sep_str)) return; // it's a folder or within a folder, we don't care about this file. if (helper.isDir(makko.paths.template, path)) return; mutex.lock(); defer mutex.unlock(); makko.loadTemplates() catch |err| log.warn("Could not reload templates! ({})", .{err}); const basename = std.fs.path.basename(path); if (std.mem.eql(u8, basename, "feed.html")) makko.generateFeeds() catch |err| log.warn("Could not generate feeds! ({})", .{err}); if (std.mem.eql(u8, basename, "post.html")) { var pass = makko.automaticPass() catch |err| log.fatal("Could not regenerate! ({})", .{err}); defer pass.deinit(); pass.runCallbacks() catch |err| log.warn("Could not run callbacks! ({})", .{err}); } makko.storeDatabase() catch |err| log.fatal("Could not store database!!! ({})", .{err}); server.handler.update(); } fn onPostChange( watcher: MakkoWatcher, action: zm.Action, path: []const u8, _: ?[]const u8, ) void { const makko = watcher.data; const log = makko.log; if (std.mem.containsAtLeast(u8, path, 1, "..")) return; mutex.lock(); defer mutex.unlock(); var pass = makko.newPass(); defer pass.deinit(); if (action == .delete) { pass.deleteFileByPath(path) catch |err| log.fatal("Could not delete file! ({})", .{err}); makko.generateFeeds() catch |err| log.warn("Could not generate feeds! ({})", .{err}); return; } if (helper.isDir(makko.paths.source, path)) { makko.paths.output.makeDir(path) catch {}; return; } const maybe_visibility = pass.processFile(path) catch |err| blk: { log.err("Could not process file! ({})", .{err}); break :blk .secret; }; if (maybe_visibility) |visibility| if (visibility == .public) makko.generateFeeds() catch |err| log.warn("Could not generate feeds! ({})", .{err}); pass.runCallbacks() catch |err| log.warn("Could not run callbacks! ({})", .{err}); makko.storeDatabase() catch |err| log.fatal("Could not store database!!! ({})", .{err}); server.handler.update(); } pub fn live(public: bool, port: u16, makko: *Makko) !void { makko.progress.end(); makko.progress = .{ .index = .none }; try makko.paths.root.setAsCwd(); zm.init(); defer zm.deinit(); const template_path_z = try makko.allocator.dupeZ( u8, makko.origin.value.paths.templates, ); defer makko.allocator.free(template_path_z); var template_watcher: MakkoWatcher = .{ .data = makko, .root = template_path_z, .on_change = onTemplateChange, }; try template_watcher.watch(); defer template_watcher.unwatch(); const source_path_z = try makko.allocator.dupeZ( u8, makko.origin.value.paths.source, ); defer makko.allocator.free(source_path_z); var blog_watcher: MakkoWatcher = .{ .data = makko, .root = source_path_z, .on_change = onPostChange, }; try blog_watcher.watch(); defer blog_watcher.unwatch(); var srv = try network.init(makko, public, port); server = &srv; _ = try srv.listen(); defer srv.deinit(); defer srv.stop(); _ = try std.io.getStdOut().write("\n"); }