@@ -29,7 +29,7 @@ pub const Diagnostics = struct {
29
29
allocator : std.mem.Allocator ,
30
30
errors : std .ArrayListUnmanaged (Error ) = .{},
31
31
32
- root_entries : usize = 0 ,
32
+ entries : usize = 0 ,
33
33
root_dir : []const u8 = "" ,
34
34
35
35
pub const Error = union (enum ) {
@@ -48,41 +48,40 @@ pub const Diagnostics = struct {
48
48
},
49
49
};
50
50
51
- fn findRoot (d : * Diagnostics , path : []const u8 , kind : FileKind ) ! void {
52
- if (rootDir (path )) | root_dir | {
53
- d .root_entries += 1 ;
54
- if (kind == .directory and d .root_entries == 1 ) {
55
- d .root_dir = try d .allocator .dupe (u8 , root_dir );
56
- return ;
57
- }
58
- d .allocator .free (d .root_dir );
59
- d .root_dir = "" ;
51
+ fn findRoot (d : * Diagnostics , path : []const u8 ) ! void {
52
+ if (path .len == 0 ) return ;
53
+
54
+ d .entries += 1 ;
55
+ const root_dir = rootDir (path );
56
+ if (d .entries == 1 ) {
57
+ d .root_dir = try d .allocator .dupe (u8 , root_dir );
58
+ return ;
60
59
}
60
+ if (d .root_dir .len == 0 or std .mem .eql (u8 , root_dir , d .root_dir ))
61
+ return ;
62
+ d .allocator .free (d .root_dir );
63
+ d .root_dir = "" ;
61
64
}
62
65
63
- // If path is package root returns root_dir name, otherwise null.
64
- fn rootDir (path : []const u8 ) ? []const u8 {
65
- if (path .len == 0 ) return null ;
66
-
66
+ // Returns root dir of the path, assumes non empty path.
67
+ fn rootDir (path : []const u8 ) []const u8 {
67
68
const start_index : usize = if (path [0 ] == '/' ) 1 else 0 ;
68
69
const end_index : usize = if (path [path .len - 1 ] == '/' ) path .len - 1 else path .len ;
69
70
const buf = path [start_index .. end_index ];
70
- return if (std .mem .indexOfScalarPos (u8 , buf , 0 , '/' ) == null )
71
- buf
72
- else
73
- null ;
71
+ if (std .mem .indexOfScalarPos (u8 , buf , 0 , '/' )) | idx | {
72
+ return buf [0 .. idx ];
73
+ }
74
+ return buf ;
74
75
}
75
76
76
77
test rootDir {
77
78
const expectEqualStrings = testing .expectEqualStrings ;
78
- const expect = testing .expect ;
79
-
80
- try expectEqualStrings ("a" , rootDir ("a" ).? );
81
- try expectEqualStrings ("b" , rootDir ("b" ).? );
82
- try expectEqualStrings ("c" , rootDir ("/c" ).? );
83
- try expectEqualStrings ("d" , rootDir ("/d/" ).? );
84
- try expect (rootDir ("a/b" ) == null );
85
- try expect (rootDir ("" ) == null );
79
+ try expectEqualStrings ("a" , rootDir ("a" ));
80
+ try expectEqualStrings ("b" , rootDir ("b" ));
81
+ try expectEqualStrings ("c" , rootDir ("/c" ));
82
+ try expectEqualStrings ("d" , rootDir ("/d/" ));
83
+ try expectEqualStrings ("a" , rootDir ("a/b" ));
84
+ try expectEqualStrings ("a" , rootDir ("a/b/c" ));
86
85
}
87
86
88
87
pub fn deinit (d : * Diagnostics ) void {
@@ -625,7 +624,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: PipeOptions)
625
624
while (try iter .next ()) | file | {
626
625
const file_name = stripComponents (file .name , options .strip_components );
627
626
if (options .diagnostics ) | d | {
628
- try d .findRoot (file_name , file . kind );
627
+ try d .findRoot (file_name );
629
628
}
630
629
631
630
switch (file .kind ) {
@@ -1056,7 +1055,7 @@ test "pipeToFileSystem root_dir" {
1056
1055
1057
1056
// there is no root_dir
1058
1057
try testing .expectEqual (0 , diagnostics .root_dir .len );
1059
- try testing .expectEqual (3 , diagnostics .root_entries );
1058
+ try testing .expectEqual (5 , diagnostics .entries );
1060
1059
}
1061
1060
1062
1061
// with strip_components = 0
@@ -1078,10 +1077,25 @@ test "pipeToFileSystem root_dir" {
1078
1077
1079
1078
// root_dir found
1080
1079
try testing .expectEqualStrings ("example" , diagnostics .root_dir );
1081
- try testing .expectEqual (1 , diagnostics .root_entries );
1080
+ try testing .expectEqual (6 , diagnostics .entries );
1082
1081
}
1083
1082
}
1084
1083
1084
+ test "findRoot without explicit root dir" {
1085
+ const data = @embedFile ("tar/testdata/19820.tar" );
1086
+ var fbs = std .io .fixedBufferStream (data );
1087
+ const reader = fbs .reader ();
1088
+
1089
+ var tmp = testing .tmpDir (.{});
1090
+ defer tmp .cleanup ();
1091
+
1092
+ var diagnostics : Diagnostics = .{ .allocator = testing .allocator };
1093
+ defer diagnostics .deinit ();
1094
+ try pipeToFileSystem (tmp .dir , reader , .{ .diagnostics = & diagnostics });
1095
+
1096
+ try testing .expectEqualStrings ("root" , diagnostics .root_dir );
1097
+ }
1098
+
1085
1099
fn normalizePath (bytes : []u8 ) []u8 {
1086
1100
const canonical_sep = std .fs .path .sep_posix ;
1087
1101
if (std .fs .path .sep == canonical_sep ) return bytes ;
0 commit comments