authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-18 22:07:27 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-18 22:07:27 -07:00
log5df10192f349aabc63abcae624cac9de205d9df6
tree59bf864144d29956bab5a013f9c791672bb86c3f
parent02b234d0a75d4c93ddcbe62d010e4445c0e94fc9

add getTags()


1 files changed, 68 insertions(+), 1 deletions(-)

git.zig+68-1
......@@ -9,6 +9,7 @@ pub const Id = *const [40]u8;
99pub const TreeId = struct { id: Id };
1010pub const CommitId = struct { id: Id };
1111pub const BlobId = struct { id: Id };
12pub const TagId = struct { id: Id };
1213
1314pub fn version(alloc: std.mem.Allocator) !string {
1415 const result = try std.ChildProcess.exec(.{
......@@ -101,6 +102,20 @@ pub fn isType(alloc: std.mem.Allocator, dir: std.fs.Dir, maybeobj: Id, typ: Tree
101102 return std.meta.stringToEnum(Tree.Object.Id.Tag, output).? == typ;
102103}
103104
105// TODO make this inspect .git manually
106// https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
107// https://git-scm.com/book/en/v2/Git-Internals-Packfiles
108pub fn getType(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !Tree.Object.Id.Tag {
109 const result = try std.ChildProcess.exec(.{
110 .allocator = alloc,
111 .cwd_dir = dir,
112 .argv = &.{ "git", "cat-file", "-t", obj },
113 });
114 std.debug.assert(result.term == .Exited and result.term.Exited == 0);
115 const output = std.mem.trimRight(u8, result.stdout, "\n");
116 return std.meta.stringToEnum(Tree.Object.Id.Tag, output) orelse @panic(output);
117}
118
104119// TODO make this inspect .git/objects manually
105120// TODO make this return a Reader when we implement it ourselves
106121// TODO make a version of this that accepts an array of sub_paths and searches all of them at once, so as to not lose spot in history when searching for many old paths
......@@ -247,6 +262,7 @@ pub const Tree = struct {
247262 blob: BlobId,
248263 tree: TreeId,
249264 commit: CommitId,
265 tag: TagId,
250266
251267 pub const Tag = std.meta.Tag(@This());
252268
......@@ -578,15 +594,66 @@ pub fn getBranches(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref {
578594 errdefer list.deinit();
579595 while (iter.next()) |line| {
580596 var jter = std.mem.split(u8, line, " ");
581 try list.append(.{
597 try list.append(Ref{
582598 .commit = ensureObjId(CommitId, jter.next().?),
583599 .label = extras.trimPrefixEnsure(jter.rest(), "refs/heads/").?,
600 .tag = null,
584601 });
585602 }
586603 return list.toOwnedSlice();
587604}
588605
606pub fn getTags(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref {
607 const result = try std.ChildProcess.exec(.{
608 .allocator = alloc,
609 .cwd_dir = dir,
610 .argv = &.{ "git", "show-ref", "--tags", "--dereference" },
611 .max_output_bytes = 1024 * 1024 * 1024,
612 });
613 std.debug.assert(result.term == .Exited and result.term.Exited == 0);
614 const output = std.mem.trimRight(u8, result.stdout, "\n");
615 var iter = std.mem.split(u8, output, "\n");
616 var list = std.ArrayList(Ref).init(alloc);
617 errdefer list.deinit();
618 while (iter.next()) |line| {
619 var jter = std.mem.split(u8, line, " ");
620 const id = ensureObjId(CommitId, jter.next().?).id;
621 const label = extras.trimPrefixEnsure(jter.rest(), "refs/tags/").?;
622 extras.assertLog(!std.mem.endsWith(u8, label, "^{}"), label);
623
624 switch (try getType(alloc, dir, id)) {
625 .tree => continue,
626 .blob => unreachable,
627 .commit => {
628 try list.append(Ref{
629 .label = label,
630 .commit = ensureObjId(CommitId, id),
631 .tag = null,
632 });
633 },
634 .tag => {
635 const derefline = iter.next().?;
636 var kter = std.mem.split(u8, derefline, " ");
637 const id2 = ensureObjId(CommitId, kter.next().?).id;
638 const label2 = extras.trimPrefixEnsure(kter.rest(), "refs/tags/").?;
639 extras.assertLog(std.mem.endsWith(u8, label2, "^{}"), label2);
640 std.debug.assert(std.mem.eql(u8, label, extras.trimSuffixEnsure(label2, "^{}").?));
641 // extras.assertLog(try isType(alloc, dir, id2, .commit), id2); // linux kernel has a single tag that points at a tree
642 if (!(try isType(alloc, dir, id2, .commit)).?) continue;
643
644 try list.append(Ref{
645 .label = label,
646 .commit = ensureObjId(CommitId, id2),
647 .tag = ensureObjId(TagId, id),
648 });
649 },
650 }
651 }
652 return list.toOwnedSlice();
653}
654
589655pub const Ref = struct {
590656 label: string,
591657 commit: CommitId,
658 tag: ?TagId,
592659};