| ... | @@ -51,11 +51,11 @@ pub const Diagnostics = struct { | ... | @@ -51,11 +51,11 @@ pub const Diagnostics = struct { |
| 51 | }, | 51 | }, |
| 52 | }; | 52 | }; |
| 53 | | 53 | |
| 54 | fn findRoot(d: *Diagnostics, path: []const u8) !void { | 54 | fn findRoot(d: *Diagnostics, kind: FileKind, path: []const u8) !void { |
| 55 | if (path.len == 0) return; | 55 | if (path.len == 0) return; |
| 56 | | 56 | |
| 57 | d.entries += 1; | 57 | d.entries += 1; |
| 58 | const root_dir = rootDir(path); | 58 | const root_dir = rootDir(path, kind); |
| 59 | if (d.entries == 1) { | 59 | if (d.entries == 1) { |
| 60 | d.root_dir = try d.allocator.dupe(u8, root_dir); | 60 | d.root_dir = try d.allocator.dupe(u8, root_dir); |
| 61 | return; | 61 | return; |
| ... | @@ -67,24 +67,31 @@ pub const Diagnostics = struct { | ... | @@ -67,24 +67,31 @@ pub const Diagnostics = struct { |
| 67 | } | 67 | } |
| 68 | | 68 | |
| 69 | // Returns root dir of the path, assumes non empty path. | 69 | // Returns root dir of the path, assumes non empty path. |
| 70 | fn rootDir(path: []const u8) []const u8 { | 70 | fn rootDir(path: []const u8, kind: FileKind) []const u8 { |
| 71 | const start_index: usize = if (path[0] == '/') 1 else 0; | 71 | const start_index: usize = if (path[0] == '/') 1 else 0; |
| 72 | const end_index: usize = if (path[path.len - 1] == '/') path.len - 1 else path.len; | 72 | const end_index: usize = if (path[path.len - 1] == '/') path.len - 1 else path.len; |
| 73 | const buf = path[start_index..end_index]; | 73 | const buf = path[start_index..end_index]; |
| 74 | if (std.mem.indexOfScalarPos(u8, buf, 0, '/')) |idx| { | 74 | if (std.mem.indexOfScalarPos(u8, buf, 0, '/')) |idx| { |
| 75 | return buf[0..idx]; | 75 | return buf[0..idx]; |
| 76 | } | 76 | } |
| 77 | return buf; | 77 | |
| | 78 | return switch (kind) { |
| | 79 | .file => "", |
| | 80 | .sym_link => "", |
| | 81 | .directory => buf, |
| | 82 | }; |
| 78 | } | 83 | } |
| 79 | | 84 | |
| 80 | test rootDir { | 85 | test rootDir { |
| 81 | const expectEqualStrings = testing.expectEqualStrings; | 86 | const expectEqualStrings = testing.expectEqualStrings; |
| 82 | try expectEqualStrings("a", rootDir("a")); | 87 | try expectEqualStrings("", rootDir("a", .file)); |
| 83 | try expectEqualStrings("b", rootDir("b")); | 88 | try expectEqualStrings("a", rootDir("a", .directory)); |
| 84 | try expectEqualStrings("c", rootDir("/c")); | 89 | try expectEqualStrings("b", rootDir("b", .directory)); |
| 85 | try expectEqualStrings("d", rootDir("/d/")); | 90 | try expectEqualStrings("c", rootDir("/c", .directory)); |
| 86 | try expectEqualStrings("a", rootDir("a/b")); | 91 | try expectEqualStrings("d", rootDir("/d/", .directory)); |
| 87 | try expectEqualStrings("a", rootDir("a/b/c")); | 92 | try expectEqualStrings("a", rootDir("a/b", .directory)); |
| | 93 | try expectEqualStrings("a", rootDir("a/b", .file)); |
| | 94 | try expectEqualStrings("a", rootDir("a/b/c", .directory)); |
| 88 | } | 95 | } |
| 89 | | 96 | |
| 90 | pub fn deinit(d: *Diagnostics) void { | 97 | pub fn deinit(d: *Diagnostics) void { |
| ... | @@ -637,7 +644,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: PipeOptions) | ... | @@ -637,7 +644,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: PipeOptions) |
| 637 | continue; | 644 | continue; |
| 638 | } | 645 | } |
| 639 | if (options.diagnostics) |d| { | 646 | if (options.diagnostics) |d| { |
| 640 | try d.findRoot(file_name); | 647 | try d.findRoot(file.kind, file_name); |
| 641 | } | 648 | } |
| 642 | | 649 | |
| 643 | switch (file.kind) { | 650 | switch (file.kind) { |
| ... | @@ -1093,6 +1100,21 @@ test "pipeToFileSystem root_dir" { | ... | @@ -1093,6 +1100,21 @@ test "pipeToFileSystem root_dir" { |
| 1093 | } | 1100 | } |
| 1094 | } | 1101 | } |
| 1095 | | 1102 | |
| | 1103 | test "findRoot with single file archive" { |
| | 1104 | const data = @embedFile("tar/testdata/22752.tar"); |
| | 1105 | var fbs = std.io.fixedBufferStream(data); |
| | 1106 | const reader = fbs.reader(); |
| | 1107 | |
| | 1108 | var tmp = testing.tmpDir(.{}); |
| | 1109 | defer tmp.cleanup(); |
| | 1110 | |
| | 1111 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| | 1112 | defer diagnostics.deinit(); |
| | 1113 | try pipeToFileSystem(tmp.dir, reader, .{ .diagnostics = &diagnostics }); |
| | 1114 | |
| | 1115 | try testing.expectEqualStrings("", diagnostics.root_dir); |
| | 1116 | } |
| | 1117 | |
| 1096 | test "findRoot without explicit root dir" { | 1118 | test "findRoot without explicit root dir" { |
| 1097 | const data = @embedFile("tar/testdata/19820.tar"); | 1119 | const data = @embedFile("tar/testdata/19820.tar"); |
| 1098 | var fbs = std.io.fixedBufferStream(data); | 1120 | var fbs = std.io.fixedBufferStream(data); |