| ... | @@ -833,6 +833,39 @@ pub const Ref = struct { | ... | @@ -833,6 +833,39 @@ pub const Ref = struct { |
| 833 | label: string, | 833 | label: string, |
| 834 | }; | 834 | }; |
| 835 | | 835 | |
| | 836 | pub fn parseTag(tagfile: string) !Tag { |
| | 837 | const t = tracer.trace(@src(), "", .{}); |
| | 838 | defer t.end(); |
| | 839 | |
| | 840 | var iter = std.mem.splitScalar(u8, tagfile, '\n'); |
| | 841 | var result: Tag = undefined; |
| | 842 | result.tagger = null; |
| | 843 | const object = extras.trimPrefixEnsure(iter.next().?, "object ").?; |
| | 844 | std.debug.assert(object.len == 40); |
| | 845 | result.object = object[0..40]; |
| | 846 | const ty = extras.trimPrefixEnsure(iter.next().?, "type ").?; |
| | 847 | result.type = std.meta.stringToEnum(OidKind, ty).?; |
| | 848 | const tag = extras.trimPrefixEnsure(iter.next().?, "tag ").?; |
| | 849 | _ = tag; |
| | 850 | |
| | 851 | while (true) { |
| | 852 | const line = iter.next() orelse break; |
| | 853 | if (line.len == 0) break; |
| | 854 | const space = std.mem.indexOfScalar(u8, line, ' ').?; |
| | 855 | const k = line[0..space]; |
| | 856 | if (std.mem.eql(u8, k, "tagger")) result.tagger = try parseCommitUserAndAt(line[space + 1 ..]); |
| | 857 | } |
| | 858 | result.message = iter.rest(); |
| | 859 | return result; |
| | 860 | } |
| | 861 | |
| | 862 | pub const Tag = struct { |
| | 863 | object: Id, |
| | 864 | type: OidKind, |
| | 865 | tagger: ?UserAndAt, |
| | 866 | message: string, |
| | 867 | }; |
| | 868 | |
| 836 | // TODO make this inspect .git/objects | 869 | // TODO make this inspect .git/objects |
| 837 | pub fn getBlame(alloc: std.mem.Allocator, dir: nfs.Dir, at: CommitId, sub_path: string) !string { | 870 | pub fn getBlame(alloc: std.mem.Allocator, dir: nfs.Dir, at: CommitId, sub_path: string) !string { |
| 838 | const t = tracer.trace(@src(), " {s} -- {s}", .{ at.id, sub_path }); | 871 | const t = tracer.trace(@src(), " {s} -- {s}", .{ at.id, sub_path }); |