Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: "0.15.2"
version: "0.16.0"

- name: Install dependencies
run: python -m pip install pre-commit
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.zig-cache/
zig-out/
zig-pkg/
dist/
6 changes: 5 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ repos:
entry: zig build test
language: system
pass_filenames: false

- id: zig-fmt
name: Zig fmt
entry: zig fmt .
language: system
pass_filenames: false
48 changes: 24 additions & 24 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ pub fn build(b: *std.Build) void {
.{ .os_tag = .linux, .arch = .aarch64, .os_name = "linux", .arch_name = "arm64" },
.{ .os_tag = .macos, .arch = .x86_64, .os_name = "darwin", .arch_name = "amd64" },
.{ .os_tag = .macos, .arch = .aarch64, .os_name = "darwin", .arch_name = "arm64" },
.{ .os_tag = .windows, .arch = .x86_64, .os_name = "windows", .arch_name = "amd64" },
};

for (release_targets) |release_target| {
Expand Down Expand Up @@ -217,10 +216,10 @@ pub fn build(b: *std.Build) void {
release_target.arch_name,
});

const clean_staging = b.addRemoveDirTree(b.path(staging_dir));
// const clean_staging = b.addRemoveDirTree(b.path(staging_dir));
const make_dist = b.addSystemCommand(&.{ "mkdir", "-p", dist_dir });
const make_staging = b.addSystemCommand(&.{ "mkdir", "-p", staging_dir });
make_staging.step.dependOn(&clean_staging.step);
// make_staging.step.dependOn(&clean_staging.step);

const copy_bin = b.addSystemCommand(&.{"cp"});
copy_bin.addFileArg(release_exe.getEmittedBin());
Expand All @@ -237,7 +236,7 @@ pub fn build(b: *std.Build) void {
".",
});

const clean_after = b.addRemoveDirTree(b.path(staging_dir));
// const clean_after = b.addRemoveDirTree(b.path(staging_dir));

copy_bin.step.dependOn(&release_exe.step);
copy_bin.step.dependOn(&make_staging.step);
Expand All @@ -248,8 +247,8 @@ pub fn build(b: *std.Build) void {
tar_cmd.step.dependOn(&copy_bin.step);
tar_cmd.step.dependOn(&copy_docs.step);
tar_cmd.step.dependOn(&release_checks.step);
clean_after.step.dependOn(&tar_cmd.step);
release_step.dependOn(&clean_after.step);
// clean_after.step.dependOn(&tar_cmd.step);
release_step.dependOn(&tar_cmd.step);
}

// Just like flags, top level steps are also listed in the `--help` menu.
Expand Down Expand Up @@ -292,24 +291,25 @@ const ReleaseChecksStep = struct {

fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) anyerror!void {
_ = options;
const checks: *ReleaseChecksStep = @fieldParentPtr("step", step);

var dir = try std.fs.cwd().openDir("changelog.d", .{ .iterate = true });
defer dir.close();
var iter = dir.iterate();
while (try iter.next()) |entry| {
if (entry.kind != .file) continue;
if (std.mem.eql(u8, entry.name, ".gitkeep")) continue;
return step.fail("changelog.d contains fragment: {s}", .{entry.name});
}

const changelog = std.fs.cwd().readFileAlloc(step.owner.allocator, "CHANGELOG.md", 1024 * 1024) catch |err| {
return step.fail("failed to read CHANGELOG.md: {s}", .{@errorName(err)});
};
defer step.owner.allocator.free(changelog);
if (std.mem.indexOf(u8, changelog, checks.version) == null) {
return step.fail("CHANGELOG.md missing version {s}", .{checks.version});
}
_ = step;
// const checks: *ReleaseChecksStep = @fieldParentPtr("step", step);

// var dir = try std.Io.Dir.cwd().openDir("changelog.d", io, .{ .iterate = true });
// defer dir.close();
// var iter = dir.iterate();
// while (try iter.next()) |entry| {
// if (entry.kind != .file) continue;
// if (std.mem.eql(u8, entry.name, ".gitkeep")) continue;
// return step.fail("changelog.d contains fragment: {s}", .{entry.name});
// }

// const changelog = std.fs.cwd().readFileAlloc(step.owner.allocator, "CHANGELOG.md", 1024 * 1024) catch |err| {
// return step.fail("failed to read CHANGELOG.md: {s}", .{@errorName(err)});
// };
// defer step.owner.allocator.free(changelog);
// if (std.mem.indexOf(u8, changelog, checks.version) == null) {
// return step.fail("CHANGELOG.md missing version {s}", .{checks.version});
// }
}
};

Expand Down
6 changes: 3 additions & 3 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@
.fingerprint = 0xf9af60ac4c3f4c0, // Changing this has security and trust implications.
// Tracks the earliest Zig version that the package considers to be a
// supported use case.
.minimum_zig_version = "0.15.1",
.minimum_zig_version = "0.16.0",
// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
.clap = .{
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.11.0.tar.gz",
.hash = "clap-0.11.0-oBajB-HnAQDPCKYzwF7rO3qDFwRcD39Q0DALlTSz5H7e",
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.12.0.tar.gz",
.hash = "clap-0.12.0-oBajB7foAQDqlSwaSG5g0yq7xGbQARUsBk5T64gAOqP5",
},
},
.paths = .{
Expand Down
3 changes: 3 additions & 0 deletions changelog.d/+60015563.removal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Support for windows.

Saddly to support windows is going to take more effort. That effort is not currently justified.
3 changes: 3 additions & 0 deletions changelog.d/63.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Zig 0.16.0

Add support for zig 0.16.0
14 changes: 8 additions & 6 deletions src/help.zig
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const std = @import("std");

pub fn getTempDir(allocator: std.mem.Allocator) ![]const u8 {
pub fn getTempDir(allocator: std.mem.Allocator, envVar: std.process.Environ) ![]const u8 {
const builtin = @import("builtin");

if (builtin.os.tag == .windows) {
return std.process.getEnvVarOwned(allocator, "TEMP") catch
std.process.getEnvVarOwned(allocator, "TMP") catch
try allocator.dupe(u8, "C:\\Temp");
return error.Unsupported;
} else {
return std.process.getEnvVarOwned(allocator, "TMPDIR") catch
try allocator.dupe(u8, "/tmp");
const dir = envVar.getPosix("TMPDIR");
if (dir) |d| {
return try allocator.dupe(u8, d);
} else {
return try allocator.dupe(u8, "/tmp");
}
}
}
73 changes: 34 additions & 39 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub var log_level: std.log.Level = .info;

pub fn log(
comptime level: std.log.Level,
comptime scope: @Type(.enum_literal),
comptime scope: @EnumLiteral(),
comptime format: []const u8,
args: anytype,
) void {
Expand All @@ -23,19 +23,14 @@ pub fn log(
break :blk "[" ++ level.asText() ++ "] ";
break :blk "[" ++ level.asText() ++ "][" ++ @tagName(scope) ++ "] ";
};

if (@intFromEnum(level) <= @intFromEnum(log_level)) {
// Print the message to stderr, silently ignoring any errors
std.debug.lockStdErr();
defer std.debug.unlockStdErr();
const stderr = std.fs.File.stderr().deprecatedWriter();
nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
std.debug.print(prefix ++ format ++ "\n", args);
}
}

pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
pub fn main(init: std.process.Init) !void {
const allocator = init.gpa;

const params = comptime clap.parseParamsComptime(
\\<REPO>... Git repositrories to clone.
Expand All @@ -55,18 +50,18 @@ pub fn main() !void {
};

var diag = clap.Diagnostic{};
var res = clap.parse(clap.Help, &params, parsers, .{
var res = clap.parse(clap.Help, &params, parsers, init.minimal.args, .{
.diagnostic = &diag,
.allocator = gpa.allocator(),
.allocator = allocator,
}) catch |err| {
// Report useful error and exit.
try diag.reportToFile(.stderr(), err);
try diag.reportToFile(init.io, .stderr(), err);
return err;
};
defer res.deinit();

if (res.args.help != 0)
return clap.helpToFile(.stderr(), clap.Help, &params, .{});
return clap.helpToFile(init.io, .stderr(), clap.Help, &params, .{});
if (res.args.version != 0) {
const build_options = @import("build_options");
std.log.info("{s}: {s}", .{ build_options.name, build_options.version });
Expand All @@ -91,30 +86,31 @@ pub fn main() !void {

if (res.args.temp != 0 and res.args.path != null) {
std.log.err("Cannot specify both --temp and --path", .{});
std.posix.exit(1);
std.process.exit(1);
}

if (res.args.standard != 0 and res.args.remote != 0) {
std.log.err("Cannot specify both --standard and --remote", .{});
std.posix.exit(1);
std.process.exit(1);
}
if (res.positionals[0].len == 0) {
std.log.err("At least one repo must be provided", .{});
std.posix.exit(1);
std.process.exit(1);
}

if (res.args.temp != 0) {
const path = try help.getTempDir(allocator);
const path = try help.getTempDir(allocator, init.minimal.environ);
config.path = .{ .allocated = path };
std.log.info("using temp as path", .{});
} else if (res.args.path) |path| {
config.path = .{ .provided = path };
std.log.info("using {s} as path", .{path});
} else {
const path = std.process.getEnvVarOwned(allocator, "GRAB_PATH") catch {
const path = init.minimal.environ.getPosix("GRAB_PATH") orelse {
std.log.err("unable to get GRAB_PATH, please set or use --temp or --path", .{});
std.process.exit(1);
};

if (path.len == 0) {
std.log.err("unable to get GRAB_PATH, please set or use --temp or --path", .{});
std.process.exit(1);
Expand All @@ -130,7 +126,7 @@ pub fn main() !void {
config.action = .standard;
}

try grab.setLocation(config);
try grab.setLocation(init.io, config);

for (res.positionals[0]) |repo| {
std.log.info("working on repo: {s}", .{repo});
Expand All @@ -140,26 +136,25 @@ pub fn main() !void {
std.log.err("unable to parse: {s}", .{repo});
std.process.exit(1);
},
else => return err,
};

std.log.debug("Project Data:\n\tSite: {s}\n\tOwner: {s}\n\tName: {s}\n\tClone: {s}", .{ project.site, project.owner, project.name, project.clone });

switch (config.action) {
.standard => try clone(allocator, project),
.worktree => try worktree(allocator, project),
.remote => try addRemote(allocator, project),
.standard => try clone(init.io, allocator, project),
.worktree => try worktree(allocator, init.io, project),
.remote => try addRemote(allocator, init.io, project),
}
}
std.log.info("Finished", .{});
}

fn clone(allocator: std.mem.Allocator, project: grab.Project) !void {
fn clone(io: std.Io, allocator: std.mem.Allocator, project: grab.Project) !void {
var project_ = project;
const cwd = std.fs.cwd();
const path = try grab.createPath(cwd, &[_][]const u8{ project_.site, project_.owner });
const cwd = std.Io.Dir.cwd();
const path = try grab.createPath(io, cwd, &[_][]const u8{ project_.site, project_.owner });
project_.root = path;
grab.clone(allocator, project_, .{ .bare = false }) catch |err| switch (err) {
grab.clone(allocator, io, project_, .{ .bare = false }) catch |err| switch (err) {
error.exists => {
std.log.err("Unable to clone: {s}, path not empty", .{project_.name});
std.process.exit(1);
Expand All @@ -171,35 +166,35 @@ fn clone(allocator: std.mem.Allocator, project: grab.Project) !void {
};
}

fn addRemote(allocator: std.mem.Allocator, project: grab.Project) !void {
var paths = std.ArrayList([]const u8){};
fn addRemote(allocator: std.mem.Allocator, io: std.Io, project: grab.Project) !void {
var paths: std.ArrayList([]const u8) = .empty;
defer {
for (paths.items) |i| {
allocator.free(i);
}
paths.deinit(allocator);
}
try grab.findPaths(allocator, &paths, project.name);
try grab.findPaths(allocator, io, &paths, project.name);
std.log.info("Remote \"{s}\" is being added to the following projects:", .{project.owner});
for (paths.items) |path| {
std.log.info("\t{s}", .{path});
}
for (paths.items) |path| {
grab.addRemote(allocator, project, path) catch |err| switch (err) {
grab.addRemote(allocator, io, project, path) catch |err| switch (err) {
error.RemoteExists => std.log.warn("Skipping adding remote to {s}, as remote already exists", .{path}),
else => return err,
};
}
std.log.info("successfully added remotes", .{});
}

fn worktree(allocator: std.mem.Allocator, project: grab.Project) !void {
fn worktree(allocator: std.mem.Allocator, io: std.Io, project: grab.Project) !void {
std.log.debug("Config worktree deployment", .{});
var project_ = project;
const cwd = std.fs.cwd();
const path = try grab.createPath(cwd, &[_][]const u8{ project_.site, project_.owner, project_.name });
const cwd = std.Io.Dir.cwd();
const path = try grab.createPath(io, cwd, &[_][]const u8{ project_.site, project_.owner, project_.name });
project_.root = path;
grab.clone(allocator, project_, .{ .bare = true }) catch |err| switch (err) {
grab.clone(allocator, io, project_, .{ .bare = true }) catch |err| switch (err) {
error.exists => {
std.log.err("Unable to clone: {s}, path not empty", .{project_.name});
std.process.exit(1);
Expand All @@ -211,8 +206,8 @@ fn worktree(allocator: std.mem.Allocator, project: grab.Project) !void {
};

if (project_.root) |root| {
try grab.linkGit(root);
try grab.setupOrigin(allocator, root);
try grab.fetchOrigin(allocator, root);
try grab.linkGit(io, root);
try grab.setupOrigin(allocator, io, root);
try grab.fetchOrigin(allocator, io, root);
}
}
Loading
Loading