authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-03 02:50:44 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-03 02:50:44 -07:00
log63c6242d86a976e268580fd24a2a8b7455fe1512
tree7b1aa8d770e2e174d1d96f8735ab9ceae6d87547
parent0af2b218d5efc4c7a60e25ffde8a048db4b45a77

parseCommit: better parse author and committer fields since we know the format

and its not based on any user input

2 files changed, 32 insertions(+), 4 deletions(-)

git.zig+31-4
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const string = []const u8;
33const top = @This();
4const time = @import("time");
45
56// 40 is length of sha1 hash
67pub const Id = *const [40]u8;
......@@ -99,8 +100,8 @@ pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit {
99100 const k = line[0..space];
100101
101102 if (std.mem.eql(u8, k, "tree")) result.tree = .{ .id = line[space + 1 ..][0..40] };
102 if (std.mem.eql(u8, k, "author")) result.author = line[space + 1 ..];
103 if (std.mem.eql(u8, k, "committer")) result.committer = line[space + 1 ..];
103 if (std.mem.eql(u8, k, "author")) result.author = try parseCommitUserAndAt(line[space + 1 ..]);
104 if (std.mem.eql(u8, k, "committer")) result.committer = try parseCommitUserAndAt(line[space + 1 ..]);
104105 if (std.mem.eql(u8, k, "parent")) try parents.append(.{ .id = line[space + 1 ..][0..40] });
105106 }
106107 result.parents = try parents.toOwnedSlice();
......@@ -108,13 +109,39 @@ pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit {
108109 return result;
109110}
110111
112fn parseCommitUserAndAt(input: string) !Commit.UserAndAt {
113 // Mitchell Hashimoto <mitchell.hashimoto@gmail.com> 1680797363 -0700
114 // first and second part is https://datatracker.ietf.org/doc/html/rfc5322#section-3.4
115 // third part is unix epoch timestamp
116 // fourth part is TZ
117 var maybe_bad_parser = std.mem.splitBackwards(u8, input, " ");
118 const tz_part = maybe_bad_parser.next() orelse return error.BadCommitTz;
119 const time_part = maybe_bad_parser.next() orelse return error.BadCommitTime;
120 const email_part = maybe_bad_parser.next() orelse return error.BadCommitEmail;
121 const name_part = maybe_bad_parser.rest();
122 _ = tz_part;
123 std.debug.assert(email_part[0] == '<');
124 std.debug.assert(email_part[email_part.len - 1] == '>');
125 return .{
126 .name = name_part,
127 .email = std.mem.trim(u8, email_part, "<>"),
128 .at = time.DateTime.initUnix(try std.fmt.parseInt(u64, time_part, 10)),
129 };
130}
131
111132pub const Commit = struct {
112133 tree: TreeId,
113134 parents: []const CommitId,
114 author: string,
115 committer: string,
135 author: UserAndAt,
136 committer: UserAndAt,
116137 gpgsig: string,
117138 message: string,
139
140 pub const UserAndAt = struct {
141 name: string,
142 email: string,
143 at: time.DateTime,
144 };
118145};
119146
120147pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree {
zig.mod+1
......@@ -4,3 +4,4 @@ main: git.zig
44license: MIT
55description: Inspect into the depths of your .git folder purely from Zig
66dependencies:
7 - src: git https://github.com/nektro/zig-time