| ... | @@ -242,20 +242,6 @@ fn parseAt(time_part: string, tz_part: string) time.DateTime { | ... | @@ -242,20 +242,6 @@ fn parseAt(time_part: string, tz_part: string) time.DateTime { |
| 242 | return at; | 242 | return at; |
| 243 | } | 243 | } |
| 244 | | 244 | |
| 245 | pub const Commit = struct { | | |
| 246 | tree: TreeId, | | |
| 247 | parents: []const CommitId, | | |
| 248 | author: UserAndAt, | | |
| 249 | committer: UserAndAt, | | |
| 250 | message: string, | | |
| 251 | }; | | |
| 252 | | | |
| 253 | pub const UserAndAt = struct { | | |
| 254 | name: string, | | |
| 255 | email: string, | | |
| 256 | at: time.DateTime, | | |
| 257 | }; | | |
| 258 | | | |
| 259 | fn parseTreeMode(input: string) !Tree.Object.Mode { | 245 | fn parseTreeMode(input: string) !Tree.Object.Mode { |
| 260 | const t = tracer.trace(@src(), "", .{}); | 246 | const t = tracer.trace(@src(), "", .{}); |
| 261 | defer t.end(); | 247 | defer t.end(); |
| ... | @@ -269,133 +255,6 @@ fn parseTreeMode(input: string) !Tree.Object.Mode { | ... | @@ -269,133 +255,6 @@ fn parseTreeMode(input: string) !Tree.Object.Mode { |
| 269 | }; | 255 | }; |
| 270 | } | 256 | } |
| 271 | | 257 | |
| 272 | pub const Tree = struct { | | |
| 273 | children: MultiArrayList(Object), | | |
| 274 | | | |
| 275 | pub fn get(self: Tree, name: string) ?Object { | | |
| 276 | if (self.children.len() <= 1000) { | | |
| 277 | for (self.children.items.name, 0..) |a_name, i| { | | |
| 278 | if (std.mem.eql(u8, a_name, name)) { | | |
| 279 | return self.children.get(i); | | |
| 280 | } | | |
| 281 | } | | |
| 282 | return null; | | |
| 283 | } | | |
| 284 | const i = std.sort.binarySearch([]const u8, self.children.items.name, name, extras.compareFnSlice(u8)) orelse return null; | | |
| 285 | return self.children.get(i); | | |
| 286 | } | | |
| 287 | | | |
| 288 | pub fn getBlob(self: Tree, name: string) ?Object { | | |
| 289 | const o = self.get(name) orelse return null; | | |
| 290 | if (o.id != .blob) return null; | | |
| 291 | return o; | | |
| 292 | } | | |
| 293 | | | |
| 294 | pub fn find(self: Tree, name: string) ?Object { | | |
| 295 | for (self.children.items.name, 0..) |item, i| { | | |
| 296 | if (std.ascii.eqlIgnoreCase(item, name)) { | | |
| 297 | return self.children.get(i); | | |
| 298 | } | | |
| 299 | } | | |
| 300 | return null; | | |
| 301 | } | | |
| 302 | | | |
| 303 | pub fn findBlob(self: Tree, name: string) ?Object { | | |
| 304 | const o = self.find(name) orelse return null; | | |
| 305 | if (o.id != .blob) return null; | | |
| 306 | return o; | | |
| 307 | } | | |
| 308 | | | |
| 309 | pub const Object = struct { | | |
| 310 | mode: Mode, | | |
| 311 | id: AnyId, | | |
| 312 | name: [:0]const u8, | | |
| 313 | | | |
| 314 | pub const Mode = struct { | | |
| 315 | type: Type, | | |
| 316 | perm_user: Perm, | | |
| 317 | perm_group: Perm, | | |
| 318 | perm_other: Perm, | | |
| 319 | | | |
| 320 | pub fn format(self: Mode, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { | | |
| 321 | _ = fmt; | | |
| 322 | _ = options; | | |
| 323 | try writer.print("{}", .{self.type}); | | |
| 324 | try writer.print("{}", .{self.perm_user}); | | |
| 325 | try writer.print("{}", .{self.perm_group}); | | |
| 326 | try writer.print("{}", .{self.perm_other}); | | |
| 327 | } | | |
| 328 | | | |
| 329 | pub fn nprint(self: Mode, writer: anytype) !void { | | |
| 330 | try self.type.nprint(writer); | | |
| 331 | try self.perm_user.nprint(writer); | | |
| 332 | try self.perm_group.nprint(writer); | | |
| 333 | try self.perm_other.nprint(writer); | | |
| 334 | } | | |
| 335 | | | |
| 336 | pub fn eql(self: Mode, other: Mode) bool { | | |
| 337 | if (self.type != other.type) return false; | | |
| 338 | if (self.perm_user != other.perm_user) return false; | | |
| 339 | if (self.perm_group != other.perm_group) return false; | | |
| 340 | if (self.perm_other != other.perm_other) return false; | | |
| 341 | return true; | | |
| 342 | } | | |
| 343 | }; | | |
| 344 | | | |
| 345 | pub const Type = enum(u8) { | | |
| 346 | file = 100, | | |
| 347 | directory = 40, | | |
| 348 | submodule = 160, | | |
| 349 | symlink = 120, | | |
| 350 | none = 0, | | |
| 351 | | | |
| 352 | pub fn format(self: Type, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { | | |
| 353 | _ = fmt; | | |
| 354 | _ = options; | | |
| 355 | try writer.writeByte(switch (self) { | | |
| 356 | .file => '-', | | |
| 357 | .directory => 'd', | | |
| 358 | .submodule => 'm', | | |
| 359 | .symlink => '-', | | |
| 360 | .none => '-', | | |
| 361 | }); | | |
| 362 | } | | |
| 363 | | | |
| 364 | pub fn nprint(self: Type, writer: anytype) !void { | | |
| 365 | try writer.writeAll(&.{switch (self) { | | |
| 366 | .file => '-', | | |
| 367 | .directory => 'd', | | |
| 368 | .submodule => 'm', | | |
| 369 | .symlink => '-', | | |
| 370 | .none => '-', | | |
| 371 | }}); | | |
| 372 | } | | |
| 373 | }; | | |
| 374 | | | |
| 375 | pub const Perm = packed struct(u3) { | | |
| 376 | execute: bool, | | |
| 377 | write: bool, | | |
| 378 | read: bool, | | |
| 379 | | | |
| 380 | pub fn format(self: Perm, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { | | |
| 381 | _ = fmt; | | |
| 382 | _ = options; | | |
| 383 | try writer.writeByte(if (self.read) 'r' else '-'); | | |
| 384 | try writer.writeByte(if (self.write) 'w' else '-'); | | |
| 385 | try writer.writeByte(if (self.execute) 'x' else '-'); | | |
| 386 | } | | |
| 387 | | | |
| 388 | pub fn nprint(self: Perm, writer: anytype) !void { | | |
| 389 | try writer.writeAll(&.{ | | |
| 390 | if (self.read) 'r' else '-', | | |
| 391 | if (self.write) 'w' else '-', | | |
| 392 | if (self.execute) 'x' else '-', | | |
| 393 | }); | | |
| 394 | } | | |
| 395 | }; | | |
| 396 | }; | | |
| 397 | }; | | |
| 398 | | | |
| 399 | // TODO make this inspect .git manually | 258 | // TODO make this inspect .git manually |
| 400 | // TODO make this return a Reader when we implement it ourselves | 259 | // TODO make this return a Reader when we implement it ourselves |
| 401 | pub fn getTreeDiff(alloc: std.mem.Allocator, dir: nfs.Dir, commitid: CommitId, parentid: ?CommitId) !string { | 260 | pub fn getTreeDiff(alloc: std.mem.Allocator, dir: nfs.Dir, commitid: CommitId, parentid: ?CommitId) !string { |
| ... | @@ -685,11 +544,6 @@ pub const TreeDiff = struct { | ... | @@ -685,11 +544,6 @@ pub const TreeDiff = struct { |
| 685 | }; | 544 | }; |
| 686 | }; | 545 | }; |
| 687 | | 546 | |
| 688 | pub const Ref = struct { | | |
| 689 | oid: Id, | | |
| 690 | label: string, | | |
| 691 | }; | | |
| 692 | | | |
| 693 | pub fn parseTag(tagfile: string) !Tag { | 547 | pub fn parseTag(tagfile: string) !Tag { |
| 694 | const t = tracer.trace(@src(), "", .{}); | 548 | const t = tracer.trace(@src(), "", .{}); |
| 695 | defer t.end(); | 549 | defer t.end(); |
| ... | @@ -716,13 +570,6 @@ pub fn parseTag(tagfile: string) !Tag { | ... | @@ -716,13 +570,6 @@ pub fn parseTag(tagfile: string) !Tag { |
| 716 | return result; | 570 | return result; |
| 717 | } | 571 | } |
| 718 | | 572 | |
| 719 | pub const Tag = struct { | | |
| 720 | object: Id, | | |
| 721 | type: RefType, | | |
| 722 | tagger: ?UserAndAt, | | |
| 723 | message: string, | | |
| 724 | }; | | |
| 725 | | | |
| 726 | // TODO make this inspect .git/objects | 573 | // TODO make this inspect .git/objects |
| 727 | pub fn getBlame(alloc: std.mem.Allocator, dir: nfs.Dir, at: CommitId, sub_path: string) !string { | 574 | pub fn getBlame(alloc: std.mem.Allocator, dir: nfs.Dir, at: CommitId, sub_path: string) !string { |
| 728 | const t = tracer.trace(@src(), " {s} -- {s}", .{ at.id, sub_path }); | 575 | const t = tracer.trace(@src(), " {s} -- {s}", .{ at.id, sub_path }); |
| ... | @@ -1493,6 +1340,159 @@ fn traverseTo(r: *Repository, arena: std.mem.Allocator, treestart_id: TreeId, di | ... | @@ -1493,6 +1340,159 @@ fn traverseTo(r: *Repository, arena: std.mem.Allocator, treestart_id: TreeId, di |
| 1493 | return tree; | 1340 | return tree; |
| 1494 | } | 1341 | } |
| 1495 | | 1342 | |
| | 1343 | pub const Tree = struct { |
| | 1344 | children: MultiArrayList(Object), |
| | 1345 | |
| | 1346 | pub fn get(self: Tree, name: string) ?Object { |
| | 1347 | if (self.children.len() <= 1000) { |
| | 1348 | for (self.children.items.name, 0..) |a_name, i| { |
| | 1349 | if (std.mem.eql(u8, a_name, name)) { |
| | 1350 | return self.children.get(i); |
| | 1351 | } |
| | 1352 | } |
| | 1353 | return null; |
| | 1354 | } |
| | 1355 | const i = std.sort.binarySearch([]const u8, self.children.items.name, name, extras.compareFnSlice(u8)) orelse return null; |
| | 1356 | return self.children.get(i); |
| | 1357 | } |
| | 1358 | |
| | 1359 | pub fn getBlob(self: Tree, name: string) ?Object { |
| | 1360 | const o = self.get(name) orelse return null; |
| | 1361 | if (o.id != .blob) return null; |
| | 1362 | return o; |
| | 1363 | } |
| | 1364 | |
| | 1365 | pub fn find(self: Tree, name: string) ?Object { |
| | 1366 | for (self.children.items.name, 0..) |item, i| { |
| | 1367 | if (std.ascii.eqlIgnoreCase(item, name)) { |
| | 1368 | return self.children.get(i); |
| | 1369 | } |
| | 1370 | } |
| | 1371 | return null; |
| | 1372 | } |
| | 1373 | |
| | 1374 | pub fn findBlob(self: Tree, name: string) ?Object { |
| | 1375 | const o = self.find(name) orelse return null; |
| | 1376 | if (o.id != .blob) return null; |
| | 1377 | return o; |
| | 1378 | } |
| | 1379 | |
| | 1380 | pub const Object = struct { |
| | 1381 | mode: Mode, |
| | 1382 | id: AnyId, |
| | 1383 | name: [:0]const u8, |
| | 1384 | |
| | 1385 | pub const Mode = struct { |
| | 1386 | type: Type, |
| | 1387 | perm_user: Perm, |
| | 1388 | perm_group: Perm, |
| | 1389 | perm_other: Perm, |
| | 1390 | |
| | 1391 | pub fn format(self: Mode, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { |
| | 1392 | _ = fmt; |
| | 1393 | _ = options; |
| | 1394 | try writer.print("{}", .{self.type}); |
| | 1395 | try writer.print("{}", .{self.perm_user}); |
| | 1396 | try writer.print("{}", .{self.perm_group}); |
| | 1397 | try writer.print("{}", .{self.perm_other}); |
| | 1398 | } |
| | 1399 | |
| | 1400 | pub fn nprint(self: Mode, writer: anytype) !void { |
| | 1401 | try self.type.nprint(writer); |
| | 1402 | try self.perm_user.nprint(writer); |
| | 1403 | try self.perm_group.nprint(writer); |
| | 1404 | try self.perm_other.nprint(writer); |
| | 1405 | } |
| | 1406 | |
| | 1407 | pub fn eql(self: Mode, other: Mode) bool { |
| | 1408 | if (self.type != other.type) return false; |
| | 1409 | if (self.perm_user != other.perm_user) return false; |
| | 1410 | if (self.perm_group != other.perm_group) return false; |
| | 1411 | if (self.perm_other != other.perm_other) return false; |
| | 1412 | return true; |
| | 1413 | } |
| | 1414 | }; |
| | 1415 | |
| | 1416 | pub const Type = enum(u8) { |
| | 1417 | file = 100, |
| | 1418 | directory = 40, |
| | 1419 | submodule = 160, |
| | 1420 | symlink = 120, |
| | 1421 | none = 0, |
| | 1422 | |
| | 1423 | pub fn format(self: Type, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { |
| | 1424 | _ = fmt; |
| | 1425 | _ = options; |
| | 1426 | try writer.writeByte(switch (self) { |
| | 1427 | .file => '-', |
| | 1428 | .directory => 'd', |
| | 1429 | .submodule => 'm', |
| | 1430 | .symlink => '-', |
| | 1431 | .none => '-', |
| | 1432 | }); |
| | 1433 | } |
| | 1434 | |
| | 1435 | pub fn nprint(self: Type, writer: anytype) !void { |
| | 1436 | try writer.writeAll(&.{switch (self) { |
| | 1437 | .file => '-', |
| | 1438 | .directory => 'd', |
| | 1439 | .submodule => 'm', |
| | 1440 | .symlink => '-', |
| | 1441 | .none => '-', |
| | 1442 | }}); |
| | 1443 | } |
| | 1444 | }; |
| | 1445 | |
| | 1446 | pub const Perm = packed struct(u3) { |
| | 1447 | execute: bool, |
| | 1448 | write: bool, |
| | 1449 | read: bool, |
| | 1450 | |
| | 1451 | pub fn format(self: Perm, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { |
| | 1452 | _ = fmt; |
| | 1453 | _ = options; |
| | 1454 | try writer.writeByte(if (self.read) 'r' else '-'); |
| | 1455 | try writer.writeByte(if (self.write) 'w' else '-'); |
| | 1456 | try writer.writeByte(if (self.execute) 'x' else '-'); |
| | 1457 | } |
| | 1458 | |
| | 1459 | pub fn nprint(self: Perm, writer: anytype) !void { |
| | 1460 | try writer.writeAll(&.{ |
| | 1461 | if (self.read) 'r' else '-', |
| | 1462 | if (self.write) 'w' else '-', |
| | 1463 | if (self.execute) 'x' else '-', |
| | 1464 | }); |
| | 1465 | } |
| | 1466 | }; |
| | 1467 | }; |
| | 1468 | }; |
| | 1469 | |
| | 1470 | pub const Commit = struct { |
| | 1471 | tree: TreeId, |
| | 1472 | parents: []const CommitId, |
| | 1473 | author: UserAndAt, |
| | 1474 | committer: UserAndAt, |
| | 1475 | message: string, |
| | 1476 | }; |
| | 1477 | |
| | 1478 | pub const UserAndAt = struct { |
| | 1479 | name: string, |
| | 1480 | email: string, |
| | 1481 | at: time.DateTime, |
| | 1482 | }; |
| | 1483 | |
| | 1484 | pub const Tag = struct { |
| | 1485 | object: Id, |
| | 1486 | type: RefType, |
| | 1487 | tagger: ?UserAndAt, |
| | 1488 | message: string, |
| | 1489 | }; |
| | 1490 | |
| | 1491 | pub const Ref = struct { |
| | 1492 | oid: Id, |
| | 1493 | label: string, |
| | 1494 | }; |
| | 1495 | |
| 1496 | /// Variant on std.MultiArrayList but using an allocation per-field rather than a single for the entire structure. | 1496 | /// Variant on std.MultiArrayList but using an allocation per-field rather than a single for the entire structure. |
| 1497 | fn MultiArrayList(T: type) type { | 1497 | fn MultiArrayList(T: type) type { |
| 1498 | return struct { | 1498 | return struct { |