@@ -54,18 +54,18 @@ pub const Errors = struct {
54
54
return self .list .items .len ;
55
55
}
56
56
57
- fn createFile (self : * Errors , sub_path : []const u8 , err : anyerror ) ! void {
57
+ fn createFile (self : * Errors , subdir_path : [] const u8 , file_path : []const u8 , err : anyerror ) ! void {
58
58
try self .list .append (self .allocator , .{ .unable_to_create_file = .{
59
59
.code = err ,
60
- .file_name = try self . allocator . dupe ( u8 , sub_path ),
60
+ .file_name = try std . fs . path . join ( testing . allocator , &.{ subdir_path , file_path } ),
61
61
} });
62
62
}
63
63
64
- fn symLink (self : * Errors , target_path : []const u8 , sym_link_path : []const u8 , err : anyerror ) ! void {
64
+ fn symLink (self : * Errors , subdir_path : [] const u8 , target_path : []const u8 , sym_link_path : []const u8 , err : anyerror ) ! void {
65
65
try self .list .append (self .allocator , .{ .unable_to_create_sym_link = .{
66
66
.code = err ,
67
67
.target_path = try self .allocator .dupe (u8 , target_path ),
68
- .sym_link_path = try self . allocator . dupe ( u8 , sym_link_path ),
68
+ .sym_link_path = try std . fs . path . join ( testing . allocator , &.{ subdir_path , sym_link_path } ),
69
69
} });
70
70
}
71
71
@@ -116,7 +116,7 @@ pub fn tarball(self: *Self, reader: anytype) !void {
116
116
if (entry .size == 0 and entry .name .len == 0 ) continue ;
117
117
const file_name = stripComponents (entry .name , strip_components );
118
118
if (file_name .len == 0 ) return error .BadFileName ;
119
- if (try self .createFile (file_name )) | file | {
119
+ if (try self .createFile ("" , file_name )) | file | {
120
120
defer file .close ();
121
121
try entry .writeAll (file );
122
122
}
@@ -125,29 +125,14 @@ pub fn tarball(self: *Self, reader: anytype) !void {
125
125
const file_name = stripComponents (entry .name , strip_components );
126
126
if (file_name .len == 0 ) return error .BadFileName ;
127
127
const link_name = entry .link_name ;
128
- try self .symLink (link_name , file_name );
128
+ try self .symLink ("" , link_name , file_name );
129
129
},
130
130
}
131
131
} else break ;
132
132
}
133
133
}
134
134
135
135
pub fn gitPack (self : * Self , commit_oid : git.Oid , reader : anytype ) ! void {
136
- // Same interface as std.fs.Dir.createFile, symLink
137
- const inf = struct {
138
- parent : * Self ,
139
-
140
- pub fn makePath (_ : @This (), _ : []const u8 ) ! void {}
141
-
142
- pub fn createFile (t : @This (), sub_path : []const u8 , _ : fs .File .CreateFlags ) ! fs.File {
143
- return (try t .parent .createFile (sub_path )) orelse error .Skip ;
144
- }
145
-
146
- pub fn symLink (t : @This (), target_path : []const u8 , sym_link_path : []const u8 , _ : fs .Dir .SymLinkFlags ) ! void {
147
- try t .parent .symLink (target_path , sym_link_path );
148
- }
149
- }{ .parent = self };
150
-
151
136
var pack_dir = try self .root .makeOpenPath (".git" , .{});
152
137
defer pack_dir .close ();
153
138
var pack_file = try pack_dir .createFile ("pkg.pack" , .{ .read = true });
@@ -168,7 +153,22 @@ pub fn gitPack(self: *Self, commit_oid: git.Oid, reader: anytype) !void {
168
153
{
169
154
var repository = try git .Repository .init (self .allocator , pack_file , index_file );
170
155
defer repository .deinit ();
171
- try repository .checkout (inf , commit_oid );
156
+ var iter = try repository .iterator (commit_oid );
157
+ defer iter .deinit ();
158
+ while (try iter .next ()) | entry | {
159
+ switch (entry .type ) {
160
+ .file = > {
161
+ if (try self .createFile (entry .path , entry .name )) | file | {
162
+ defer file .close ();
163
+ try file .writeAll (entry .data );
164
+ }
165
+ },
166
+ .symlink = > {
167
+ try self .symLink (entry .path , entry .data , entry .name );
168
+ },
169
+ else = > {}, // skip empty directory
170
+ }
171
+ }
172
172
}
173
173
174
174
try self .root .deleteTree (".git" );
@@ -186,7 +186,7 @@ pub fn directory(self: *Self, source: fs.Dir) !void {
186
186
.sym_link = > {
187
187
var buf : [fs .MAX_PATH_BYTES ]u8 = undefined ;
188
188
const link_name = try source .readLink (entry .path , & buf );
189
- try self .symLink (link_name , entry .path );
189
+ try self .symLink ("" , link_name , entry .path );
190
190
},
191
191
else = > return error .IllegalFileTypeInPackage ,
192
192
}
@@ -201,6 +201,12 @@ pub fn filterErrors(self: *Self, filter: Filter) !void {
201
201
try self .errors .filterWith (filter );
202
202
}
203
203
204
+ fn makePath (self : * Self , sub_path : []const u8 ) ! fs.Dir {
205
+ if (sub_path .len == 0 ) return self .root ;
206
+ try self .root .makePath (sub_path );
207
+ return try self .root .openDir (sub_path , .{});
208
+ }
209
+
204
210
fn copyFile (source_dir : fs.Dir , source_path : []const u8 , dest_dir : fs.Dir , dest_path : []const u8 ) ! void {
205
211
source_dir .copyFile (source_path , dest_dir , dest_path , .{}) catch | err | switch (err ) {
206
212
error .FileNotFound = > {
@@ -213,32 +219,44 @@ fn copyFile(source_dir: fs.Dir, source_path: []const u8, dest_dir: fs.Dir, dest_
213
219
214
220
/// Returns fs.File on success, null on failure.
215
221
/// Errors are collected in errors list.
216
- fn createFile (self : * Self , sub_path : []const u8 ) ! ? fs.File {
217
- return createFilePath (self .root , sub_path ) catch | err | {
218
- try self .errors .createFile (sub_path , err );
222
+ fn createFile (self : * Self , subdir_path : [] const u8 , file_path : []const u8 ) ! ? fs.File {
223
+ return createFilePath (self .root , subdir_path , file_path ) catch | err | {
224
+ try self .errors .createFile (subdir_path , file_path , err );
219
225
return null ;
220
226
};
221
227
}
222
228
223
- fn symLink (self : * Self , target_path : []const u8 , sym_link_path : []const u8 ) ! void {
224
- symLinkPath (self .root , target_path , sym_link_path ) catch | err | {
225
- try self .errors .symLink (target_path , sym_link_path , err );
229
+ fn symLink (self : * Self , subdir_path : [] const u8 , target_path : []const u8 , sym_link_path : []const u8 ) ! void {
230
+ symLinkPath (self .root , subdir_path , target_path , sym_link_path ) catch | err | {
231
+ try self .errors .symLink (subdir_path , target_path , sym_link_path , err );
226
232
};
227
233
}
228
234
229
- fn createFilePath (dir : fs.Dir , sub_path : []const u8 ) ! fs.File {
230
- return dir .createFile (sub_path , .{ .exclusive = true }) catch | err | switch (err ) {
235
+ fn createFilePath (root : fs.Dir , subdir_path : []const u8 , file_path : []const u8 ) ! fs.File {
236
+ var dir = root ;
237
+ if (subdir_path .len > 0 ) {
238
+ try dir .makePath (subdir_path );
239
+ dir = try dir .openDir (subdir_path , .{});
240
+ }
241
+
242
+ return dir .createFile (file_path , .{ .exclusive = true }) catch | err | switch (err ) {
231
243
error .FileNotFound = > {
232
- if (std .fs .path .dirname (sub_path )) | dirname | try dir .makePath (dirname );
233
- return try dir .createFile (sub_path , .{ .exclusive = true });
244
+ if (std .fs .path .dirname (file_path )) | dirname | try dir .makePath (dirname );
245
+ return try dir .createFile (file_path , .{ .exclusive = true });
234
246
},
235
247
else = > | e | return e ,
236
248
};
237
249
}
238
250
239
- fn symLinkPath (dir : fs.Dir , target_path : []const u8 , sym_link_path : []const u8 ) ! void {
251
+ fn symLinkPath (root : fs.Dir , subdir_path : [] const u8 , target_path : []const u8 , sym_link_path : []const u8 ) ! void {
240
252
// TODO: if this would create a symlink to outside
241
253
// the destination directory, fail with an error instead.
254
+ var dir = root ;
255
+ if (subdir_path .len > 0 ) {
256
+ try dir .makePath (subdir_path );
257
+ dir = try dir .openDir (subdir_path , .{});
258
+ }
259
+
242
260
dir .symLink (target_path , sym_link_path , .{}) catch | err | switch (err ) {
243
261
error .FileNotFound = > {
244
262
if (fs .path .dirname (sym_link_path )) | dirname | try dir .makePath (dirname );
@@ -275,40 +293,21 @@ test "tar stripComponents" {
275
293
}
276
294
277
295
test gitPack {
278
- const paths : []const []const u8 = &.{
279
- "dir/file" ,
280
- "dir/subdir/file" ,
281
- "dir/subdir/file2" ,
282
- "dir2/file" ,
283
- "dir3/file" ,
284
- "dir3/file2" ,
285
- "file" ,
286
- "file2" ,
287
- "file3" ,
288
- "file4" ,
289
- "file5" ,
290
- "file6" ,
291
- "file7" ,
292
- "file8" ,
293
- "file9" ,
294
- };
295
-
296
- // load git pack with expected files
297
- const data = @embedFile ("Fetch/git/testdata/testrepo.pack" );
298
- var fbs = std .io .fixedBufferStream (data );
299
-
300
296
var tmp = testing .tmpDir (.{ .iterate = true });
301
297
defer tmp .cleanup ();
302
298
303
- // unpack git pack
299
+ const repo = git .TestRepo ;
300
+ var stream = repo .stream ();
301
+ const reader = stream .reader ();
302
+
303
+ // Unpack git repo at commitID from reader
304
304
{
305
305
var unpack = Unpack .init (testing .allocator , tmp .dir );
306
306
defer unpack .deinit ();
307
- const commit_id = try git .parseOid ("dd582c0720819ab7130b103635bd7271b9fd4feb" );
308
- try unpack .gitPack (commit_id , fbs .reader ());
307
+ try unpack .gitPack (try repo .commitID (), reader );
309
308
}
310
309
311
- try expectDirFiles (tmp .dir , paths );
310
+ try expectDirFiles (tmp .dir , repo . expected_files );
312
311
}
313
312
314
313
const TarHeader = std .tar .output .Header ;
@@ -354,7 +353,7 @@ test directory {
354
353
defer source .cleanup ();
355
354
356
355
for (paths ) | path | {
357
- const f = try createFilePath (source .dir , path );
356
+ const f = try createFilePath (source .dir , "" , path );
358
357
f .close ();
359
358
}
360
359
@@ -453,6 +452,3 @@ fn expectDirFiles(dir: fs.Dir, expected_files: []const []const u8) !void {
453
452
}.lessThan );
454
453
try testing .expectEqualDeep (expected_files , actual_files .items );
455
454
}
456
-
457
- // var buf: [256]u8 = undefined;
458
- // std.debug.print("tmp dir: {s}\n", .{try tmp.dir.realpath(".", &buf)});
0 commit comments