| ... | @@ -41,6 +41,26 @@ pub const TagId = struct { | ... | @@ -41,6 +41,26 @@ pub const TagId = struct { |
| 41 | } | 41 | } |
| 42 | }; | 42 | }; |
| 43 | | 43 | |
| | 44 | pub const OidKind = enum { |
| | 45 | blob, |
| | 46 | tree, |
| | 47 | commit, |
| | 48 | tag, |
| | 49 | }; |
| | 50 | |
| | 51 | pub const AnyId = union(OidKind) { |
| | 52 | blob: BlobId, |
| | 53 | tree: TreeId, |
| | 54 | commit: CommitId, |
| | 55 | tag: TagId, |
| | 56 | |
| | 57 | pub fn erase(self: AnyId) Id { |
| | 58 | return switch (self) { |
| | 59 | inline else => |v| v.id, |
| | 60 | }; |
| | 61 | } |
| | 62 | }; |
| | 63 | |
| 44 | pub fn version(alloc: std.mem.Allocator) !string { | 64 | pub fn version(alloc: std.mem.Allocator) !string { |
| 45 | const result = try std.process.Child.run(.{ | 65 | const result = try std.process.Child.run(.{ |
| 46 | .allocator = alloc, | 66 | .allocator = alloc, |
| ... | @@ -139,7 +159,7 @@ pub fn getObjectSize(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !u64 { | ... | @@ -139,7 +159,7 @@ pub fn getObjectSize(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !u64 { |
| 139 | // TODO make this inspect .git manually | 159 | // TODO make this inspect .git manually |
| 140 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 160 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 141 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 161 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 142 | pub fn isType(alloc: std.mem.Allocator, dir: nfs.Dir, maybeobj: Id, typ: Tree.Object.Id.Tag) !bool { | 162 | pub fn isType(alloc: std.mem.Allocator, dir: nfs.Dir, maybeobj: Id, typ: OidKind) !bool { |
| 143 | const t = tracer.trace(@src(), " {s} = {s} ?", .{ maybeobj, @tagName(typ) }); | 163 | const t = tracer.trace(@src(), " {s} = {s} ?", .{ maybeobj, @tagName(typ) }); |
| 144 | defer t.end(); | 164 | defer t.end(); |
| 145 | | 165 | |
| ... | @@ -150,13 +170,13 @@ pub fn isType(alloc: std.mem.Allocator, dir: nfs.Dir, maybeobj: Id, typ: Tree.Ob | ... | @@ -150,13 +170,13 @@ pub fn isType(alloc: std.mem.Allocator, dir: nfs.Dir, maybeobj: Id, typ: Tree.Ob |
| 150 | }); | 170 | }); |
| 151 | std.debug.assert(result.term == .Exited and result.term.Exited == 0); | 171 | std.debug.assert(result.term == .Exited and result.term.Exited == 0); |
| 152 | const output = std.mem.trimRight(u8, result.stdout, "\n"); | 172 | const output = std.mem.trimRight(u8, result.stdout, "\n"); |
| 153 | return std.meta.stringToEnum(Tree.Object.Id.Tag, output).? == typ; | 173 | return std.meta.stringToEnum(OidKind, output).? == typ; |
| 154 | } | 174 | } |
| 155 | | 175 | |
| 156 | // TODO make this inspect .git manually | 176 | // TODO make this inspect .git manually |
| 157 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects | 177 | // https://git-scm.com/book/en/v2/Git-Internals-Git-Objects |
| 158 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles | 178 | // https://git-scm.com/book/en/v2/Git-Internals-Packfiles |
| 159 | pub fn getType(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !Tree.Object.Id.Tag { | 179 | pub fn getType(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !OidKind { |
| 160 | const t = tracer.trace(@src(), " {s}", .{obj}); | 180 | const t = tracer.trace(@src(), " {s}", .{obj}); |
| 161 | defer t.end(); | 181 | defer t.end(); |
| 162 | | 182 | |
| ... | @@ -167,7 +187,7 @@ pub fn getType(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !Tree.Object.Id. | ... | @@ -167,7 +187,7 @@ pub fn getType(alloc: std.mem.Allocator, dir: nfs.Dir, obj: Id) !Tree.Object.Id. |
| 167 | }); | 187 | }); |
| 168 | std.debug.assert(result.term == .Exited and result.term.Exited == 0); | 188 | std.debug.assert(result.term == .Exited and result.term.Exited == 0); |
| 169 | const output = std.mem.trimRight(u8, result.stdout, "\n"); | 189 | const output = std.mem.trimRight(u8, result.stdout, "\n"); |
| 170 | return std.meta.stringToEnum(Tree.Object.Id.Tag, output) orelse @panic(output); | 190 | return std.meta.stringToEnum(OidKind, output) orelse @panic(output); |
| 171 | } | 191 | } |
| 172 | | 192 | |
| 173 | // TODO make this inspect .git/objects manually | 193 | // TODO make this inspect .git/objects manually |
| ... | @@ -311,18 +331,18 @@ pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { | ... | @@ -311,18 +331,18 @@ pub fn parseTree(alloc: std.mem.Allocator, treefile: string) !Tree { |
| 311 | } | 331 | } |
| 312 | var jter = std.mem.splitScalar(u8, line, ' '); | 332 | var jter = std.mem.splitScalar(u8, line, ' '); |
| 313 | const mode = jter.next().?; | 333 | const mode = jter.next().?; |
| 314 | const otype = std.meta.stringToEnum(Tree.Object.Id.Tag, jter.next().?).?; | 334 | const otype = std.meta.stringToEnum(OidKind, jter.next().?).?; |
| 315 | const id_and_name = jter.rest(); | 335 | const id_and_name = jter.rest(); |
| 316 | const tab_pos = std.mem.indexOfScalar(u8, id_and_name, '\t').?; // why git. why. | 336 | const tab_pos = std.mem.indexOfScalar(u8, id_and_name, '\t').?; // why git. why. |
| 317 | std.debug.assert(tab_pos == 40); | 337 | std.debug.assert(tab_pos == 40); |
| 318 | const id = id_and_name[0..tab_pos][0..40]; | 338 | const id = id_and_name[0..tab_pos][0..40]; |
| 319 | const name = id_and_name[tab_pos + 1 ..]; | 339 | const name = id_and_name[tab_pos + 1 ..]; |
| 320 | | 340 | |
| 321 | inline for (std.meta.fields(Tree.Object.Id)) |item| { | 341 | inline for (std.meta.fields(AnyId)) |item| { |
| 322 | if (std.mem.eql(u8, item.name, @tagName(otype))) { | 342 | if (std.mem.eql(u8, item.name, @tagName(otype))) { |
| 323 | try children.append(.{ | 343 | try children.append(.{ |
| 324 | .mode = try parseTreeMode(mode), | 344 | .mode = try parseTreeMode(mode), |
| 325 | .id = @unionInit(Tree.Object.Id, item.name, item.type{ .id = id }), | 345 | .id = @unionInit(AnyId, item.name, item.type{ .id = id }), |
| 326 | .name = name, | 346 | .name = name, |
| 327 | }); | 347 | }); |
| 328 | } | 348 | } |
| ... | @@ -381,24 +401,9 @@ pub const Tree = struct { | ... | @@ -381,24 +401,9 @@ pub const Tree = struct { |
| 381 | | 401 | |
| 382 | pub const Object = struct { | 402 | pub const Object = struct { |
| 383 | mode: Mode, | 403 | mode: Mode, |
| 384 | id: @This().Id, | 404 | id: AnyId, |
| 385 | name: string, | 405 | name: string, |
| 386 | | 406 | |
| 387 | pub const Id = union(enum) { | | |
| 388 | blob: BlobId, | | |
| 389 | tree: TreeId, | | |
| 390 | commit: CommitId, | | |
| 391 | tag: TagId, | | |
| 392 | | | |
| 393 | pub const Tag = std.meta.Tag(@This()); | | |
| 394 | | | |
| 395 | pub fn erase(self: @This()) top.Id { | | |
| 396 | return switch (self) { | | |
| 397 | inline else => |v| v.id, | | |
| 398 | }; | | |
| 399 | } | | |
| 400 | }; | | |
| 401 | | | |
| 402 | pub const Mode = struct { | 407 | pub const Mode = struct { |
| 403 | type: Type, | 408 | type: Type, |
| 404 | perm_user: Perm, | 409 | perm_user: Perm, |