mirror of
https://github.com/marlersoft/win32json
synced 2026-06-21 13:57:33 +00:00
initial sync branch implementation
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.zig-cache/
|
||||
zig-out/
|
||||
/generate-branch/
|
||||
@@ -0,0 +1,164 @@
|
||||
const std = @import("std");
|
||||
const Build = std.Build;
|
||||
|
||||
const version = "25.0.28-preview";
|
||||
|
||||
pub fn build(b: *Build) !void {
|
||||
const sync_step = b.step("sync", "Sync the generate/main branches");
|
||||
b.default_step = sync_step;
|
||||
|
||||
const nofetch = b.option(bool, "nofetch", "disable fetching the generate branch on every build") orelse false;
|
||||
|
||||
const desc_line_prefix = [_]u8{' '} ** 31;
|
||||
const sha_file = blk: {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "fetchgenerate",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/fetchgenerate.zig"),
|
||||
.target = b.graph.host,
|
||||
}),
|
||||
});
|
||||
const run = b.addRunArtifact(exe);
|
||||
run.has_side_effects = if (nofetch) false else true;
|
||||
run.addDirectoryArg(b.path("generate-branch"));
|
||||
const sha_file = run.addOutputFileArg("generate-sha");
|
||||
b.step("fetchgenerate", ("Fetches the generate branch in 'generate-branch'\n" ++ desc_line_prefix ++
|
||||
"and stores its sha in a file for other\n" ++ desc_line_prefix ++
|
||||
"steps to use as an input.")).dependOn(&run.step);
|
||||
break :blk sha_file;
|
||||
};
|
||||
|
||||
{
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "sync",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/sync.zig"),
|
||||
.target = b.graph.host,
|
||||
}),
|
||||
});
|
||||
const run = b.addRunArtifact(exe);
|
||||
run.addFileArg(sha_file);
|
||||
sync_step.dependOn(&run.step);
|
||||
}
|
||||
// TODO: default step clones/updates a copy of the "generate" branch
|
||||
// a copy of the repo
|
||||
// into a subdirectory (work/
|
||||
|
||||
// const metadata_nupkg_file = blk: {
|
||||
// const download_winmd_nupkg = b.addSystemCommand(&.{
|
||||
// "curl",
|
||||
// "https://www.nuget.org/api/v2/package/Microsoft.Windows.SDK.Win32Metadata/" ++ version,
|
||||
// "--location",
|
||||
// "--output",
|
||||
// });
|
||||
// break :blk download_winmd_nupkg.addOutputFileArg("win32metadata.nupkg");
|
||||
// };
|
||||
|
||||
// const metadata_nupkg_out = blk: {
|
||||
// const zipcmdline = b.dependency("zipcmdline", .{
|
||||
// .target = b.graph.host,
|
||||
// });
|
||||
// const unzip_exe = zipcmdline.artifact("unzip");
|
||||
// const unzip_metadata = b.addRunArtifact(unzip_exe);
|
||||
// unzip_metadata.addFileArg(metadata_nupkg_file);
|
||||
// unzip_metadata.addArg("-d");
|
||||
// break :blk unzip_metadata.addOutputDirectoryArg("nupkg");
|
||||
// };
|
||||
|
||||
// const winmd = metadata_nupkg_out.path(b, "Windows.Win32.winmd");
|
||||
// b.step(
|
||||
// "show-winmd",
|
||||
// "Print the winmd file path in the cache",
|
||||
// ).dependOn(
|
||||
// &PrintLazyPath.create(b, winmd).step,
|
||||
// );
|
||||
|
||||
// const gen_step = b.step("gen", "Generate JSON files (in .zig-cache)");
|
||||
|
||||
// const winmd_dep = b.dependency("winmd", .{});
|
||||
// const gen_out_dir = blk: {
|
||||
// const exe = b.addExecutable(.{
|
||||
// .name = "genjson",
|
||||
// .root_module = b.createModule(.{
|
||||
// .root_source_file = b.path("src/genjson.zig"),
|
||||
// .target = b.graph.host,
|
||||
// }),
|
||||
// });
|
||||
// exe.root_module.addImport("winmd", winmd_dep.module("winmd"));
|
||||
// const run = b.addRunArtifact(exe);
|
||||
// run.addFileArg(winmd);
|
||||
// const out_dir = run.addOutputDirectoryArg(".");
|
||||
// gen_step.dependOn(&run.step);
|
||||
// break :blk out_dir;
|
||||
// };
|
||||
|
||||
// {
|
||||
// // we can't use b.installDirectory because we need to make sure we delete
|
||||
// // all existing files before installing the new ones in case JSON files are removed
|
||||
// // b.installDirectory(.{
|
||||
// // .source_dir = gen_out_dir,
|
||||
// // .install_dir = .prefix,
|
||||
// // .install_subdir = ".",
|
||||
// // });
|
||||
// const install_exe = b.addExecutable(.{
|
||||
// .name = "install",
|
||||
// .root_module = b.createModule(.{
|
||||
// .root_source_file = b.path("src/install.zig"),
|
||||
// .target = b.graph.host,
|
||||
// }),
|
||||
// });
|
||||
// const install = b.addRunArtifact(install_exe);
|
||||
// install.addDirectoryArg(gen_out_dir);
|
||||
// install.addArg(b.pathResolve(&.{ b.build_root.path.?, "win32json", "api" }));
|
||||
// b.getInstallStep().dependOn(&install.step);
|
||||
// }
|
||||
|
||||
// const test_step = b.step("test", "Run all the tests");
|
||||
// {
|
||||
// const validate_exe = b.addExecutable(.{
|
||||
// .name = "validate",
|
||||
// .root_module = b.createModule(.{
|
||||
// .root_source_file = b.path("src/validate.zig"),
|
||||
// .target = b.graph.host,
|
||||
// .optimize = .Debug,
|
||||
// }),
|
||||
// });
|
||||
// const validate = b.addRunArtifact(validate_exe);
|
||||
// validate.addDirectoryArg(gen_out_dir);
|
||||
// validate.expectExitCode(0);
|
||||
// test_step.dependOn(&validate.step);
|
||||
// }
|
||||
}
|
||||
|
||||
// const PrintLazyPath = struct {
|
||||
// step: std.Build.Step,
|
||||
// lazy_path: Build.LazyPath,
|
||||
// pub fn create(
|
||||
// b: *Build,
|
||||
// lazy_path: Build.LazyPath,
|
||||
// ) *PrintLazyPath {
|
||||
// const print = b.allocator.create(PrintLazyPath) catch unreachable;
|
||||
// print.* = .{
|
||||
// .step = std.Build.Step.init(.{
|
||||
// .id = .custom,
|
||||
// .name = "print the given lazy path",
|
||||
// .owner = b,
|
||||
// .makeFn = make,
|
||||
// }),
|
||||
// .lazy_path = lazy_path,
|
||||
// };
|
||||
// lazy_path.addStepDependencies(&print.step);
|
||||
// return print;
|
||||
// }
|
||||
// fn make(step: *std.Build.Step, opt: std.Build.Step.MakeOptions) !void {
|
||||
// _ = opt;
|
||||
// const print: *PrintLazyPath = @fieldParentPtr("step", step);
|
||||
// var write_buf: [1024]u8 = undefined;
|
||||
// var stdout = std.fs.File.stdout().writer(&write_buf);
|
||||
// try stdout.interface.print(
|
||||
// "{s}\n",
|
||||
// .{print.lazy_path.getPath(step.owner)},
|
||||
// );
|
||||
// try stdout.interface.flush();
|
||||
// }
|
||||
// };
|
||||
@@ -0,0 +1,22 @@
|
||||
.{
|
||||
.name = .generatewin32json,
|
||||
.fingerprint = 0xfd7a77ded32ab056,
|
||||
.version = "0.0.0",
|
||||
.zig_version = "0.15.2",
|
||||
.minimum_zig_version = "0.15.0",
|
||||
.dependencies = .{
|
||||
.zipcmdline = .{
|
||||
.url = "git+https://github.com/marler8997/zipcmdline#a6de65875023c52d2f56f21a31c6487266f8105f",
|
||||
.hash = "zipcmdline-0.0.0-DFii07hmAwCFNhtMpml64Pj_hr8kN4WesClygZErQHsk",
|
||||
},
|
||||
.winmd = .{
|
||||
.url = "git+https://github.com/marler8997/winmd-zig#d0d8daff01b4fb1a6324c79a855c34ced5bbc8d2",
|
||||
.hash = "winmd-0.0.0-2QIrG4MpAQCCh0ReC0jZKAps9Frn3jbbR--W7szyGAOS",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
pub fn run(
|
||||
allocator: std.mem.Allocator,
|
||||
name: []const u8,
|
||||
argv: []const []const u8,
|
||||
) !void {
|
||||
var child = std.process.Child.init(argv, allocator);
|
||||
std.log.info("{f}", .{fmtArgv(child.argv)});
|
||||
try child.spawn();
|
||||
const term = try child.wait();
|
||||
if (childProcFailed(term)) {
|
||||
errExit("{s} {f}", .{ name, fmtTerm(term) });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn childProcFailed(term: std.process.Child.Term) bool {
|
||||
return switch (term) {
|
||||
.Exited => |code| code != 0,
|
||||
.Signal => true,
|
||||
.Stopped => true,
|
||||
.Unknown => true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fmtArgv(argv: []const []const u8) FormatArgv {
|
||||
return .{ .argv = argv };
|
||||
}
|
||||
const FormatArgv = struct {
|
||||
argv: []const []const u8,
|
||||
pub fn format(self: @This(), writer: *std.Io.Writer) error{WriteFailed}!void {
|
||||
var prefix: []const u8 = "";
|
||||
for (self.argv) |arg| {
|
||||
try writer.print("{s}{s}", .{ prefix, arg });
|
||||
prefix = " ";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn fmtTerm(term: std.process.Child.Term) FormatTerm {
|
||||
return .{ .term = term };
|
||||
}
|
||||
const FormatTerm = struct {
|
||||
term: std.process.Child.Term,
|
||||
pub fn format(self: @This(), writer: *std.Io.Writer) error{WriteFailed}!void {
|
||||
switch (self.term) {
|
||||
.Exited => |code| try writer.print("exited with code {}", .{code}),
|
||||
.Signal => |sig| try writer.print("exited with signal {}", .{sig}),
|
||||
.Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),
|
||||
.Unknown => |sig| try writer.print("terminated abnormally with signal {}", .{sig}),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn makeRepo(path: []const u8) !void {
|
||||
std.fs.cwd().access(path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => try gitInit(path),
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
fn gitInit(repo: []const u8) !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const tmp_repo = try std.mem.concat(allocator, u8, &.{ repo, ".initializing" });
|
||||
defer allocator.free(tmp_repo);
|
||||
try std.fs.cwd().deleteTree(tmp_repo);
|
||||
try std.fs.cwd().makeDir(tmp_repo);
|
||||
try run(allocator, "git init", &.{
|
||||
"git",
|
||||
"-C",
|
||||
tmp_repo,
|
||||
"init",
|
||||
});
|
||||
try std.fs.cwd().rename(tmp_repo, repo);
|
||||
}
|
||||
|
||||
pub fn readSha(sha_file: []const u8) !union(enum) {
|
||||
invalid: []const u8,
|
||||
good: [40]u8,
|
||||
} {
|
||||
var buffer: [41]u8 = undefined;
|
||||
var out_file = std.fs.cwd().openFile(sha_file, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => return .{ .invalid = "file not found" },
|
||||
else => |e| return e,
|
||||
};
|
||||
defer out_file.close();
|
||||
const len = try out_file.readAll(&buffer);
|
||||
if (len < 40) return .{ .invalid = "file too small" };
|
||||
if (len > 40) return .{ .invalid = "file too big" };
|
||||
return .{ .good = buffer[0..40].* };
|
||||
}
|
||||
|
||||
pub fn errExit(comptime fmt: []const u8, args: anytype) noreturn {
|
||||
std.log.err(fmt, args);
|
||||
std.process.exit(0xff);
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
@@ -0,0 +1,93 @@
|
||||
pub fn main() !u8 {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
const allocator = arena.allocator();
|
||||
const all_args = try std.process.argsAlloc(allocator);
|
||||
// don't care about freeing args
|
||||
|
||||
const cmd_args = all_args[1..];
|
||||
if (cmd_args.len != 2) {
|
||||
std.log.err("expected 2 cmdline arguments but got {}", .{cmd_args.len});
|
||||
return 1;
|
||||
}
|
||||
const gen_repo = cmd_args[0];
|
||||
const out_file_path = cmd_args[1];
|
||||
|
||||
try common.makeRepo(gen_repo);
|
||||
|
||||
const repo_url = "https://github.com/marlersoft/win32json";
|
||||
try common.run(allocator, "git fetch", &.{
|
||||
"git",
|
||||
"-C",
|
||||
gen_repo,
|
||||
"fetch",
|
||||
repo_url,
|
||||
"generate",
|
||||
});
|
||||
|
||||
const latest_sha = blk: {
|
||||
const argv = [_][]const u8{
|
||||
"git",
|
||||
"-C",
|
||||
gen_repo,
|
||||
"rev-parse",
|
||||
"FETCH_HEAD",
|
||||
};
|
||||
std.log.info("{f}", .{common.fmtArgv(&argv)});
|
||||
const result = try std.process.Child.run(.{
|
||||
.allocator = allocator,
|
||||
.argv = &argv,
|
||||
});
|
||||
// don't free stdout, we're using it
|
||||
//defer allocator.free(result.stdout);
|
||||
defer allocator.free(result.stderr);
|
||||
if (result.stderr.len > 0) {
|
||||
var fw = std.fs.File.stderr().writer(&.{});
|
||||
try fw.interface.writeAll(result.stderr);
|
||||
}
|
||||
if (common.childProcFailed(result.term))
|
||||
errExit("git rev-parse {f}", .{common.fmtTerm(result.term)});
|
||||
break :blk std.mem.trimRight(u8, result.stdout, "\r\n");
|
||||
};
|
||||
if (latest_sha.len != 40) errExit(
|
||||
"expected sha from git rev-parse to be 40 characters but got {}: '{s}'",
|
||||
.{ latest_sha.len, latest_sha },
|
||||
);
|
||||
std.log.info("latest generate sha: {s}", .{latest_sha});
|
||||
|
||||
switch (try common.readSha(out_file_path)) {
|
||||
.invalid => |reason| {
|
||||
std.log.info("existing generate sha: invalid: {s}", .{reason});
|
||||
},
|
||||
.good => |existing_sha| {
|
||||
std.log.info("existing generate sha: {s}", .{existing_sha});
|
||||
if (std.mem.eql(u8, &existing_sha, latest_sha)) {
|
||||
std.log.info("status: already up-to-date", .{});
|
||||
return 0;
|
||||
}
|
||||
std.log.info("status: needs update", .{});
|
||||
},
|
||||
}
|
||||
|
||||
{
|
||||
var file = try std.fs.cwd().createFile(out_file_path, .{});
|
||||
defer file.close();
|
||||
var fw = file.writer(&.{});
|
||||
try fw.interface.writeAll(latest_sha);
|
||||
}
|
||||
|
||||
// sanity check
|
||||
switch (try common.readSha(out_file_path)) {
|
||||
.invalid => |reason| errExit("can't read sha after writing it: {s}", .{reason}),
|
||||
.good => |sha_from_file| if (!std.mem.eql(u8, &sha_from_file, latest_sha)) errExit(
|
||||
"sha changed to '{s}'",
|
||||
.{sha_from_file},
|
||||
),
|
||||
}
|
||||
std.log.info("{s}", .{out_file_path});
|
||||
return 0;
|
||||
}
|
||||
|
||||
const errExit = common.errExit;
|
||||
|
||||
const std = @import("std");
|
||||
const common = @import("common.zig");
|
||||
@@ -0,0 +1,38 @@
|
||||
pub fn main() !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const all_args = try std.process.argsAlloc(allocator);
|
||||
// don't care about freeing args
|
||||
|
||||
const cmd_args = all_args[1..];
|
||||
if (cmd_args.len != 1) {
|
||||
std.log.err("expected 1 cmdline argument but got {}", .{cmd_args.len});
|
||||
std.process.exit(0xff);
|
||||
}
|
||||
const generate_sha_file_path = cmd_args[0];
|
||||
// const gen_repo = cmd_args[0];
|
||||
// const main_sha_file_path = cmd_args[1];
|
||||
// const releases_file_path = cmd_args[2];
|
||||
// const zigwin32_repo = cmd_args[3];
|
||||
// const clean_arg = cmd_args[4];
|
||||
|
||||
// const do_clean = if (std.mem.eql(u8, clean_arg, "noclean"))
|
||||
// false
|
||||
// else if (std.mem.eql(u8, clean_arg, "clean"))
|
||||
// true
|
||||
// else
|
||||
// fatal("unexpected clean cmdline argument '{s}'", .{clean_arg});
|
||||
|
||||
const generate_sha = switch (try common.readSha(generate_sha_file_path)) {
|
||||
.invalid => |reason| errExit("read sha from '{s}' failed: {s}", .{ generate_sha_file_path, reason }),
|
||||
.good => |sha| sha,
|
||||
};
|
||||
std.log.info("generate branch sha: {s}", .{&generate_sha});
|
||||
@panic("todo");
|
||||
}
|
||||
|
||||
const errExit = common.errExit;
|
||||
|
||||
const std = @import("std");
|
||||
const common = @import("common.zig");
|
||||
Reference in New Issue
Block a user