1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
const std = @import("std");
const Alloc = std.mem.Allocator;
const Id = u160;
const Commit = struct {
author: std.BoundedArray(u8, 64),
message: std.BoundedArray(u8, 1024),
parent: Id,
tree: Id,
};
const Blob = struct {
data: std.BoundedArray(u8, 1024),
};
const Object = struct {
alloc: Alloc,
// pub fn getCommit(self: *Object) Commit {}
// pub fn getBlob(self: *Object) Blob {}
};
const PackFile = struct {
alloc: Alloc,
pub fn init(alloc: Alloc) PackFile {
return .{
.alloc = alloc,
};
}
pub fn deinit(self: *PackFile) void {
_ = self;
}
pub fn parse(self: *PackFile, idxReader: std.io.AnyReader, pckReader: anytype) !void {
_ = self;
var buffer: [16]u8 = undefined;
_ = try idxReader.read(&buffer);
std.debug.print("{s}\n", .{&buffer});
_ = try pckReader.read(&buffer);
std.debug.print("{s}\n", .{&buffer});
}
// pub fn init(alloc: Alloc, path: []const u8) PackFile {}
// pub fn deinit(self: *PackFile) void {}
// pub fn getObject(self: *PackFile, id: Id) Object {}
};
const Repo = struct {
alloc: Alloc,
packfile: PackFile,
head: Id,
pub fn open(alloc: Alloc, path: []const u8) !Repo {
const dir = try std.fs.cwd().openDir(path, .{});
// read file HEAD
const head = try dir.readFileAlloc(alloc, "HEAD", 1024);
defer alloc.free(head);
// read file pointed at by HEAD
const headPath = head[5 .. head.len - 1];
var idBuffer: [40]u8 = undefined;
const idStr = try dir.readFile(headPath, &idBuffer);
// parse id from file
const id = try std.fmt.parseUnsigned(u160, idStr, 16);
// open any packfiles
var packfile = PackFile.init(alloc);
if (dir.openDir("objects/pack", .{ .iterate = true })) |packDir| {
var packIt = packDir.iterate();
while (try packIt.next()) |f| {
if (std.mem.endsWith(u8, f.name, ".idx")) {
const idxFilename = f.name;
var pckFilenameBuffer: [64]u8 = undefined;
const pckFilename = try std.fmt.bufPrint(&pckFilenameBuffer, "{s}.pack", .{idxFilename[0 .. idxFilename.len - 4]});
const idxFile = try packDir.openFile(idxFilename, .{});
const pckFile = try packDir.openFile(pckFilename, .{});
defer idxFile.close();
defer pckFile.close();
const idxReader = idxFile.reader().any();
const pckReader = pckFile.reader().any();
try packfile.parse(idxReader, pckReader);
}
}
} else |err| {
std.debug.print("{}\n", .{err});
}
return .{
.alloc = alloc,
.packfile = packfile,
.head = id,
};
}
pub fn close(self: *Repo) void {
self.packfile.deinit();
}
// pub fn getObject(self: *Repo, id: Id) Object {}
};
test "print HEAD" {
var repo = try Repo.open(std.testing.allocator, "../microwindows/.git");
defer repo.close();
std.debug.print("HEAD: {}\n", .{repo.head});
}
// test "list commits" {
// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
// defer repo.close();
// const head = repo.getObject(repo.head);
// defer head.deinit();
// var c = head.getCommit();
// for (0..3) |_| {
// std.debug.print("{}\n", .{c});
// c = c.parent;
// }
// }
// test "tree" {
// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
// defer repo.close();
// const head = repo.getObject(repo.head);
// defer head.deinit();
// const commit = head.getCommit();
// std.debug.print("{}\n", .{commit.tree});
// }
// test "blob" {
// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
// defer repo.close();
// const head = repo.getObject(repo.head);
// defer head.deinit();
// const commit = head.getCommit();
// const blob = repo.getBlob(commit.files[0].id);
// std.debug.print("{}\n", .{blob});
// }
|