| ... | @@ -2,10 +2,57 @@ const std = @import("std"); | ... | @@ -2,10 +2,57 @@ const std = @import("std"); |
| 2 | const string = []const u8; | 2 | const string = []const u8; |
| 3 | | 3 | |
| 4 | /// Returns the result of running `git rev-parse HEAD` | 4 | /// Returns the result of running `git rev-parse HEAD` |
| | 5 | /// dir must already be pointing at the .git folder |
| 5 | pub fn getHEAD(alloc: std.mem.Allocator, dir: std.fs.Dir) !string { | 6 | pub fn getHEAD(alloc: std.mem.Allocator, dir: std.fs.Dir) !string { |
| 6 | var dirg = try dir.openDir(".git", .{}); | 7 | const h = std.mem.trimRight(u8, try dir.readFileAlloc(alloc, "HEAD", 1024), "\n"); |
| 7 | defer dirg.close(); | 8 | |
| 8 | const h = std.mem.trimRight(u8, try dirg.readFileAlloc(alloc, "HEAD", 1024), "\n"); | 9 | if (std.mem.startsWith(u8, h, "ref:")) { |
| 9 | const r = std.mem.trimRight(u8, try dirg.readFileAlloc(alloc, h[5..], 1024), "\n"); | 10 | return std.mem.trimRight(u8, try dir.readFileAlloc(alloc, h[5..], 1024), "\n"); |
| 10 | return r; | 11 | } |
| | 12 | |
| | 13 | // content should be 40-char sha1 hash |
| | 14 | std.debug.assert(h.len == 40); |
| | 15 | return h; |
| | 16 | } |
| | 17 | |
| | 18 | // TODO make this inspect .git/objects |
| | 19 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| | 20 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| | 21 | pub fn getObject(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: string) !string { |
| | 22 | const result = try std.ChildProcess.exec(.{ |
| | 23 | .allocator = alloc, |
| | 24 | .cwd_dir = dir, |
| | 25 | .argv = &.{ "git", "cat-file", "-p", obj }, |
| | 26 | }); |
| | 27 | return result.stdout; |
| 11 | } | 28 | } |
| | 29 | |
| | 30 | pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit { |
| | 31 | var iter = std.mem.split(u8, commitfile, "\n"); |
| | 32 | var result: Commit = undefined; |
| | 33 | var parents = std.ArrayList(string).init(alloc); |
| | 34 | errdefer parents.deinit(); |
| | 35 | while (true) { |
| | 36 | const line = iter.next().?; |
| | 37 | if (line.len == 0) break; |
| | 38 | const space = std.mem.indexOfScalar(u8, line, ' ').?; |
| | 39 | const k = line[0..space]; |
| | 40 | |
| | 41 | if (std.mem.eql(u8, k, "tree")) result.tree = line[space + 1 ..]; |
| | 42 | if (std.mem.eql(u8, k, "author")) result.author = line[space + 1 ..]; |
| | 43 | if (std.mem.eql(u8, k, "committer")) result.committer = line[space + 1 ..]; |
| | 44 | if (std.mem.eql(u8, k, "parent")) try parents.append(line[space + 1 ..]); |
| | 45 | } |
| | 46 | result.parents = try parents.toOwnedSlice(); |
| | 47 | result.message = iter.rest(); |
| | 48 | return result; |
| | 49 | } |
| | 50 | |
| | 51 | pub const Commit = struct { |
| | 52 | tree: string, |
| | 53 | parents: []const string, |
| | 54 | author: string, |
| | 55 | committer: string, |
| | 56 | gpgsig: string, |
| | 57 | message: string, |
| | 58 | }; |