Compare commits
No commits in common. "9e02196dd0ec1f180bedf50aa0ec1b195bb24fff" and "e5b3f03681cc3bad7c50b8abef4ea25483a3d611" have entirely different histories.
9e02196dd0
...
e5b3f03681
15 changed files with 618 additions and 91 deletions
36
CopyStep.zig
Normal file
36
CopyStep.zig
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const CopyStep = @This();
|
||||||
|
|
||||||
|
step: std.build.Step,
|
||||||
|
builder: *std.build.Builder,
|
||||||
|
from_path: ?[]const u8 = null,
|
||||||
|
to_path: ?[]const u8 = null,
|
||||||
|
|
||||||
|
pub fn create(
|
||||||
|
b: *std.build.Builder,
|
||||||
|
from_path_relative: []const u8,
|
||||||
|
to_path_relative: []const u8,
|
||||||
|
) *CopyStep {
|
||||||
|
var result = b.allocator.create(CopyStep) catch @panic("memory");
|
||||||
|
result.* = CopyStep{
|
||||||
|
.step = std.build.Step.init(.custom, "copy a file", b.allocator, make),
|
||||||
|
.builder = b,
|
||||||
|
.from_path = std.fs.path.resolve(b.allocator, &[_][]const u8{
|
||||||
|
b.build_root,
|
||||||
|
from_path_relative,
|
||||||
|
}) catch @panic("memory"),
|
||||||
|
.to_path = std.fs.path.resolve(b.allocator, &[_][]const u8{
|
||||||
|
b.build_root,
|
||||||
|
to_path_relative,
|
||||||
|
}) catch @panic("memory"),
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make(step: *std.build.Step) !void {
|
||||||
|
const self = @fieldParentPtr(CopyStep, "step", step);
|
||||||
|
std.fs.copyFileAbsolute(self.from_path.?, self.to_path.?, .{}) catch |e| {
|
||||||
|
std.log.err("Error copying {s} to {s}: {}", .{ self.from_path.?, self.to_path.?, e });
|
||||||
|
std.os.exit(1);
|
||||||
|
};
|
||||||
|
}
|
218
GitRepoStep.zig
Normal file
218
GitRepoStep.zig
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
//! Publish Date: 2021_10_17
|
||||||
|
//! This file is hosted at github.com/marler8997/zig-build-repos and is meant to be copied
|
||||||
|
//! to projects that use it.
|
||||||
|
const std = @import("std");
|
||||||
|
const GitRepoStep = @This();
|
||||||
|
|
||||||
|
pub const ShaCheck = enum {
|
||||||
|
none,
|
||||||
|
warn,
|
||||||
|
err,
|
||||||
|
|
||||||
|
pub fn reportFail(self: ShaCheck, comptime fmt: []const u8, args: anytype) void {
|
||||||
|
switch (self) {
|
||||||
|
.none => unreachable,
|
||||||
|
.warn => std.log.warn(fmt, args),
|
||||||
|
.err => {
|
||||||
|
std.log.err(fmt, args);
|
||||||
|
std.os.exit(0xff);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
step: std.build.Step,
|
||||||
|
builder: *std.build.Builder,
|
||||||
|
url: []const u8,
|
||||||
|
name: []const u8,
|
||||||
|
branch: ?[]const u8 = null,
|
||||||
|
sha: []const u8,
|
||||||
|
path: ?[]const u8 = null,
|
||||||
|
sha_check: ShaCheck = .warn,
|
||||||
|
fetch_enabled: bool,
|
||||||
|
|
||||||
|
var cached_default_fetch_option: ?bool = null;
|
||||||
|
pub fn defaultFetchOption(b: *std.build.Builder) bool {
|
||||||
|
if (cached_default_fetch_option) |_| {} else {
|
||||||
|
cached_default_fetch_option = if (b.option(bool, "fetch", "automatically fetch network resources")) |o| o else false;
|
||||||
|
}
|
||||||
|
return cached_default_fetch_option.?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(b: *std.build.Builder, opt: struct {
|
||||||
|
url: []const u8,
|
||||||
|
branch: ?[]const u8 = null,
|
||||||
|
sha: []const u8,
|
||||||
|
path: ?[]const u8 = null,
|
||||||
|
sha_check: ShaCheck = .warn,
|
||||||
|
fetch_enabled: ?bool = null,
|
||||||
|
}) *GitRepoStep {
|
||||||
|
var result = b.allocator.create(GitRepoStep) catch @panic("memory");
|
||||||
|
const name = std.fs.path.basename(opt.url);
|
||||||
|
result.* = GitRepoStep{
|
||||||
|
.step = std.build.Step.init(.custom, "clone a git repository", b.allocator, make),
|
||||||
|
.builder = b,
|
||||||
|
.url = opt.url,
|
||||||
|
.name = name,
|
||||||
|
.branch = opt.branch,
|
||||||
|
.sha = opt.sha,
|
||||||
|
.path = if (opt.path) |p| (b.allocator.dupe(u8, p) catch @panic("memory")) else (std.fs.path.resolve(b.allocator, &[_][]const u8{
|
||||||
|
b.build_root,
|
||||||
|
"libs",
|
||||||
|
name,
|
||||||
|
})) catch @panic("memory"),
|
||||||
|
.sha_check = opt.sha_check,
|
||||||
|
.fetch_enabled = if (opt.fetch_enabled) |fe| fe else defaultFetchOption(b),
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this should be included in std.build, it helps find bugs in build files
|
||||||
|
fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.Step) bool {
|
||||||
|
for (step.dependencies.items) |dep| {
|
||||||
|
// TODO: should probably use step.loop_flag to prevent infinite recursion
|
||||||
|
// when a circular reference is encountered, or maybe keep track of
|
||||||
|
// the steps encounterd with a hash set
|
||||||
|
if (dep == dep_candidate or hasDependency(dep, dep_candidate))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make(step: *std.build.Step) !void {
|
||||||
|
const self = @fieldParentPtr(GitRepoStep, "step", step);
|
||||||
|
|
||||||
|
std.fs.accessAbsolute(self.path.?, .{ .mode = .read_only }) catch {
|
||||||
|
const branch_args = if (self.branch) |b| &[2][]const u8{ " -b ", b } else &[2][]const u8{ "", "" };
|
||||||
|
if (!self.fetch_enabled) {
|
||||||
|
std.debug.print("Error: git repository '{s}' does not exist\n", .{self.path.?});
|
||||||
|
std.debug.print(" Use -Dfetch to download it automatically, or run the following to clone it:\n", .{});
|
||||||
|
std.debug.print(" git clone {s}{s}{s} {s} && git -C {3s} checkout {s} -b for_ziget\n", .{ self.url, branch_args[0], branch_args[1], self.path.?, self.sha });
|
||||||
|
std.os.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var args = std.ArrayList([]const u8).init(self.builder.allocator);
|
||||||
|
defer args.deinit();
|
||||||
|
try args.append("git");
|
||||||
|
try args.append("clone");
|
||||||
|
// This is a bad idea, because we really want to get to the correct
|
||||||
|
// revision before we go updating submodules
|
||||||
|
// try args.append("--recurse-submodules");
|
||||||
|
try args.append(self.url);
|
||||||
|
// TODO: clone it to a temporary location in case of failure
|
||||||
|
// also, remove that temporary location before running
|
||||||
|
try args.append(self.path.?);
|
||||||
|
if (self.branch) |branch| {
|
||||||
|
try args.append("-b");
|
||||||
|
try args.append(branch);
|
||||||
|
}
|
||||||
|
try run(self.builder, args.items);
|
||||||
|
}
|
||||||
|
try run(self.builder, &[_][]const u8{
|
||||||
|
"git",
|
||||||
|
"-C",
|
||||||
|
self.path.?,
|
||||||
|
"checkout",
|
||||||
|
self.sha,
|
||||||
|
"-b",
|
||||||
|
"fordep",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now that we're on the correct revision, we can update submodules
|
||||||
|
try run(self.builder, &[_][]const u8{
|
||||||
|
"git",
|
||||||
|
"-C",
|
||||||
|
self.path.?,
|
||||||
|
"submodule",
|
||||||
|
"update",
|
||||||
|
"--init",
|
||||||
|
"--recursive",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
try self.checkSha();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn checkSha(self: GitRepoStep) !void {
|
||||||
|
if (self.sha_check == .none)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const result: union(enum) { failed: anyerror, output: []const u8 } = blk: {
|
||||||
|
const result = std.ChildProcess.exec(.{
|
||||||
|
.allocator = self.builder.allocator,
|
||||||
|
.argv = &[_][]const u8{
|
||||||
|
"git",
|
||||||
|
"-C",
|
||||||
|
self.path.?,
|
||||||
|
"rev-parse",
|
||||||
|
"HEAD",
|
||||||
|
},
|
||||||
|
.cwd = self.builder.build_root,
|
||||||
|
.env_map = self.builder.env_map,
|
||||||
|
}) catch |e| break :blk .{ .failed = e };
|
||||||
|
try std.io.getStdErr().writer().writeAll(result.stderr);
|
||||||
|
switch (result.term) {
|
||||||
|
.Exited => |code| {
|
||||||
|
if (code == 0) break :blk .{ .output = result.stdout };
|
||||||
|
break :blk .{ .failed = error.GitProcessNonZeroExit };
|
||||||
|
},
|
||||||
|
.Signal => break :blk .{ .failed = error.GitProcessFailedWithSignal },
|
||||||
|
.Stopped => break :blk .{ .failed = error.GitProcessWasStopped },
|
||||||
|
.Unknown => break :blk .{ .failed = error.GitProcessFailed },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
switch (result) {
|
||||||
|
.failed => |err| {
|
||||||
|
return self.sha_check.reportFail("failed to retreive sha for repository '{s}': {s}", .{ self.name, @errorName(err) });
|
||||||
|
},
|
||||||
|
.output => |output| {
|
||||||
|
if (!std.mem.eql(u8, std.mem.trimRight(u8, output, "\n\r"), self.sha)) {
|
||||||
|
return self.sha_check.reportFail("repository '{s}' sha does not match\nexpected: {s}\nactual : {s}\n", .{ self.name, self.sha, output });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(builder: *std.build.Builder, argv: []const []const u8) !void {
|
||||||
|
{
|
||||||
|
var msg = std.ArrayList(u8).init(builder.allocator);
|
||||||
|
defer msg.deinit();
|
||||||
|
const writer = msg.writer();
|
||||||
|
var prefix: []const u8 = "";
|
||||||
|
for (argv) |arg| {
|
||||||
|
try writer.print("{s}\"{s}\"", .{ prefix, arg });
|
||||||
|
prefix = " ";
|
||||||
|
}
|
||||||
|
std.log.debug("[RUN] {s}", .{msg.items});
|
||||||
|
}
|
||||||
|
|
||||||
|
var child = std.ChildProcess.init(argv, builder.allocator);
|
||||||
|
|
||||||
|
child.stdin_behavior = .Ignore;
|
||||||
|
child.stdout_behavior = .Inherit;
|
||||||
|
child.stderr_behavior = .Inherit;
|
||||||
|
child.cwd = builder.build_root;
|
||||||
|
child.env_map = builder.env_map;
|
||||||
|
|
||||||
|
try child.spawn();
|
||||||
|
const result = try child.wait();
|
||||||
|
switch (result) {
|
||||||
|
.Exited => |code| if (code != 0) {
|
||||||
|
std.log.err("git clone failed with exit code {}", .{code});
|
||||||
|
std.os.exit(0xff);
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
std.log.err("git clone failed with: {}", .{result});
|
||||||
|
std.os.exit(0xff);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get's the repository path and also verifies that the step requesting the path
|
||||||
|
// is dependent on this step.
|
||||||
|
pub fn getPath(self: *const GitRepoStep, who_wants_to_know: *const std.build.Step) []const u8 {
|
||||||
|
if (!hasDependency(who_wants_to_know, &self.step))
|
||||||
|
@panic("a step called GitRepoStep.getPath but has not added it as a dependency");
|
||||||
|
return self.path;
|
||||||
|
}
|
229
VersionStep.zig
Normal file
229
VersionStep.zig
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
//! Publish Date: 2022-01-12
|
||||||
|
//! This file is hosted at ??? and is meant to be copied
|
||||||
|
//! to projects that use it. Sample usage:
|
||||||
|
//!
|
||||||
|
//! const version = VersionStep.create(b, null);
|
||||||
|
//! exe.step.dependOn(&version.step);
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const Step = @This();
|
||||||
|
|
||||||
|
step: std.build.Step,
|
||||||
|
builder: *std.build.Builder,
|
||||||
|
version_path: []const u8,
|
||||||
|
|
||||||
|
// Creates a step that will add the git version info in a file in src/
|
||||||
|
// so it can be consumed by additional code. If version_path is not specified,
|
||||||
|
// it will default to "git_version.zig". This should be part of .gitignore
|
||||||
|
pub fn create(b: *std.build.Builder, version_path: ?[]const u8) *Step {
|
||||||
|
var result = b.allocator.create(Step) catch @panic("memory");
|
||||||
|
result.* = Step{
|
||||||
|
.step = std.build.Step.init(.custom, "create version file", b.allocator, make),
|
||||||
|
.builder = b,
|
||||||
|
.version_path = std.fs.path.resolve(b.allocator, &[_][]const u8{
|
||||||
|
b.build_root,
|
||||||
|
"src",
|
||||||
|
version_path orelse "git_version.zig",
|
||||||
|
}) catch @panic("memory"),
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make(step: *std.build.Step) !void {
|
||||||
|
const self = @fieldParentPtr(Step, "step", step);
|
||||||
|
const file = try std.fs.createFileAbsolute(self.version_path, .{});
|
||||||
|
defer file.close();
|
||||||
|
const version = try getGitVersion(
|
||||||
|
self.builder.allocator,
|
||||||
|
self.builder.build_root,
|
||||||
|
self.builder.env_map,
|
||||||
|
);
|
||||||
|
defer version.deinit();
|
||||||
|
try file.writer().print(
|
||||||
|
\\pub const hash = "{s}";
|
||||||
|
\\pub const abbreviated_hash = "{s}";
|
||||||
|
\\pub const commit_date = "{s}";
|
||||||
|
\\pub const branch = "{s}";
|
||||||
|
\\pub const dirty = {};
|
||||||
|
\\pub const pretty_version = "{s}";
|
||||||
|
, .{
|
||||||
|
version.hash,
|
||||||
|
version.abbreviated_hash,
|
||||||
|
version.commit_date,
|
||||||
|
version.branch,
|
||||||
|
version.dirty,
|
||||||
|
version.pretty_version,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const GitVersion = struct {
|
||||||
|
hash: []const u8,
|
||||||
|
abbreviated_hash: []const u8,
|
||||||
|
commit_date: []const u8,
|
||||||
|
branch: []const u8,
|
||||||
|
dirty: bool,
|
||||||
|
pretty_version: []const u8,
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn deinit(self: Self) void {
|
||||||
|
self.allocator.free(self.hash);
|
||||||
|
self.allocator.free(self.abbreviated_hash);
|
||||||
|
self.allocator.free(self.commit_date);
|
||||||
|
self.allocator.free(self.branch);
|
||||||
|
self.allocator.free(self.pretty_version);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn getGitVersion(allocator: std.mem.Allocator, git_working_root: ?[]const u8, env: anytype) !GitVersion {
|
||||||
|
// git log -1 --pretty="%H%n%h%n%ci%n%D"
|
||||||
|
// 3bf6adc13e4aa653a7b75b1b5e9c9db5215df8e1
|
||||||
|
// 3bf6adc
|
||||||
|
// 2022-01-12 12:21:28 -0800
|
||||||
|
// HEAD -> zig-native
|
||||||
|
|
||||||
|
const log_output = run(
|
||||||
|
allocator,
|
||||||
|
&[_][]const u8{
|
||||||
|
"git",
|
||||||
|
"log",
|
||||||
|
"-1",
|
||||||
|
"--pretty=%H%n%h%n%ci%n%D",
|
||||||
|
},
|
||||||
|
git_working_root,
|
||||||
|
env,
|
||||||
|
) catch |e| {
|
||||||
|
if (std.os.getenv("DRONE_COMMIT_SHA") != null)
|
||||||
|
return getGitVersionFromDrone(allocator);
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
defer allocator.free(log_output);
|
||||||
|
const line_data = try getLines(allocator, 4, log_output);
|
||||||
|
const hash = line_data[0];
|
||||||
|
const abbrev_hash = line_data[1];
|
||||||
|
const date = line_data[2];
|
||||||
|
const branch = line_data[3];
|
||||||
|
|
||||||
|
// git status --porcelain
|
||||||
|
const status_output = try run(
|
||||||
|
allocator,
|
||||||
|
&[_][]const u8{
|
||||||
|
"git",
|
||||||
|
"status",
|
||||||
|
"--porcelain",
|
||||||
|
},
|
||||||
|
git_working_root,
|
||||||
|
env,
|
||||||
|
);
|
||||||
|
const dirty = blk: {
|
||||||
|
if (status_output.len > 0) {
|
||||||
|
allocator.free(status_output);
|
||||||
|
break :blk true;
|
||||||
|
}
|
||||||
|
break :blk false;
|
||||||
|
};
|
||||||
|
const dirty_str = blk: {
|
||||||
|
if (dirty) {
|
||||||
|
break :blk " (dirty)";
|
||||||
|
}
|
||||||
|
break :blk "";
|
||||||
|
};
|
||||||
|
|
||||||
|
return GitVersion{
|
||||||
|
.hash = hash,
|
||||||
|
.abbreviated_hash = abbrev_hash,
|
||||||
|
.commit_date = date,
|
||||||
|
.branch = branch,
|
||||||
|
.allocator = allocator,
|
||||||
|
.dirty = dirty,
|
||||||
|
.pretty_version = try prettyVersion(allocator, abbrev_hash, date, dirty_str),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fn prettyVersion(allocator: std.mem.Allocator, abbrev_hash: []const u8, date: []const u8, dirty_str: []const u8) ![]const u8 {
|
||||||
|
const pretty_version: []const u8 = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"version {s}, committed at {s}{s}",
|
||||||
|
.{
|
||||||
|
abbrev_hash,
|
||||||
|
date,
|
||||||
|
dirty_str,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return pretty_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getGitVersionFromDrone(allocator: std.mem.Allocator) !GitVersion {
|
||||||
|
const abbrev_hash = std.os.getenv("DRONE_COMMIT_SHA").?[0..7]; // This isn't quite how git works, but ok
|
||||||
|
const date = std.os.getenv("DRONE_BUILD_STARTED").?; // this is a timestamp :(
|
||||||
|
return GitVersion{
|
||||||
|
.hash = std.os.getenv("DRONE_COMMIT_SHA").?,
|
||||||
|
.abbreviated_hash = abbrev_hash,
|
||||||
|
.commit_date = date,
|
||||||
|
.branch = std.os.getenv("DRONE_COMMIT_BRANCH").?,
|
||||||
|
.allocator = allocator,
|
||||||
|
.dirty = false,
|
||||||
|
.pretty_version = try prettyVersion(allocator, abbrev_hash, date, ""),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fn getLines(allocator: std.mem.Allocator, comptime line_count: u32, data: []const u8) ![line_count][]u8 {
|
||||||
|
var line: u32 = 0;
|
||||||
|
var start: u32 = 0;
|
||||||
|
var current: u32 = 0;
|
||||||
|
var line_data: [line_count][]u8 = undefined;
|
||||||
|
errdefer {
|
||||||
|
while (line > 0) {
|
||||||
|
allocator.free(line_data[line]);
|
||||||
|
line -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (data) |c| {
|
||||||
|
// try std.io.getStdErr().writer().print("line: {d}, c: {c}, cur: {d}, strt: {d}\n", .{ line, c, current, start });
|
||||||
|
if (c == '\n') {
|
||||||
|
line_data[line] = try allocator.dupe(u8, data[start..current]);
|
||||||
|
// try std.io.getStdErr().writer().print("c: {d}, s: {d}, data: '{s}'\n", .{ current, start, line_data[line] });
|
||||||
|
start = current + 1;
|
||||||
|
line += 1;
|
||||||
|
}
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
return line_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// env is a std.process.BufMap, but that's private, which is a little weird tbh
|
||||||
|
fn run(allocator: std.mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env: anytype) ![]const u8 {
|
||||||
|
{
|
||||||
|
var msg = std.ArrayList(u8).init(allocator);
|
||||||
|
defer msg.deinit();
|
||||||
|
const writer = msg.writer();
|
||||||
|
var prefix: []const u8 = "";
|
||||||
|
for (argv) |arg| {
|
||||||
|
try writer.print("{s}\"{s}\"", .{ prefix, arg });
|
||||||
|
prefix = " ";
|
||||||
|
}
|
||||||
|
// std.log.debug("[RUN] {s}", .{msg.items});
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = try std.ChildProcess.exec(.{
|
||||||
|
.allocator = allocator,
|
||||||
|
.argv = argv,
|
||||||
|
.cwd = cwd,
|
||||||
|
.env_map = env,
|
||||||
|
});
|
||||||
|
defer if (result.stderr.len > 0) allocator.free(result.stderr);
|
||||||
|
try std.io.getStdErr().writer().writeAll(result.stderr);
|
||||||
|
|
||||||
|
switch (result.term) {
|
||||||
|
.Exited => |code| if (code != 0) {
|
||||||
|
std.log.err("process failed with exit code: {}", .{code});
|
||||||
|
|
||||||
|
std.os.exit(0xff);
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
std.log.err("process failed due to exception: {}", .{result});
|
||||||
|
std.os.exit(0xff);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return result.stdout;
|
||||||
|
}
|
36
build.zig
36
build.zig
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const Builder = @import("std").build.Builder;
|
const Builder = @import("std").build.Builder;
|
||||||
|
const tst = @import("build_test.zig");
|
||||||
|
|
||||||
pub fn build(b: *Builder) !void {
|
pub fn build(b: *Builder) !void {
|
||||||
// Standard target options allows the person running `zig build` to choose
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
@ -13,16 +14,6 @@ pub fn build(b: *Builder) !void {
|
||||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
// TODO: Embed the current git version in the code. We can do this
|
|
||||||
// by looking for .git/HEAD (if it exists, follow the ref to /ref/heads/whatevs,
|
|
||||||
// grab that commit, and use b.addOptions/exe.addOptions to generate the
|
|
||||||
// Options file. See https://github.com/ziglang/zig/issues/14979 for usage
|
|
||||||
// example.
|
|
||||||
//
|
|
||||||
// From there, I'm not sure what the generated file looks like or quite how
|
|
||||||
// to use, but that should be easy. It may also give some ideas on the
|
|
||||||
// code gen piece itself, though it might be nice to leave as a seperate
|
|
||||||
// executable
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "demo",
|
.name = "demo",
|
||||||
.root_source_file = .{ .path = "src/main.zig" },
|
.root_source_file = .{ .path = "src/main.zig" },
|
||||||
|
@ -53,7 +44,8 @@ pub fn build(b: *Builder) !void {
|
||||||
const run_step = b.step("run", "Run the app");
|
const run_step = b.step("run", "Run the app");
|
||||||
run_step.dependOn(&run_cmd.step);
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
// TODO: Proper testing
|
// TODO: Demo for testing is kind of terrible. Proper testing
|
||||||
|
// var test_step = try tst.addTestStep(b, optimize, exe.packages.items);
|
||||||
|
|
||||||
var codegen: ?*std.build.Step = null;
|
var codegen: ?*std.build.Step = null;
|
||||||
if (target.getOs().tag == .linux and false) {
|
if (target.getOs().tag == .linux and false) {
|
||||||
|
@ -61,25 +53,13 @@ pub fn build(b: *Builder) !void {
|
||||||
// std.build.RunStep.create(null,null).cwd(std.fs.path.resolve(b.build_root, "codegen")).addArgs(...)
|
// std.build.RunStep.create(null,null).cwd(std.fs.path.resolve(b.build_root, "codegen")).addArgs(...)
|
||||||
codegen = b.step("gen", "Generate zig service code from smithy models");
|
codegen = b.step("gen", "Generate zig service code from smithy models");
|
||||||
const cg = codegen.?;
|
const cg = codegen.?;
|
||||||
// TODO: this should use zig_exe from std.Build
|
|
||||||
// codegen should store a hash in a comment
|
|
||||||
// this would be hash of the exe that created the file
|
|
||||||
// concatenated with hash of input json. this would
|
|
||||||
// allow skipping generated files. May not include hash
|
|
||||||
// of contents of output file as maybe we want to tweak
|
|
||||||
// manually??
|
|
||||||
//
|
|
||||||
// All the hashes can be in service_manifest.zig, which
|
|
||||||
// could be fun to just parse and go nuts. Top of
|
|
||||||
// file, generator exe hash. Each import has comment
|
|
||||||
// with both input and output hash and we can decide
|
|
||||||
// later about warning on manual changes...
|
|
||||||
//
|
|
||||||
// this scheme would permit cross plat codegen and maybe
|
|
||||||
// we can have codegen added in a seperate repo,
|
|
||||||
// though not sure how necessary that is
|
|
||||||
cg.dependOn(&b.addSystemCommand(&.{ "/bin/sh", "-c", "cd codegen && zig build" }).step);
|
cg.dependOn(&b.addSystemCommand(&.{ "/bin/sh", "-c", "cd codegen && zig build" }).step);
|
||||||
|
|
||||||
|
// This can probably be triggered instead by GitRepoStep cloning the repo
|
||||||
|
// with models
|
||||||
|
// Since codegen binary is built every time, if it's newer than our
|
||||||
|
// service manifest we know it needs to be regenerated. So this step
|
||||||
|
// will remove the service manifest if codegen has been touched, thereby
|
||||||
// triggering the re-gen
|
// triggering the re-gen
|
||||||
cg.dependOn(&b.addSystemCommand(&.{
|
cg.dependOn(&b.addSystemCommand(&.{
|
||||||
"/bin/sh", "-c",
|
"/bin/sh", "-c",
|
||||||
|
|
32
build_test.zig
Normal file
32
build_test.zig
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//! Publish Date: 2022-01-12
|
||||||
|
//! This file is hosted at ??? and is meant to be copied
|
||||||
|
//! to projects that use it. Sample usage:
|
||||||
|
//!
|
||||||
|
//! const @"test" = @import("build_test.zig");
|
||||||
|
//! var test_step = try @"test".addTestStep(b, mode, exe.packages.items);
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn addTestStep(b: *std.build.Builder, mode: std.builtin.Mode, packages: []std.build.Pkg) !*std.build.Step {
|
||||||
|
const test_step = b.step("test", "Run all tests");
|
||||||
|
const src_path = try std.fs.path.resolve(b.allocator, &[_][]const u8{
|
||||||
|
b.build_root,
|
||||||
|
"src",
|
||||||
|
});
|
||||||
|
defer b.allocator.free(src_path);
|
||||||
|
var src_dir = try std.fs.openDirAbsolute(src_path, .{});
|
||||||
|
defer src_dir.close();
|
||||||
|
var iterable = try src_dir.openIterableDir(".", .{});
|
||||||
|
defer iterable.close();
|
||||||
|
var iterator = iterable.iterate();
|
||||||
|
while (try iterator.next()) |entry| {
|
||||||
|
if (std.mem.endsWith(u8, entry.name, ".zig")) {
|
||||||
|
const name = try std.fmt.allocPrint(b.allocator, "src/{s}", .{entry.name});
|
||||||
|
defer b.allocator.free(name);
|
||||||
|
const t = b.addTest(name);
|
||||||
|
for (packages) |package| t.addPackage(package);
|
||||||
|
t.setBuildMode(mode);
|
||||||
|
test_step.dependOn(&t.step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return test_step;
|
||||||
|
}
|
20
src/Amazon_Root_CA_1.pem
Normal file
20
src/Amazon_Root_CA_1.pem
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
|
||||||
|
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
|
||||||
|
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
|
||||||
|
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
|
||||||
|
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
|
||||||
|
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
|
||||||
|
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
|
||||||
|
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
|
||||||
|
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
|
||||||
|
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
|
||||||
|
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
|
||||||
|
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
|
||||||
|
rqXRfboQnoZsG4q5WTP468SQvvG5
|
||||||
|
-----END CERTIFICATE-----
|
14
src/aws.zig
14
src/aws.zig
|
@ -76,7 +76,7 @@ pub fn Request(comptime request_action: anytype) type {
|
||||||
Self.service_meta.version,
|
Self.service_meta.version,
|
||||||
action.action_name,
|
action.action_name,
|
||||||
});
|
});
|
||||||
log.debug("proto: {}", .{Self.service_meta.aws_protocol});
|
log.debug("proto: {s}", .{Self.service_meta.aws_protocol});
|
||||||
|
|
||||||
// It seems as though there are 3 major branches of the 6 protocols.
|
// It seems as though there are 3 major branches of the 6 protocols.
|
||||||
// 1. query/ec2_query, which are identical until you get to complex
|
// 1. query/ec2_query, which are identical until you get to complex
|
||||||
|
@ -600,7 +600,7 @@ pub fn Request(comptime request_action: anytype) type {
|
||||||
\\This could be the result of a bug or a stale set of code generated
|
\\This could be the result of a bug or a stale set of code generated
|
||||||
\\service models.
|
\\service models.
|
||||||
\\
|
\\
|
||||||
\\Model Type: {}
|
\\Model Type: {s}
|
||||||
\\
|
\\
|
||||||
\\Response from server:
|
\\Response from server:
|
||||||
\\
|
\\
|
||||||
|
@ -620,7 +620,7 @@ pub fn Request(comptime request_action: anytype) type {
|
||||||
\\This could be the result of a bug or a stale set of code generated
|
\\This could be the result of a bug or a stale set of code generated
|
||||||
\\service models.
|
\\service models.
|
||||||
\\
|
\\
|
||||||
\\Model Type: {}
|
\\Model Type: {s}
|
||||||
\\
|
\\
|
||||||
\\Response from server:
|
\\Response from server:
|
||||||
\\
|
\\
|
||||||
|
@ -674,7 +674,7 @@ fn generalAllocPrint(allocator: std.mem.Allocator, val: anytype) !?[]const u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn headersFor(allocator: std.mem.Allocator, request: anytype) ![]awshttp.Header {
|
fn headersFor(allocator: std.mem.Allocator, request: anytype) ![]awshttp.Header {
|
||||||
log.debug("Checking for headers to include for type {}", .{@TypeOf(request)});
|
log.debug("Checking for headers to include for type {s}", .{@TypeOf(request)});
|
||||||
if (!@hasDecl(@TypeOf(request), "http_header")) return &[_]awshttp.Header{};
|
if (!@hasDecl(@TypeOf(request), "http_header")) return &[_]awshttp.Header{};
|
||||||
const http_header = @TypeOf(request).http_header;
|
const http_header = @TypeOf(request).http_header;
|
||||||
const fields = std.meta.fields(@TypeOf(http_header));
|
const fields = std.meta.fields(@TypeOf(http_header));
|
||||||
|
@ -983,14 +983,14 @@ fn buildQuery(allocator: std.mem.Allocator, request: anytype) ![]const u8 {
|
||||||
const writer = buffer.writer();
|
const writer = buffer.writer();
|
||||||
defer buffer.deinit();
|
defer buffer.deinit();
|
||||||
var prefix = "?";
|
var prefix = "?";
|
||||||
if (@hasDecl(@TypeOf(request), "http_query")) {
|
// TODO: This was a pain before, and it's a pain now. Clearly our codegen
|
||||||
const query_arguments = @field(@TypeOf(request), "http_query");
|
// needs to emit a declaration 100% of the time
|
||||||
|
const query_arguments = @TypeOf(request).http_query;
|
||||||
inline for (@typeInfo(@TypeOf(query_arguments)).Struct.fields) |arg| {
|
inline for (@typeInfo(@TypeOf(query_arguments)).Struct.fields) |arg| {
|
||||||
const val = @field(request, arg.name);
|
const val = @field(request, arg.name);
|
||||||
if (try addQueryArg(arg.type, prefix, @field(query_arguments, arg.name), val, writer))
|
if (try addQueryArg(arg.type, prefix, @field(query_arguments, arg.name), val, writer))
|
||||||
prefix = "&";
|
prefix = "&";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return buffer.toOwnedSlice();
|
return buffer.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ fn getImdsv2Credentials(allocator: std.mem.Allocator) !?auth.Credentials {
|
||||||
defer resp_payload.deinit();
|
defer resp_payload.deinit();
|
||||||
try resp_payload.resize(req.response.content_length.?);
|
try resp_payload.resize(req.response.content_length.?);
|
||||||
token = try resp_payload.toOwnedSlice();
|
token = try resp_payload.toOwnedSlice();
|
||||||
errdefer if (token) |t| allocator.free(t);
|
errdefer allocator.free(token);
|
||||||
_ = try req.readAll(token.?);
|
_ = try req.readAll(token.?);
|
||||||
}
|
}
|
||||||
std.debug.assert(token != null);
|
std.debug.assert(token != null);
|
||||||
|
@ -207,7 +207,7 @@ fn getImdsv2Credentials(allocator: std.mem.Allocator) !?auth.Credentials {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
defer allocator.free(role_name.?);
|
defer allocator.free(role_name.?);
|
||||||
log.debug("Got role name '{s}'", .{role_name.?});
|
log.debug("Got role name '{s}'", .{role_name});
|
||||||
return getImdsCredentials(allocator, &cl, role_name.?, token.?);
|
return getImdsCredentials(allocator, &cl, role_name.?, token.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ pub const AwsHttp = struct {
|
||||||
|
|
||||||
// TODO: Timeout - is this now above us?
|
// TODO: Timeout - is this now above us?
|
||||||
log.debug(
|
log.debug(
|
||||||
"Request Complete. Response code {d}: {any}",
|
"Request Complete. Response code {d}: {s}",
|
||||||
.{ @intFromEnum(req.response.status), req.response.status.phrase() },
|
.{ @intFromEnum(req.response.status), req.response.status.phrase() },
|
||||||
);
|
);
|
||||||
log.debug("Response headers:", .{});
|
log.debug("Response headers:", .{});
|
||||||
|
|
|
@ -358,7 +358,7 @@ fn createCanonicalRequest(allocator: std.mem.Allocator, request: base.Request, p
|
||||||
;
|
;
|
||||||
|
|
||||||
// TODO: This is all better as a writer - less allocations/copying
|
// TODO: This is all better as a writer - less allocations/copying
|
||||||
const canonical_method = try canonicalRequestMethod(request.method);
|
const canonical_method = canonicalRequestMethod(request.method);
|
||||||
// Let's not mess around here...s3 is the oddball
|
// Let's not mess around here...s3 is the oddball
|
||||||
const double_encode = !std.mem.eql(u8, config.service, "s3");
|
const double_encode = !std.mem.eql(u8, config.service, "s3");
|
||||||
const canonical_url = try canonicalUri(allocator, request.path, double_encode);
|
const canonical_url = try canonicalUri(allocator, request.path, double_encode);
|
||||||
|
|
6
src/git_version-orig.zig
Normal file
6
src/git_version-orig.zig
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pub const hash = "a662f6f674e66aa4cff435553e2593b7fd0a9aef";
|
||||||
|
pub const abbreviated_hash = "a662f6f";
|
||||||
|
pub const commit_date = "2022-06-05 18:34:39 -0700";
|
||||||
|
pub const branch = "HEAD -> master, origin/master";
|
||||||
|
pub const dirty = true;
|
||||||
|
pub const pretty_version = "version a662f6f, committed at 2022-06-05 18:34:39 -0700 (dirty)";
|
77
src/main.zig
77
src/main.zig
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const aws = @import("aws.zig");
|
const aws = @import("aws.zig");
|
||||||
const json = @import("json.zig");
|
const json = @import("json.zig");
|
||||||
|
const version = @import("git_version.zig");
|
||||||
|
|
||||||
var verbose: u8 = 0;
|
var verbose: u8 = 0;
|
||||||
|
|
||||||
|
@ -62,7 +63,11 @@ pub fn main() anyerror!void {
|
||||||
var tests = std.ArrayList(Tests).init(allocator);
|
var tests = std.ArrayList(Tests).init(allocator);
|
||||||
defer tests.deinit();
|
defer tests.deinit();
|
||||||
var args = std.process.args();
|
var args = std.process.args();
|
||||||
|
var first = true;
|
||||||
while (args.next()) |arg| {
|
while (args.next()) |arg| {
|
||||||
|
if (first)
|
||||||
|
std.log.info("{s} {s}", .{ arg, version.pretty_version });
|
||||||
|
first = false;
|
||||||
if (std.mem.eql(u8, "-v", arg)) {
|
if (std.mem.eql(u8, "-v", arg)) {
|
||||||
verbose += 1;
|
verbose += 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -96,64 +101,64 @@ pub fn main() anyerror!void {
|
||||||
const call = try aws.Request(services.sts.get_caller_identity).call(.{}, options);
|
const call = try aws.Request(services.sts.get_caller_identity).call(.{}, options);
|
||||||
// const call = try client.call(services.sts.get_caller_identity.Request{}, options);
|
// const call = try client.call(services.sts.get_caller_identity.Request{}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("arn: {any}", .{call.response.arn});
|
std.log.info("arn: {s}", .{call.response.arn});
|
||||||
std.log.info("id: {any}", .{call.response.user_id});
|
std.log.info("id: {s}", .{call.response.user_id});
|
||||||
std.log.info("account: {any}", .{call.response.account});
|
std.log.info("account: {s}", .{call.response.account});
|
||||||
std.log.info("requestId: {any}", .{call.response_metadata.request_id});
|
std.log.info("requestId: {s}", .{call.response_metadata.request_id});
|
||||||
},
|
},
|
||||||
.query_with_input => {
|
.query_with_input => {
|
||||||
const call = try client.call(services.sqs.list_queues.Request{
|
const call = try client.call(services.sqs.list_queues.Request{
|
||||||
.queue_name_prefix = "s",
|
.queue_name_prefix = "s",
|
||||||
}, options);
|
}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has queues with prefix 's': {}", .{call.response.queue_urls != null});
|
std.log.info("account has queues with prefix 's': {b}", .{call.response.queue_urls != null});
|
||||||
},
|
},
|
||||||
.json_1_0_query_with_input => {
|
.json_1_0_query_with_input => {
|
||||||
const call = try client.call(services.dynamo_db.list_tables.Request{
|
const call = try client.call(services.dynamo_db.list_tables.Request{
|
||||||
.limit = 1,
|
.limit = 1,
|
||||||
}, options);
|
}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has tables: {}", .{call.response.table_names.?.len > 0});
|
std.log.info("account has tables: {b}", .{call.response.table_names.?.len > 0});
|
||||||
},
|
},
|
||||||
.json_1_0_query_no_input => {
|
.json_1_0_query_no_input => {
|
||||||
const call = try client.call(services.dynamo_db.describe_limits.Request{}, options);
|
const call = try client.call(services.dynamo_db.describe_limits.Request{}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("account read capacity limit: {?d}", .{call.response.account_max_read_capacity_units});
|
std.log.info("account read capacity limit: {d}", .{call.response.account_max_read_capacity_units});
|
||||||
},
|
},
|
||||||
.json_1_1_query_with_input => {
|
.json_1_1_query_with_input => {
|
||||||
const call = try client.call(services.ecs.list_clusters.Request{
|
const call = try client.call(services.ecs.list_clusters.Request{
|
||||||
.max_results = 1,
|
.max_results = 1,
|
||||||
}, options);
|
}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has clusters: {}", .{call.response.cluster_arns.?.len > 0});
|
std.log.info("account has clusters: {b}", .{call.response.cluster_arns.?.len > 0});
|
||||||
},
|
},
|
||||||
.json_1_1_query_no_input => {
|
.json_1_1_query_no_input => {
|
||||||
const call = try client.call(services.ecs.list_clusters.Request{}, options);
|
const call = try client.call(services.ecs.list_clusters.Request{}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has clusters: {}", .{call.response.cluster_arns.?.len > 0});
|
std.log.info("account has clusters: {b}", .{call.response.cluster_arns.?.len > 0});
|
||||||
},
|
},
|
||||||
.rest_json_1_query_with_input => {
|
.rest_json_1_query_with_input => {
|
||||||
const call = try client.call(services.lambda.list_functions.Request{
|
const call = try client.call(services.lambda.list_functions.Request{
|
||||||
.max_items = 1,
|
.max_items = 1,
|
||||||
}, options);
|
}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has functions: {}", .{call.response.functions.?.len > 0});
|
std.log.info("account has functions: {b}", .{call.response.functions.?.len > 0});
|
||||||
},
|
},
|
||||||
.rest_json_1_query_no_input => {
|
.rest_json_1_query_no_input => {
|
||||||
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
||||||
std.log.info("account has functions: {}", .{call.response.functions.?.len > 0});
|
std.log.info("account has functions: {b}", .{call.response.functions.?.len > 0});
|
||||||
},
|
},
|
||||||
.rest_json_1_work_with_lambda => {
|
.rest_json_1_work_with_lambda => {
|
||||||
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
std.log.info("list request id: {any}", .{call.response_metadata.request_id});
|
std.log.info("list request id: {s}", .{call.response_metadata.request_id});
|
||||||
if (call.response.functions) |fns| {
|
if (call.response.functions) |fns| {
|
||||||
if (fns.len > 0) {
|
if (fns.len > 0) {
|
||||||
const func = fns[0];
|
const func = fns[0];
|
||||||
|
@ -166,11 +171,11 @@ pub fn main() anyerror!void {
|
||||||
const addtag = try aws.Request(services.lambda.tag_resource).call(req, options);
|
const addtag = try aws.Request(services.lambda.tag_resource).call(req, options);
|
||||||
defer addtag.deinit();
|
defer addtag.deinit();
|
||||||
// const addtag = try client.call(services.lambda.tag_resource.Request{ .resource = arn, .tags = &.{.{ .key = "Foo", .value = "Bar" }} }, options);
|
// const addtag = try client.call(services.lambda.tag_resource.Request{ .resource = arn, .tags = &.{.{ .key = "Foo", .value = "Bar" }} }, options);
|
||||||
std.log.info("add tag request id: {any}", .{addtag.response_metadata.request_id});
|
std.log.info("add tag request id: {s}", .{addtag.response_metadata.request_id});
|
||||||
var keys = [_][]const u8{"Foo"}; // Would love to have a way to express this without burning a var here
|
var keys = [_][]const u8{"Foo"}; // Would love to have a way to express this without burning a var here
|
||||||
const deletetag = try aws.Request(services.lambda.untag_resource).call(.{ .tag_keys = keys[0..], .resource = arn }, options);
|
const deletetag = try aws.Request(services.lambda.untag_resource).call(.{ .tag_keys = keys[0..], .resource = arn }, options);
|
||||||
defer deletetag.deinit();
|
defer deletetag.deinit();
|
||||||
std.log.info("delete tag request id: {any}", .{deletetag.response_metadata.request_id});
|
std.log.info("delete tag request id: {s}", .{deletetag.response_metadata.request_id});
|
||||||
} else {
|
} else {
|
||||||
std.log.err("no functions to work with", .{});
|
std.log.err("no functions to work with", .{});
|
||||||
}
|
}
|
||||||
|
@ -182,7 +187,7 @@ pub fn main() anyerror!void {
|
||||||
// Describe regions is a simpler request and easier to debug
|
// Describe regions is a simpler request and easier to debug
|
||||||
const result = try client.call(services.ec2.describe_regions.Request{}, options);
|
const result = try client.call(services.ec2.describe_regions.Request{}, options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
std.log.info("request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("region count: {d}", .{result.response.regions.?.len});
|
std.log.info("region count: {d}", .{result.response.regions.?.len});
|
||||||
},
|
},
|
||||||
.ec2_query_with_input => {
|
.ec2_query_with_input => {
|
||||||
|
@ -216,15 +221,15 @@ pub fn main() anyerror!void {
|
||||||
.rest_xml_no_input => {
|
.rest_xml_no_input => {
|
||||||
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
std.log.info("request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("bucket count: {d}", .{result.response.buckets.?.len});
|
std.log.info("bucket count: {d}", .{result.response.buckets.?.len});
|
||||||
},
|
},
|
||||||
.rest_xml_anything_but_s3 => {
|
.rest_xml_anything_but_s3 => {
|
||||||
const result = try client.call(services.cloudfront.list_key_groups.Request{}, options);
|
const result = try client.call(services.cloudfront.list_key_groups.Request{}, options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
std.log.info("request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
||||||
const list = result.response.key_group_list.?;
|
const list = result.response.key_group_list.?;
|
||||||
std.log.info("key group list max: {?d}", .{list.max_items});
|
std.log.info("key group list max: {d}", .{list.max_items});
|
||||||
std.log.info("key group quantity: {d}", .{list.quantity});
|
std.log.info("key group quantity: {d}", .{list.quantity});
|
||||||
},
|
},
|
||||||
.rest_xml_work_with_s3 => {
|
.rest_xml_work_with_s3 => {
|
||||||
|
@ -235,8 +240,8 @@ pub fn main() anyerror!void {
|
||||||
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
const bucket = result.response.buckets.?[result.response.buckets.?.len - 1];
|
const bucket = result.response.buckets.?[result.response.buckets.?.len - 1];
|
||||||
std.log.info("ListBuckets request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("ListBuckets request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("bucket name: {any}", .{bucket.name.?});
|
std.log.info("bucket name: {s}", .{bucket.name.?});
|
||||||
break :blk try allocator.dupe(u8, bucket.name.?);
|
break :blk try allocator.dupe(u8, bucket.name.?);
|
||||||
};
|
};
|
||||||
defer allocator.free(bucket);
|
defer allocator.free(bucket);
|
||||||
|
@ -246,8 +251,8 @@ pub fn main() anyerror!void {
|
||||||
}, options);
|
}, options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
const location = result.response.location_constraint.?;
|
const location = result.response.location_constraint.?;
|
||||||
std.log.info("GetBucketLocation request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("GetBucketLocation request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("location: {any}", .{location});
|
std.log.info("location: {s}", .{location});
|
||||||
break :blk try allocator.dupe(u8, location);
|
break :blk try allocator.dupe(u8, location);
|
||||||
};
|
};
|
||||||
defer allocator.free(location);
|
defer allocator.free(location);
|
||||||
|
@ -263,8 +268,8 @@ pub fn main() anyerror!void {
|
||||||
.body = "bar",
|
.body = "bar",
|
||||||
.storage_class = "STANDARD",
|
.storage_class = "STANDARD",
|
||||||
}, s3opts);
|
}, s3opts);
|
||||||
std.log.info("PutObject Request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("PutObject Request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("PutObject etag: {any}", .{result.response.e_tag.?});
|
std.log.info("PutObject etag: {s}", .{result.response.e_tag.?});
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -274,9 +279,9 @@ pub fn main() anyerror!void {
|
||||||
.bucket = bucket,
|
.bucket = bucket,
|
||||||
.key = key,
|
.key = key,
|
||||||
}, s3opts);
|
}, s3opts);
|
||||||
std.log.info("GetObject Request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("GetObject Request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("GetObject Body: {any}", .{result.response.body});
|
std.log.info("GetObject Body: {s}", .{result.response.body});
|
||||||
std.log.info("GetObject etag: {any}", .{result.response.e_tag.?});
|
std.log.info("GetObject etag: {s}", .{result.response.e_tag.?});
|
||||||
std.log.info("GetObject last modified (seconds since epoch): {d}", .{result.response.last_modified.?});
|
std.log.info("GetObject last modified (seconds since epoch): {d}", .{result.response.last_modified.?});
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
}
|
}
|
||||||
|
@ -285,14 +290,14 @@ pub fn main() anyerror!void {
|
||||||
.bucket = bucket,
|
.bucket = bucket,
|
||||||
.key = key,
|
.key = key,
|
||||||
}, s3opts);
|
}, s3opts);
|
||||||
std.log.info("DeleteObject Request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("DeleteObject Request id: {s}", .{result.response_metadata.request_id});
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const result = try aws.Request(services.s3.list_objects).call(.{
|
const result = try aws.Request(services.s3.list_objects).call(.{
|
||||||
.bucket = bucket,
|
.bucket = bucket,
|
||||||
}, s3opts);
|
}, s3opts);
|
||||||
std.log.info("ListObject Request id: {any}", .{result.response_metadata.request_id});
|
std.log.info("ListObject Request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("Object count: {d}", .{result.response.contents.?.len});
|
std.log.info("Object count: {d}", .{result.response.contents.?.len});
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
}
|
}
|
||||||
|
@ -344,5 +349,5 @@ pub fn jsonFun() !void {
|
||||||
.allow_unknown_fields = true, // new option
|
.allow_unknown_fields = true, // new option
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
std.log.info("{}", .{res3});
|
std.log.info("{}", .{res3});
|
||||||
std.log.info("{any}", .{res3.getCallerIdentityResponse.getCallerIdentityResult.user_id});
|
std.log.info("{s}", .{res3.getCallerIdentityResponse.getCallerIdentityResult.user_id});
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub fn encodeInternal(
|
||||||
rc = try encodeInternal(allocator, parent, field_name, first, obj.*, writer, options);
|
rc = try encodeInternal(allocator, parent, field_name, first, obj.*, writer, options);
|
||||||
} else {
|
} else {
|
||||||
if (!first) _ = try writer.write("&");
|
if (!first) _ = try writer.write("&");
|
||||||
try writer.print("{s}{s}={any}", .{ parent, field_name, obj });
|
try writer.print("{s}{s}={s}", .{ parent, field_name, obj });
|
||||||
rc = false;
|
rc = false;
|
||||||
},
|
},
|
||||||
.Struct => if (std.mem.eql(u8, "", field_name)) {
|
.Struct => if (std.mem.eql(u8, "", field_name)) {
|
||||||
|
|
|
@ -102,7 +102,7 @@ fn parseInternal(comptime T: type, element: *xml.Element, options: ParseOptions)
|
||||||
return std.fmt.parseFloat(T, element.children.items[0].CharData) catch |e| {
|
return std.fmt.parseFloat(T, element.children.items[0].CharData) catch |e| {
|
||||||
if (log_parse_traces) {
|
if (log_parse_traces) {
|
||||||
std.log.err(
|
std.log.err(
|
||||||
"Could not parse '{s}' as float in element '{s}': {any}",
|
"Could not parse '{s}' as float in element '{s}': {s}",
|
||||||
.{
|
.{
|
||||||
element.children.items[0].CharData,
|
element.children.items[0].CharData,
|
||||||
element.tag,
|
element.tag,
|
||||||
|
@ -127,7 +127,7 @@ fn parseInternal(comptime T: type, element: *xml.Element, options: ParseOptions)
|
||||||
}
|
}
|
||||||
if (log_parse_traces) {
|
if (log_parse_traces) {
|
||||||
std.log.err(
|
std.log.err(
|
||||||
"Could not parse '{s}' as integer in element '{s}': {any}",
|
"Could not parse '{s}' as integer in element '{s}': {s}",
|
||||||
.{
|
.{
|
||||||
element.children.items[0].CharData,
|
element.children.items[0].CharData,
|
||||||
element.tag,
|
element.tag,
|
||||||
|
@ -392,7 +392,7 @@ test "can parse a simple type" {
|
||||||
foo_bar: []const u8,
|
foo_bar: []const u8,
|
||||||
};
|
};
|
||||||
// std.debug.print("{s}", .{data});
|
// std.debug.print("{s}", .{data});
|
||||||
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqualStrings("bar", parsed_data.parsed_value.foo_bar);
|
try testing.expectEqualStrings("bar", parsed_data.parsed_value.foo_bar);
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ test "can parse a boolean type" {
|
||||||
foo_bar: bool,
|
foo_bar: bool,
|
||||||
};
|
};
|
||||||
// std.debug.print("{s}", .{data});
|
// std.debug.print("{s}", .{data});
|
||||||
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqual(true, parsed_data.parsed_value.foo_bar);
|
try testing.expectEqual(true, parsed_data.parsed_value.foo_bar);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +427,7 @@ test "can parse an integer type" {
|
||||||
foo_bar: u8,
|
foo_bar: u8,
|
||||||
};
|
};
|
||||||
// std.debug.print("{s}", .{data});
|
// std.debug.print("{s}", .{data});
|
||||||
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqual(@as(u8, 42), parsed_data.parsed_value.foo_bar);
|
try testing.expectEqual(@as(u8, 42), parsed_data.parsed_value.foo_bar);
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ test "can parse an optional boolean type" {
|
||||||
const ExampleDoesNotMatter = struct {
|
const ExampleDoesNotMatter = struct {
|
||||||
foo_bar: ?bool = null,
|
foo_bar: ?bool = null,
|
||||||
};
|
};
|
||||||
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqual(@as(?bool, true), parsed_data.parsed_value.foo_bar);
|
try testing.expectEqual(@as(?bool, true), parsed_data.parsed_value.foo_bar);
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ test "can coerce 8601 date to integer" {
|
||||||
const ExampleDoesNotMatter = struct {
|
const ExampleDoesNotMatter = struct {
|
||||||
foo_bar: ?i64 = null,
|
foo_bar: ?i64 = null,
|
||||||
};
|
};
|
||||||
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqual(@as(i64, 1633451985), parsed_data.parsed_value.foo_bar.?);
|
try testing.expectEqual(@as(i64, 1633451985), parsed_data.parsed_value.foo_bar.?);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ test "can parse a boolean type (two fields)" {
|
||||||
foo_bar: bool,
|
foo_bar: bool,
|
||||||
foo_baz: bool,
|
foo_baz: bool,
|
||||||
};
|
};
|
||||||
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqual(@as(bool, true), parsed_data.parsed_value.foo_bar);
|
try testing.expectEqual(@as(bool, true), parsed_data.parsed_value.foo_bar);
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,7 @@ test "can error without leaking memory" {
|
||||||
defer log_parse_traces = true;
|
defer log_parse_traces = true;
|
||||||
try std.testing.expectError(
|
try std.testing.expectError(
|
||||||
error.InvalidCharacter,
|
error.InvalidCharacter,
|
||||||
parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual }),
|
parse(ExampleDoesNotMatter, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ test "can parse a nested type" {
|
||||||
bar: []const u8,
|
bar: []const u8,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.bar);
|
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.bar);
|
||||||
}
|
}
|
||||||
|
@ -539,7 +539,7 @@ test "can parse a nested type - two fields" {
|
||||||
qux: []const u8,
|
qux: []const u8,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate_ptr = fuzzyEqual });
|
const parsed_data = try parse(Example, data, .{ .allocator = allocator, .match_predicate = fuzzyEqual });
|
||||||
defer parsed_data.deinit();
|
defer parsed_data.deinit();
|
||||||
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.bar);
|
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.bar);
|
||||||
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.qux);
|
try testing.expectEqualStrings("baz", parsed_data.parsed_value.foo.qux);
|
||||||
|
|
1
zfetch_deps.zig
Normal file
1
zfetch_deps.zig
Normal file
|
@ -0,0 +1 @@
|
||||||
|
const use_submodules = 1;
|
Loading…
Add table
Reference in a new issue