| ... | @@ -3,6 +3,7 @@ const string = []const u8; | ... | @@ -3,6 +3,7 @@ const string = []const u8; |
| 3 | const top = @This(); | 3 | const top = @This(); |
| 4 | const time = @import("time"); | 4 | const time = @import("time"); |
| 5 | const extras = @import("extras"); | 5 | const extras = @import("extras"); |
| | 6 | const tracer = @import("tracer"); |
| 6 | | 7 | |
| 7 | // 40 is length of sha1 hash | 8 | // 40 is length of sha1 hash |
| 8 | pub const Id = *const [40]u8; | 9 | pub const Id = *const [40]u8; |
| ... | @@ -27,6 +28,9 @@ pub fn version(alloc: std.mem.Allocator) !string { | ... | @@ -27,6 +28,9 @@ pub fn version(alloc: std.mem.Allocator) !string { |
| 27 | /// dir must already be pointing at the .git folder | 28 | /// dir must already be pointing at the .git folder |
| 28 | // TODO this doesnt handle when there are 0 commits | 29 | // TODO this doesnt handle when there are 0 commits |
| 29 | pub fn getHEAD(alloc: std.mem.Allocator, dir: std.fs.Dir) !?CommitId { | 30 | pub fn getHEAD(alloc: std.mem.Allocator, dir: std.fs.Dir) !?CommitId { |
| | 31 | const t = tracer.trace(@src()); |
| | 32 | defer t.end(); |
| | 33 | |
| 30 | const h = std.mem.trimRight(u8, try dir.readFileAlloc(alloc, "HEAD", 1024), "\n"); | 34 | const h = std.mem.trimRight(u8, try dir.readFileAlloc(alloc, "HEAD", 1024), "\n"); |
| 31 | | 35 | |
| 32 | if (std.mem.startsWith(u8, h, "ref:")) { | 36 | if (std.mem.startsWith(u8, h, "ref:")) { |
| ... | @@ -70,6 +74,9 @@ fn ensureObjId(comptime T: type, input: string) T { | ... | @@ -70,6 +74,9 @@ fn ensureObjId(comptime T: type, input: string) T { |
| 70 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 74 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 71 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 75 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 72 | pub fn getObject(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !string { | 76 | pub fn getObject(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !string { |
| | 77 | const t = tracer.trace(@src()); |
| | 78 | defer t.end(); |
| | 79 | |
| 73 | const result = try std.ChildProcess.exec(.{ | 80 | const result = try std.ChildProcess.exec(.{ |
| 74 | .allocator = alloc, | 81 | .allocator = alloc, |
| 75 | .cwd_dir = dir, | 82 | .cwd_dir = dir, |
| ... | @@ -85,6 +92,9 @@ pub fn getObject(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !string { | ... | @@ -85,6 +92,9 @@ pub fn getObject(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !string { |
| 85 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 92 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 86 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 93 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 87 | pub fn getObjectSize(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !u64 { | 94 | pub fn getObjectSize(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !u64 { |
| | 95 | const t = tracer.trace(@src()); |
| | 96 | defer t.end(); |
| | 97 | |
| 88 | const result = try std.ChildProcess.exec(.{ | 98 | const result = try std.ChildProcess.exec(.{ |
| 89 | .allocator = alloc, | 99 | .allocator = alloc, |
| 90 | .cwd_dir = dir, | 100 | .cwd_dir = dir, |
| ... | @@ -98,6 +108,9 @@ pub fn getObjectSize(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !u64 { | ... | @@ -98,6 +108,9 @@ pub fn getObjectSize(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !u64 { |
| 98 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 108 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 99 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 109 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 100 | pub fn isType(alloc: std.mem.Allocator, dir: std.fs.Dir, maybeobj: Id, typ: Tree.Object.Id.Tag) !?bool { | 110 | pub fn isType(alloc: std.mem.Allocator, dir: std.fs.Dir, maybeobj: Id, typ: Tree.Object.Id.Tag) !?bool { |
| | 111 | const t = tracer.trace(@src()); |
| | 112 | defer t.end(); |
| | 113 | |
| 101 | const result = try std.ChildProcess.exec(.{ | 114 | const result = try std.ChildProcess.exec(.{ |
| 102 | .allocator = alloc, | 115 | .allocator = alloc, |
| 103 | .cwd_dir = dir, | 116 | .cwd_dir = dir, |
| ... | @@ -112,6 +125,9 @@ pub fn isType(alloc: std.mem.Allocator, dir: std.fs.Dir, maybeobj: Id, typ: Tree | ... | @@ -112,6 +125,9 @@ pub fn isType(alloc: std.mem.Allocator, dir: std.fs.Dir, maybeobj: Id, typ: Tree |
| 112 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 125 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 113 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 126 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 114 | pub fn getType(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !Tree.Object.Id.Tag { | 127 | pub fn getType(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !Tree.Object.Id.Tag { |
| | 128 | const t = tracer.trace(@src()); |
| | 129 | defer t.end(); |
| | 130 | |
| 115 | const result = try std.ChildProcess.exec(.{ | 131 | const result = try std.ChildProcess.exec(.{ |
| 116 | .allocator = alloc, | 132 | .allocator = alloc, |
| 117 | .cwd_dir = dir, | 133 | .cwd_dir = dir, |
| ... | @@ -128,6 +144,9 @@ pub fn getType(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !Tree.Object. | ... | @@ -128,6 +144,9 @@ pub fn getType(alloc: std.mem.Allocator, dir: std.fs.Dir, obj: Id) !Tree.Object. |
| 128 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 144 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 129 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 145 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 130 | pub fn revList(alloc: std.mem.Allocator, dir: std.fs.Dir, comptime count: u31, from: CommitId, sub_path: string) !string { | 146 | pub fn revList(alloc: std.mem.Allocator, dir: std.fs.Dir, comptime count: u31, from: CommitId, sub_path: string) !string { |
| | 147 | const t = tracer.trace(@src()); |
| | 148 | defer t.end(); |
| | 149 | |
| 131 | const result = try std.ChildProcess.exec(.{ | 150 | const result = try std.ChildProcess.exec(.{ |
| 132 | .allocator = alloc, | 151 | .allocator = alloc, |
| 133 | .cwd_dir = dir, | 152 | .cwd_dir = dir, |
| ... | @@ -145,6 +164,9 @@ pub fn revList(alloc: std.mem.Allocator, dir: std.fs.Dir, comptime count: u31, f | ... | @@ -145,6 +164,9 @@ pub fn revList(alloc: std.mem.Allocator, dir: std.fs.Dir, comptime count: u31, f |
| 145 | } | 164 | } |
| 146 | | 165 | |
| 147 | pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit { | 166 | pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit { |
| | 167 | const t = tracer.trace(@src()); |
| | 168 | defer t.end(); |
| | 169 | |
| 148 | var iter = std.mem.split(u8, commitfile, "\n"); | 170 | var iter = std.mem.split(u8, commitfile, "\n"); |
| 149 | var result: Commit = undefined; | 171 | var result: Commit = undefined; |
| 150 | var parents = std.ArrayList(CommitId).init(alloc); | 172 | var parents = std.ArrayList(CommitId).init(alloc); |
| ... | @@ -166,6 +188,9 @@ pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit { | ... | @@ -166,6 +188,9 @@ pub fn parseCommit(alloc: std.mem.Allocator, commitfile: string) !Commit { |
| 166 | } | 188 | } |
| 167 | | 189 | |
| 168 | fn parseCommitUserAndAt(input: string) !Commit.UserAndAt { | 190 | fn parseCommitUserAndAt(input: string) !Commit.UserAndAt { |
| | 191 | const t = tracer.trace(@src()); |
| | 192 | defer t.end(); |
| | 193 | |
| 169 | // Mitchell Hashimoto <mitchell.hashimoto@gmail.com> 1680797363 -0700 | 194 | // Mitchell Hashimoto <mitchell.hashimoto@gmail.com> 1680797363 -0700 |
| 170 | // first and second part is https://datatracker.ietf.org/doc/html/rfc5322#section-3.4 | 195 | // first and second part is https://datatracker.ietf.org/doc/html/rfc5322#section-3.4 |
| 171 | // third part is unix epoch timestamp | 196 | // third part is unix epoch timestamp |
| ... | @@ -218,6 +243,9 @@ pub const Commit = struct { | ... | @@ -218,6 +243,9 @@ pub const Commit = struct { |
| 218 | }; | 243 | }; |
| 219 | | 244 | |
| 220 | pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { | 245 | pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { |
| | 246 | const t = tracer.trace(@src()); |
| | 247 | defer t.end(); |
| | 248 | |
| 221 | var iter = std.mem.split(u8, treefile, "\n"); | 249 | var iter = std.mem.split(u8, treefile, "\n"); |
| 222 | var children = std.ArrayList(Tree.Object).init(alloc); | 250 | var children = std.ArrayList(Tree.Object).init(alloc); |
| 223 | errdefer children.deinit(); | 251 | errdefer children.deinit(); |
| ... | @@ -249,6 +277,9 @@ pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { | ... | @@ -249,6 +277,9 @@ pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { |
| 249 | } | 277 | } |
| 250 | | 278 | |
| 251 | fn parseTreeMode(input: string) !Tree.Object.Mode { | 279 | fn parseTreeMode(input: string) !Tree.Object.Mode { |
| | 280 | const t = tracer.trace(@src()); |
| | 281 | defer t.end(); |
| | 282 | |
| 252 | std.debug.assert(input.len == 6); | 283 | std.debug.assert(input.len == 6); |
| 253 | return .{ | 284 | return .{ |
| 254 | .type = @enumFromInt(try std.fmt.parseInt(u16, input[0..3], 10)), | 285 | .type = @enumFromInt(try std.fmt.parseInt(u16, input[0..3], 10)), |
| ... | @@ -354,6 +385,9 @@ pub const Tree = struct { | ... | @@ -354,6 +385,9 @@ pub const Tree = struct { |
| 354 | // TODO make this inspect .git manually | 385 | // TODO make this inspect .git manually |
| 355 | // TODO make this return a Reader when we implement it ourselves | 386 | // TODO make this return a Reader when we implement it ourselves |
| 356 | pub fn getTreeDiff(alloc: std.mem.Allocator, dir: std.fs.Dir, commitid: CommitId, parentid: ?CommitId) !string { | 387 | pub fn getTreeDiff(alloc: std.mem.Allocator, dir: std.fs.Dir, commitid: CommitId, parentid: ?CommitId) !string { |
| | 388 | const t = tracer.trace(@src()); |
| | 389 | defer t.end(); |
| | 390 | |
| 357 | if (parentid == null) { | 391 | if (parentid == null) { |
| 358 | const result = try std.ChildProcess.exec(.{ | 392 | const result = try std.ChildProcess.exec(.{ |
| 359 | .allocator = alloc, | 393 | .allocator = alloc, |
| ... | @@ -377,6 +411,9 @@ pub fn getTreeDiff(alloc: std.mem.Allocator, dir: std.fs.Dir, commitid: CommitId | ... | @@ -377,6 +411,9 @@ pub fn getTreeDiff(alloc: std.mem.Allocator, dir: std.fs.Dir, commitid: CommitId |
| 377 | } | 411 | } |
| 378 | | 412 | |
| 379 | pub fn parseTreeDiffMeta(input: string) !TreeDiffMeta { | 413 | pub fn parseTreeDiffMeta(input: string) !TreeDiffMeta { |
| | 414 | const t = tracer.trace(@src()); |
| | 415 | defer t.end(); |
| | 416 | |
| 380 | var result = std.mem.zeroes(TreeDiffMeta); | 417 | var result = std.mem.zeroes(TreeDiffMeta); |
| 381 | var lineiter = std.mem.split(u8, input, "\n"); | 418 | var lineiter = std.mem.split(u8, input, "\n"); |
| 382 | | 419 | |
| ... | @@ -448,6 +485,9 @@ pub const TreeDiffMeta = struct { | ... | @@ -448,6 +485,9 @@ pub const TreeDiffMeta = struct { |
| 448 | }; | 485 | }; |
| 449 | | 486 | |
| 450 | pub fn parseTreeDiff(alloc: std.mem.Allocator, input: string) !TreeDiff { | 487 | pub fn parseTreeDiff(alloc: std.mem.Allocator, input: string) !TreeDiff { |
| | 488 | const t = tracer.trace(@src()); |
| | 489 | defer t.end(); |
| | 490 | |
| 451 | var lineiter = std.mem.split(u8, input, "\n"); | 491 | var lineiter = std.mem.split(u8, input, "\n"); |
| 452 | var overview = std.ArrayList(TreeDiff.StateLine).init(alloc); | 492 | var overview = std.ArrayList(TreeDiff.StateLine).init(alloc); |
| 453 | var diffs = std.ArrayList(TreeDiff.Diff).init(alloc); | 493 | var diffs = std.ArrayList(TreeDiff.Diff).init(alloc); |
| ... | @@ -604,6 +644,9 @@ pub const TreeDiff = struct { | ... | @@ -604,6 +644,9 @@ pub const TreeDiff = struct { |
| 604 | }; | 644 | }; |
| 605 | | 645 | |
| 606 | pub fn getBranches(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { | 646 | pub fn getBranches(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { |
| | 647 | const t = tracer.trace(@src()); |
| | 648 | defer t.end(); |
| | 649 | |
| 607 | const result = try std.ChildProcess.exec(.{ | 650 | const result = try std.ChildProcess.exec(.{ |
| 608 | .allocator = alloc, | 651 | .allocator = alloc, |
| 609 | .cwd_dir = dir, | 652 | .cwd_dir = dir, |
| ... | @@ -627,6 +670,13 @@ pub fn getBranches(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { | ... | @@ -627,6 +670,13 @@ pub fn getBranches(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { |
| 627 | } | 670 | } |
| 628 | | 671 | |
| 629 | pub fn getTags(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { | 672 | pub fn getTags(alloc: std.mem.Allocator, dir: std.fs.Dir) ![]const Ref { |
| | 673 | const t = tracer.trace(@src()); |
| | 674 | defer t.end(); |
| | 675 | |
| | 676 | // 97bc4b5f87656a34139e1a8122866c8c5b432598 refs/tags/1.2.5 |
| | 677 | // a450a23e318c5a8fcba5a52c8fdc2e23584650b3 refs/tags/1.2.5^{} |
| | 678 | // 71264720050572b7bad24532ff39951f47d9296a refs/tags/15.3.1 |
| | 679 | // 7dfd3948a9095f0253bfba60fed52895ffbf84bb refs/tags/15.3.2 |
| 630 | const result = try std.ChildProcess.exec(.{ | 680 | const result = try std.ChildProcess.exec(.{ |
| 631 | .allocator = alloc, | 681 | .allocator = alloc, |
| 632 | .cwd_dir = dir, | 682 | .cwd_dir = dir, |