@@ -36,32 +36,6 @@ test parseOid {
36
36
try testing .expectError (error .InvalidOid , parseOid ("HEAD" ));
37
37
}
38
38
39
- pub const Diagnostics = struct {
40
- allocator : Allocator ,
41
- errors : std .ArrayListUnmanaged (Error ) = .{},
42
-
43
- pub const Error = union (enum ) {
44
- unable_to_create_sym_link : struct {
45
- code : anyerror ,
46
- file_name : []const u8 ,
47
- link_name : []const u8 ,
48
- },
49
- };
50
-
51
- pub fn deinit (d : * Diagnostics ) void {
52
- for (d .errors .items ) | item | {
53
- switch (item ) {
54
- .unable_to_create_sym_link = > | info | {
55
- d .allocator .free (info .file_name );
56
- d .allocator .free (info .link_name );
57
- },
58
- }
59
- }
60
- d .errors .deinit (d .allocator );
61
- d .* = undefined ;
62
- }
63
- };
64
-
65
39
pub const Repository = struct {
66
40
odb : Odb ,
67
41
@@ -76,85 +50,6 @@ pub const Repository = struct {
76
50
77
51
/// Checks out the repository at `commit_oid` to `worktree`.
78
52
pub fn checkout (
79
- repository : * Repository ,
80
- worktree : std.fs.Dir ,
81
- commit_oid : Oid ,
82
- diagnostics : * Diagnostics ,
83
- ) ! void {
84
- try repository .odb .seekOid (commit_oid );
85
- const tree_oid = tree_oid : {
86
- const commit_object = try repository .odb .readObject ();
87
- if (commit_object .type != .commit ) return error .NotACommit ;
88
- break :tree_oid try getCommitTree (commit_object .data );
89
- };
90
- try repository .checkoutTree (worktree , tree_oid , "" , diagnostics );
91
- }
92
-
93
- /// Checks out the tree at `tree_oid` to `worktree`.
94
- fn checkoutTree (
95
- repository : * Repository ,
96
- dir : std.fs.Dir ,
97
- tree_oid : Oid ,
98
- current_path : []const u8 ,
99
- diagnostics : * Diagnostics ,
100
- ) ! void {
101
- try repository .odb .seekOid (tree_oid );
102
- const tree_object = try repository .odb .readObject ();
103
- if (tree_object .type != .tree ) return error .NotATree ;
104
- // The tree object may be evicted from the object cache while we're
105
- // iterating over it, so we can make a defensive copy here to make sure
106
- // it remains valid until we're done with it
107
- const tree_data = try repository .odb .allocator .dupe (u8 , tree_object .data );
108
- defer repository .odb .allocator .free (tree_data );
109
-
110
- var tree_iter : TreeIterator = .{ .data = tree_data };
111
- while (try tree_iter .next ()) | entry | {
112
- switch (entry .type ) {
113
- .directory = > {
114
- try dir .makeDir (entry .name );
115
- var subdir = try dir .openDir (entry .name , .{});
116
- defer subdir .close ();
117
- const sub_path = try std .fs .path .join (repository .odb .allocator , &.{ current_path , entry .name });
118
- defer repository .odb .allocator .free (sub_path );
119
- try repository .checkoutTree (subdir , entry .oid , sub_path , diagnostics );
120
- },
121
- .file = > {
122
- var file = try dir .createFile (entry .name , .{});
123
- defer file .close ();
124
- try repository .odb .seekOid (entry .oid );
125
- const file_object = try repository .odb .readObject ();
126
- if (file_object .type != .blob ) return error .InvalidFile ;
127
- try file .writeAll (file_object .data );
128
- try file .sync ();
129
- },
130
- .symlink = > {
131
- try repository .odb .seekOid (entry .oid );
132
- const symlink_object = try repository .odb .readObject ();
133
- if (symlink_object .type != .blob ) return error .InvalidFile ;
134
- const link_name = symlink_object .data ;
135
- dir .symLink (link_name , entry .name , .{}) catch | e | {
136
- const file_name = try std .fs .path .join (diagnostics .allocator , &.{ current_path , entry .name });
137
- errdefer diagnostics .allocator .free (file_name );
138
- const link_name_dup = try diagnostics .allocator .dupe (u8 , link_name );
139
- errdefer diagnostics .allocator .free (link_name_dup );
140
- try diagnostics .errors .append (diagnostics .allocator , .{ .unable_to_create_sym_link = .{
141
- .code = e ,
142
- .file_name = file_name ,
143
- .link_name = link_name_dup ,
144
- } });
145
- };
146
- },
147
- .gitlink = > {
148
- // Consistent with git archive behavior, create the directory but
149
- // do nothing else
150
- try dir .makeDir (entry .name );
151
- },
152
- }
153
- }
154
- }
155
-
156
- /// Checks out the repository at `commit_oid` to `worktree`.
157
- pub fn checkout2 (
158
53
repository : * Repository ,
159
54
worktree : anytype ,
160
55
commit_oid : Oid ,
@@ -165,11 +60,11 @@ pub const Repository = struct {
165
60
if (commit_object .type != .commit ) return error .NotACommit ;
166
61
break :tree_oid try getCommitTree (commit_object .data );
167
62
};
168
- try repository .checkoutTree2 (worktree , tree_oid , "" );
63
+ try repository .checkoutTree (worktree , tree_oid , "" );
169
64
}
170
65
171
66
/// Checks out the tree at `tree_oid` to `worktree`.
172
- fn checkoutTree2 (
67
+ fn checkoutTree (
173
68
repository : * Repository ,
174
69
dir : anytype ,
175
70
tree_oid : Oid ,
@@ -191,27 +86,32 @@ pub const Repository = struct {
191
86
defer allocator .free (sub_path );
192
87
switch (entry .type ) {
193
88
.directory = > {
194
- try repository .checkoutTree2 (dir , entry .oid , sub_path );
89
+ try dir .makePath (sub_path );
90
+ try repository .checkoutTree (dir , entry .oid , sub_path );
195
91
},
196
92
.file = > {
197
93
try repository .odb .seekOid (entry .oid );
198
94
const file_object = try repository .odb .readObject ();
199
95
if (file_object .type != .blob ) return error .InvalidFile ;
200
96
201
- if (try dir .createFile (sub_path )) | file | {
202
- defer file .close ();
203
- try file .writeAll (file_object .data );
204
- try file .sync ();
205
- }
97
+ var file = dir .createFile (sub_path , .{}) catch | err | {
98
+ if (err == error .Skip ) continue ;
99
+ return err ;
100
+ };
101
+ defer file .close ();
102
+ try file .writeAll (file_object .data );
103
+ try file .sync ();
206
104
},
207
105
.symlink = > {
208
106
try repository .odb .seekOid (entry .oid );
209
107
const symlink_object = try repository .odb .readObject ();
210
108
if (symlink_object .type != .blob ) return error .InvalidFile ;
211
109
212
- try dir .symLink (symlink_object .data , sub_path );
110
+ try dir .symLink (symlink_object .data , sub_path , .{});
111
+ },
112
+ .gitlink = > {
113
+ try dir .makePath (sub_path );
213
114
},
214
- .gitlink = > {},
215
115
}
216
116
}
217
117
}
@@ -1458,11 +1358,7 @@ test "packfile indexing and checkout" {
1458
1358
defer worktree .cleanup ();
1459
1359
1460
1360
const commit_id = try parseOid ("dd582c0720819ab7130b103635bd7271b9fd4feb" );
1461
-
1462
- var diagnostics : Diagnostics = .{ .allocator = testing .allocator };
1463
- defer diagnostics .deinit ();
1464
- try repository .checkout (worktree .dir , commit_id , & diagnostics );
1465
- try testing .expect (diagnostics .errors .items .len == 0 );
1361
+ try repository .checkout (worktree .dir , commit_id );
1466
1362
1467
1363
const expected_files : []const []const u8 = &.{
1468
1364
"dir/file" ,
@@ -1552,11 +1448,5 @@ pub fn main() !void {
1552
1448
std .debug .print ("Starting checkout...\n " , .{});
1553
1449
var repository = try Repository .init (allocator , pack_file , index_file );
1554
1450
defer repository .deinit ();
1555
- var diagnostics : Diagnostics = .{ .allocator = allocator };
1556
- defer diagnostics .deinit ();
1557
- try repository .checkout (worktree , commit , & diagnostics );
1558
-
1559
- for (diagnostics .errors .items ) | err | {
1560
- std .debug .print ("Diagnostic: {}\n " , .{err });
1561
- }
1451
+ try repository .checkout (worktree , commit );
1562
1452
}
0 commit comments