diff options
Diffstat (limited to 'tools/embed_zig_sources.zig')
| -rw-r--r-- | tools/embed_zig_sources.zig | 177 |
1 files changed, 0 insertions, 177 deletions
diff --git a/tools/embed_zig_sources.zig b/tools/embed_zig_sources.zig deleted file mode 100644 index 91fd128f..00000000 --- a/tools/embed_zig_sources.zig +++ /dev/null @@ -1,177 +0,0 @@ -//! Build-time generator for the web LOOK filesystem. -//! -//! Prefer Git's tracked-plus-untracked/nonignored view so a new source works in -//! the browser before it is staged, while ignored build/cache/vendor files can -//! never leak into the bundle. A source archive should still be buildable -//! without Git, so a conservative directory walk is the fallback. -const std = @import("std"); - -pub fn main(init: std.process.Init) !void { - const gpa = init.gpa; - const io = init.io; - const args = try init.minimal.args.toSlice(init.arena.allocator()); - if (args.len != 3) return error.BadArgs; - - const root = args[1]; - const output_path = args[2]; - const paths = (try gitWorkingTreeZigFiles(gpa, io, root)) orelse try walkedZigFiles(gpa, io, root); - defer { - for (paths) |path| gpa.free(path); - gpa.free(paths); - } - std.mem.sort([]const u8, paths, {}, lessThanPath); - - var generated: std.Io.Writer.Allocating = .init(gpa); - defer generated.deinit(); - try generated.writer.writeAll( - \\// Generated by tools/embed_zig_sources.zig. Do not edit. - \\pub const Source = struct { path: []const u8, contents: []const u8 }; - \\pub const all = [_]Source{ - \\ - ); - - for (paths) |path| { - const full_path = try std.Io.Dir.path.join(gpa, &.{ root, path }); - defer gpa.free(full_path); - // Cached entries can still name a file moved or deleted without - // staging it—an ordinary mid-edit state, and in a jj-colocated repo the - // normal one until the change is exported. A path no longer on disk is - // simply not a source to embed; failing the whole web build over it - // means an unrelated refactor breaks a shell it never touched. - const contents = std.Io.Dir.cwd().readFileAlloc(io, full_path, gpa, .limited(64 * 1024 * 1024)) catch |err| switch (err) { - error.FileNotFound => continue, - else => return err, - }; - defer gpa.free(contents); - try generated.writer.print(" .{{ .path = \"{f}\", .contents = \"{f}\" }},\n", .{ - std.zig.fmtString(path), - std.zig.fmtString(contents), - }); - } - try generated.writer.writeAll("};\n"); - - const output = if (std.Io.Dir.path.isAbsolute(output_path)) - try std.Io.Dir.createFileAbsolute(io, output_path, .{}) - else - try std.Io.Dir.cwd().createFile(io, output_path, .{}); - defer output.close(io); - try output.writeStreamingAll(io, generated.written()); -} - -/// Returns null only when Git cannot supply the working-tree source list. -/// `--cached --others --exclude-standard` includes a newly-created module -/// before it is staged but retains Git's ignore rules. Contents are read later; -/// Git supplies only the path filter, never historical blobs. -fn gitWorkingTreeZigFiles( - gpa: std.mem.Allocator, - io: std.Io, - root: []const u8, -) !?[][]const u8 { - const result = std.process.run(gpa, io, .{ - .argv = &.{ - "git", "-C", root, "ls-files", "-z", - "--cached", "--others", "--exclude-standard", "--", "*.zig", - }, - .stdout_limit = .limited(16 * 1024 * 1024), - .stderr_limit = .limited(1024 * 1024), - }) catch return null; - defer gpa.free(result.stdout); - defer gpa.free(result.stderr); - switch (result.term) { - .exited => |code| if (code != 0) return null, - else => return null, - } - - var count: usize = 0; - var count_it = std.mem.splitScalar(u8, result.stdout, 0); - while (count_it.next()) |raw_path| { - if (raw_path.len == 0 or !std.mem.endsWith(u8, raw_path, ".zig")) continue; - count += 1; - } - - const paths = try gpa.alloc([]const u8, count); - errdefer gpa.free(paths); - var index: usize = 0; - errdefer for (paths[0..index]) |path| gpa.free(path); - var it = std.mem.splitScalar(u8, result.stdout, 0); - while (it.next()) |raw_path| { - if (raw_path.len == 0 or !std.mem.endsWith(u8, raw_path, ".zig")) continue; - paths[index] = try normalizedPath(gpa, raw_path); - index += 1; - } - std.debug.assert(index == paths.len); - return paths; -} - -fn walkedZigFiles( - gpa: std.mem.Allocator, - io: std.Io, - root: []const u8, -) ![][]const u8 { - var count: usize = 0; - { - var dir = if (std.Io.Dir.path.isAbsolute(root)) - try std.Io.Dir.openDirAbsolute(io, root, .{ .iterate = true }) - else - try std.Io.Dir.cwd().openDir(io, root, .{ .iterate = true }); - defer dir.close(io); - var walker = try dir.walk(gpa); - defer walker.deinit(); - - while (try walker.next(io)) |entry| { - if (entry.kind == .directory and ignoredFallbackDir(entry.path)) { - walker.leave(io); - continue; - } - if ((entry.kind != .file and entry.kind != .sym_link) or !std.mem.endsWith(u8, entry.path, ".zig")) continue; - count += 1; - } - } - - const paths = try gpa.alloc([]const u8, count); - errdefer gpa.free(paths); - var index: usize = 0; - errdefer for (paths[0..index]) |path| gpa.free(path); - var dir = if (std.Io.Dir.path.isAbsolute(root)) - try std.Io.Dir.openDirAbsolute(io, root, .{ .iterate = true }) - else - try std.Io.Dir.cwd().openDir(io, root, .{ .iterate = true }); - defer dir.close(io); - var walker = try dir.walk(gpa); - defer walker.deinit(); - - while (try walker.next(io)) |entry| { - if (entry.kind == .directory and ignoredFallbackDir(entry.path)) { - walker.leave(io); - continue; - } - if ((entry.kind != .file and entry.kind != .sym_link) or !std.mem.endsWith(u8, entry.path, ".zig")) continue; - paths[index] = try normalizedPath(gpa, entry.path); - index += 1; - } - std.debug.assert(index == paths.len); - return paths; -} - -fn ignoredFallbackDir(path: []const u8) bool { - var parts = std.mem.tokenizeAny(u8, path, "/\\"); - while (parts.next()) |part| { - if (std.mem.eql(u8, part, ".git") or - std.mem.eql(u8, part, ".zig-cache") or - std.mem.eql(u8, part, "zig-cache") or - std.mem.eql(u8, part, "zig-out") or - std.mem.eql(u8, part, "zig-pkg")) return true; - } - return false; -} - -fn normalizedPath(gpa: std.mem.Allocator, path: []const u8) ![]u8 { - const copy = try gpa.dupe(u8, path); - if (std.Io.Dir.path.sep != '/') - std.mem.replaceScalar(u8, copy, std.Io.Dir.path.sep, '/'); - return copy; -} - -fn lessThanPath(_: void, a: []const u8, b: []const u8) bool { - return std.mem.order(u8, a, b) == .lt; -} |
