commit 871ebbae8d66341336b5e29535300d7c284d0fa1
parent 040307b324692a6146ddcb903f190879547dea7a
Author: Martin Ashby <martin@ashbysoft.com>
Date: Tue, 27 Aug 2024 22:01:09 +0100
Implement tag listing
Rename GitTree -> Tree to be more consistent
Diffstat:
M | src/root.zig | | | 177 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
1 file changed, 110 insertions(+), 67 deletions(-)
diff --git a/src/root.zig b/src/root.zig
@@ -53,6 +53,15 @@ pub fn doMain() !void {
var show_ref: argparse.Subcommand = .{ .parent = &ap, .description = "List references in a local repository", .name = "show-ref" };
try ap.addSubcommand(&show_ref);
+ var tag: argparse.Subcommand = .{ .parent = &ap, .description = "Manage tags", .name = "tag" };
+ try ap.addSubcommand(&tag);
+ var tag_name: argparse.Positional = .{ .name = "name", .description = "name for the new tag" };
+ try tag.addPositional(&tag_name);
+ var tag_object: argparse.Positional = .{ .name = "object", .description = "the object to add a tag for" };
+ try tag.addPositional(&tag_object);
+ var tag_kind: argparse.Flag = .{ .long = "add", .short = "a", .description = "whether to create a tag object", .hasarg = false };
+ try tag.addFlag(&tag_kind);
+
if (!try ap.parseOrHelp()) {
return;
}
@@ -107,6 +116,12 @@ pub fn doMain() !void {
}
} else if (show_ref.wasExecuted) {
try doShowRef(a, std.fs.cwd(), std.io.getStdOut().writer());
+ } else if (tag.wasExecuted) {
+ if (tag_name.value) |tagname| {
+ try doAddTag(a, std.fs.cwd(), std.io.getStdOut().writer(), tagname, tag_object.value);
+ } else {
+ try doListTags(a, std.fs.cwd(), std.io.getStdOut().writer());
+ }
} else {
if (ap.excess.items.len > 0) {
std.log.err("Unsupported sub-command {s}, have you tried implementing it yourself?", .{ap.excess.items[0]});
@@ -117,6 +132,33 @@ pub fn doMain() !void {
}
}
+fn doListTags(a: std.mem.Allocator, dir: std.fs.Dir, writer: anytype) !void {
+ var repo = try repo_find(a, dir);
+ defer repo.deinit();
+ var refs = try repo.ref_list(a);
+ defer {
+ // TODO could do with a more convenient wrapper probably, maybe even an arena
+ for (refs.keys()) |k| a.free(k);
+ refs.deinit();
+ }
+ for (refs.keys()) |k| {
+ // tags/
+ const tags_prefix = "tags/";
+ if (std.mem.startsWith(u8, k, tags_prefix)) {
+ try std.fmt.format(writer, "{s}\n", .{k[tags_prefix.len..]});
+ }
+ }
+}
+
+fn doAddTag(a: std.mem.Allocator, dir: std.fs.Dir, writer: anytype, tagname: []const u8, tagobj: ?[]const u8) !void {
+ _ = a;
+ _ = dir;
+ _ = writer;
+ _ = tagname;
+ _ = tagobj;
+ return error.Unimplemented;
+}
+
fn doShowRef(a: std.mem.Allocator, dir: std.fs.Dir, writer: anytype) !void {
var repo = try repo_find(a, dir);
defer repo.deinit();
@@ -154,7 +196,7 @@ fn doCheckout(a: std.mem.Allocator, dir: std.fs.Dir, commit_ref: []const u8, che
fn doCheckoutInternal(a: std.mem.Allocator, repo: *GitRepository, go: *GitObject, dir: std.fs.Dir) !void {
if (go.kind != .tree) return error.NotATree;
- var gt = try GitTree.parse(a, go.reader());
+ var gt = try Tree.parse(a, go.reader());
defer gt.deinit();
for (gt.leaves.items) |leaf| {
var go2 = try repo.read_object_sha(a, leaf.sha);
@@ -199,7 +241,7 @@ fn lsTree(a: std.mem.Allocator, dir: Dir, ref: []const u8, writer: anytype, recu
fn lsTreeInternal(a: std.mem.Allocator, repo: *GitRepository, go: *GitObject, writer: anytype, recurse: bool, path_prefix: []const u8) !void {
if (go.kind != .tree) return error.NotATree;
- var gt = try GitTree.parse(a, go.reader());
+ var gt = try Tree.parse(a, go.reader());
defer gt.deinit();
for (gt.leaves.items) |leaf| {
const filetype_str = switch (leaf.filetype) {
@@ -512,7 +554,6 @@ pub const GitRepository = struct {
try res.put(key, ref);
}
}
- //`fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool`
const Srt = struct {
map: std.StringArrayHashMap([20]u8),
pub fn lessThan(slf: *@This(), ai: usize, bi: usize) bool {
@@ -588,65 +629,6 @@ const ObjectKind = enum {
blob,
};
-const Commit = struct {
- _kvlm: Kvlm,
- tree: []const u8,
- parents: std.ArrayListUnmanaged([]const u8),
- author: []const u8,
- committer: ?[]const u8,
- gpgsig: ?[]const u8,
- message: []const u8,
-
- pub fn parse(a: std.mem.Allocator, z_reader: anytype) !Commit {
- var kvlm = try Kvlm.parse(a, z_reader);
- errdefer kvlm.deinit(a);
- return .{
- ._kvlm = kvlm,
- .tree = if (kvlm.headers.get("tree")) |tree| tree.items[0] else return error.InvalidCommit,
- .parents = kvlm.headers.get("parent") orelse .{},
- .author = if (kvlm.headers.get("author")) |tree| tree.items[0] else return error.InvalidCommit,
- .committer = if (kvlm.headers.get("committer")) |tree| tree.items[0] else null,
- .gpgsig = if (kvlm.headers.get("gpgsig")) |tree| tree.items[0] else null,
- .message = kvlm.message,
- };
- }
-
- pub fn deinit(self: *Commit, a: std.mem.Allocator) void {
- self._kvlm.deinit(a);
- }
-};
-
-test "parse commit" {
- const commit_str =
- \\tree 29ff16c9c14e2652b22f8b78bb08a5a07930c147
- \\parent 206941306e8a8af65b66eaaaea388a7ae24d49a0
- \\author Thibault Polge <thibault@thb.lt> 1527025023 +0200
- \\committer Thibault Polge <thibault@thb.lt> 1527025044 +0200
- \\gpgsig -----BEGIN PGP SIGNATURE-----
- \\
- \\ iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL
- \\ kGQdcBAAqPP+ln4nGDd2gETXjvOpOxLzIMEw4A9gU6CzWzm+oB8mEIKyaH0UFIPh
- \\ rNUZ1j7/ZGFNeBDtT55LPdPIQw4KKlcf6kC8MPWP3qSu3xHqx12C5zyai2duFZUU
- \\ wqOt9iCFCscFQYqKs3xsHI+ncQb+PGjVZA8+jPw7nrPIkeSXQV2aZb1E68wa2YIL
- \\ 3eYgTUKz34cB6tAq9YwHnZpyPx8UJCZGkshpJmgtZ3mCbtQaO17LoihnqPn4UOMr
- \\ V75R/7FjSuPLS8NaZF4wfi52btXMSxO/u7GuoJkzJscP3p4qtwe6Rl9dc1XC8P7k
- \\ NIbGZ5Yg5cEPcfmhgXFOhQZkD0yxcJqBUcoFpnp2vu5XJl2E5I/quIyVxUXi6O6c
- \\ /obspcvace4wy8uO0bdVhc4nJ+Rla4InVSJaUaBeiHTW8kReSFYyMmDCzLjGIu1q
- \\ doU61OM3Zv1ptsLu3gUE6GU27iWYj2RWN3e3HE4Sbd89IFwLXNdSuM0ifDLZk7AQ
- \\ WBhRhipCCgZhkj9g2NEk7jRVslti1NdN5zoQLaJNqSwO1MtxTmJ15Ksk3QP6kfLB
- \\ Q52UWybBzpaP9HEd4XnR+HuQ4k2K0ns2KgNImsNvIyFwbpMUyUWLMPimaV1DWUXo
- \\ 5SBjDB/V/W2JBFR+XKHFJeFwYhj7DD/ocsGr4ZMx/lgc8rjIBkI=
- \\ =lgTX
- \\ -----END PGP SIGNATURE-----
- \\
- \\Create first draft
- ;
- var fbs = std.io.fixedBufferStream(commit_str);
- const rdr = fbs.reader();
- var commit = try Commit.parse(std.testing.allocator, rdr);
- defer commit.deinit(std.testing.allocator);
-}
-
const Kvlm = struct {
headers: std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged([]const u8)),
message: []const u8,
@@ -733,7 +715,68 @@ const Kvlm = struct {
}
};
-pub const GitTree = struct {
+const Commit = struct {
+ _kvlm: Kvlm,
+ tree: []const u8,
+ parents: std.ArrayListUnmanaged([]const u8),
+ author: []const u8,
+ committer: ?[]const u8,
+ gpgsig: ?[]const u8,
+ message: []const u8,
+
+ pub fn parse(a: std.mem.Allocator, z_reader: anytype) !Commit {
+ var kvlm = try Kvlm.parse(a, z_reader);
+ errdefer kvlm.deinit(a);
+ return .{
+ ._kvlm = kvlm,
+ .tree = if (kvlm.headers.get("tree")) |tree| tree.items[0] else return error.InvalidCommit,
+ .parents = kvlm.headers.get("parent") orelse .{},
+ .author = if (kvlm.headers.get("author")) |tree| tree.items[0] else return error.InvalidCommit,
+ .committer = if (kvlm.headers.get("committer")) |tree| tree.items[0] else null,
+ .gpgsig = if (kvlm.headers.get("gpgsig")) |tree| tree.items[0] else null,
+ .message = kvlm.message,
+ };
+ }
+
+ pub fn deinit(self: *Commit, a: std.mem.Allocator) void {
+ self._kvlm.deinit(a);
+ }
+};
+
+const Tag = Commit; // same structure and everything
+
+test "parse commit" {
+ const commit_str =
+ \\tree 29ff16c9c14e2652b22f8b78bb08a5a07930c147
+ \\parent 206941306e8a8af65b66eaaaea388a7ae24d49a0
+ \\author Thibault Polge <thibault@thb.lt> 1527025023 +0200
+ \\committer Thibault Polge <thibault@thb.lt> 1527025044 +0200
+ \\gpgsig -----BEGIN PGP SIGNATURE-----
+ \\
+ \\ iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL
+ \\ kGQdcBAAqPP+ln4nGDd2gETXjvOpOxLzIMEw4A9gU6CzWzm+oB8mEIKyaH0UFIPh
+ \\ rNUZ1j7/ZGFNeBDtT55LPdPIQw4KKlcf6kC8MPWP3qSu3xHqx12C5zyai2duFZUU
+ \\ wqOt9iCFCscFQYqKs3xsHI+ncQb+PGjVZA8+jPw7nrPIkeSXQV2aZb1E68wa2YIL
+ \\ 3eYgTUKz34cB6tAq9YwHnZpyPx8UJCZGkshpJmgtZ3mCbtQaO17LoihnqPn4UOMr
+ \\ V75R/7FjSuPLS8NaZF4wfi52btXMSxO/u7GuoJkzJscP3p4qtwe6Rl9dc1XC8P7k
+ \\ NIbGZ5Yg5cEPcfmhgXFOhQZkD0yxcJqBUcoFpnp2vu5XJl2E5I/quIyVxUXi6O6c
+ \\ /obspcvace4wy8uO0bdVhc4nJ+Rla4InVSJaUaBeiHTW8kReSFYyMmDCzLjGIu1q
+ \\ doU61OM3Zv1ptsLu3gUE6GU27iWYj2RWN3e3HE4Sbd89IFwLXNdSuM0ifDLZk7AQ
+ \\ WBhRhipCCgZhkj9g2NEk7jRVslti1NdN5zoQLaJNqSwO1MtxTmJ15Ksk3QP6kfLB
+ \\ Q52UWybBzpaP9HEd4XnR+HuQ4k2K0ns2KgNImsNvIyFwbpMUyUWLMPimaV1DWUXo
+ \\ 5SBjDB/V/W2JBFR+XKHFJeFwYhj7DD/ocsGr4ZMx/lgc8rjIBkI=
+ \\ =lgTX
+ \\ -----END PGP SIGNATURE-----
+ \\
+ \\Create first draft
+ ;
+ var fbs = std.io.fixedBufferStream(commit_str);
+ const rdr = fbs.reader();
+ var commit = try Commit.parse(std.testing.allocator, rdr);
+ defer commit.deinit(std.testing.allocator);
+}
+
+pub const Tree = struct {
pub const Leaf = struct {
pub const FileType = enum {
file,
@@ -761,8 +804,8 @@ pub const GitTree = struct {
aa: std.heap.ArenaAllocator,
leaves: std.ArrayListUnmanaged(Leaf) = .{},
- pub fn parse(ca: std.mem.Allocator, reader: anytype) !GitTree {
- var result: GitTree = .{
+ pub fn parse(ca: std.mem.Allocator, reader: anytype) !Tree {
+ var result: Tree = .{
.aa = std.heap.ArenaAllocator.init(ca),
};
errdefer result.aa.deinit();
@@ -787,7 +830,7 @@ pub const GitTree = struct {
return result;
}
- pub fn deinit(self: *GitTree) void {
+ pub fn deinit(self: *Tree) void {
self.aa.deinit();
}
};
@@ -795,7 +838,7 @@ pub const GitTree = struct {
test "parse tree" {
const a = std.testing.allocator;
var fbs = std.io.fixedBufferStream(@embedFile("sample.tree"));
- var tree = try GitTree.parse(a, fbs.reader());
+ var tree = try Tree.parse(a, fbs.reader());
defer tree.deinit();
}