Skip to content

Commit 6943cef

Browse files
committedJun 14, 2018
std.os.path.dirname: return null instead of empty slice
for when there is no directory component. Makes it harder to write bugs. closes #1017
·
0.15.20.3.0
1 parent 2219cc0 commit 6943cef

File tree

5 files changed

+51
-35
lines changed

5 files changed

+51
-35
lines changed
 

‎src-self-hosted/introspect.zig‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn findZigLibDir(allocator: *mem.Allocator) ![]u8 {
2727

2828
var cur_path: []const u8 = self_exe_path;
2929
while (true) {
30-
const test_dir = os.path.dirname(cur_path);
30+
const test_dir = os.path.dirname(cur_path) orelse ".";
3131

3232
if (mem.eql(u8, test_dir, cur_path)) {
3333
break;

‎src-self-hosted/main.zig‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ fn cmdBuild(allocator: *Allocator, args: []const []const u8) !void {
249249
defer build_args.deinit();
250250

251251
const build_file_basename = os.path.basename(build_file_abs);
252-
const build_file_dirname = os.path.dirname(build_file_abs);
252+
const build_file_dirname = os.path.dirname(build_file_abs) orelse ".";
253253

254254
var full_cache_dir: []u8 = undefined;
255255
if (flags.single("cache-dir")) |cache_dir| {

‎std/build.zig‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ pub const Builder = struct {
617617
warn("cp {} {}\n", source_path, dest_path);
618618
}
619619

620-
const dirname = os.path.dirname(dest_path);
620+
const dirname = os.path.dirname(dest_path) orelse ".";
621621
const abs_source_path = self.pathFromRoot(source_path);
622622
os.makePath(self.allocator, dirname) catch |err| {
623623
warn("Unable to create path {}: {}\n", dirname, @errorName(err));
@@ -1395,8 +1395,9 @@ pub const LibExeObjStep = struct {
13951395
cc_args.append(abs_source_file) catch unreachable;
13961396

13971397
const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
1398-
const cache_o_dir = os.path.dirname(cache_o_src);
1399-
try builder.makePath(cache_o_dir);
1398+
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
1399+
try builder.makePath(cache_o_dir);
1400+
}
14001401
const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt());
14011402
cc_args.append("-o") catch unreachable;
14021403
cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable;
@@ -1509,8 +1510,9 @@ pub const LibExeObjStep = struct {
15091510
cc_args.append(abs_source_file) catch unreachable;
15101511

15111512
const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
1512-
const cache_o_dir = os.path.dirname(cache_o_src);
1513-
try builder.makePath(cache_o_dir);
1513+
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
1514+
try builder.makePath(cache_o_dir);
1515+
}
15141516
const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt());
15151517
cc_args.append("-o") catch unreachable;
15161518
cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable;
@@ -1855,7 +1857,7 @@ pub const WriteFileStep = struct {
18551857
fn make(step: *Step) !void {
18561858
const self = @fieldParentPtr(WriteFileStep, "step", step);
18571859
const full_path = self.builder.pathFromRoot(self.file_path);
1858-
const full_path_dir = os.path.dirname(full_path);
1860+
const full_path_dir = os.path.dirname(full_path) orelse ".";
18591861
os.makePath(self.builder.allocator, full_path_dir) catch |err| {
18601862
warn("unable to make path {}: {}\n", full_path_dir, @errorName(err));
18611863
return err;
@@ -1945,7 +1947,7 @@ pub const Step = struct {
19451947
};
19461948

19471949
fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
1948-
const out_dir = os.path.dirname(output_path);
1950+
const out_dir = os.path.dirname(output_path) orelse ".";
19491951
const out_basename = os.path.basename(output_path);
19501952
// sym link for libfoo.so.1 to libfoo.so.1.2.3
19511953
const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable;

‎std/os/index.zig‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
714714
else => return err, // TODO zig should know this set does not include PathAlreadyExists
715715
}
716716

717-
const dirname = os.path.dirname(new_path);
717+
const dirname = os.path.dirname(new_path) orelse ".";
718718

719719
var rand_buf: [12]u8 = undefined;
720720
const tmp_path = try allocator.alloc(u8, dirname.len + 1 + base64.Base64Encoder.calcSize(rand_buf.len));
@@ -860,14 +860,14 @@ pub const AtomicFile = struct {
860860

861861
var rand_buf: [12]u8 = undefined;
862862

863-
const dirname_component_len = if (dirname.len == 0) 0 else dirname.len + 1;
863+
const dirname_component_len = if (dirname) |d| d.len + 1 else 0;
864864
const tmp_path = try allocator.alloc(u8, dirname_component_len +
865865
base64.Base64Encoder.calcSize(rand_buf.len));
866866
errdefer allocator.free(tmp_path);
867867

868-
if (dirname.len != 0) {
869-
mem.copy(u8, tmp_path[0..], dirname);
870-
tmp_path[dirname.len] = os.path.sep;
868+
if (dirname) |dir| {
869+
mem.copy(u8, tmp_path[0..], dir);
870+
tmp_path[dir.len] = os.path.sep;
871871
}
872872

873873
while (true) {
@@ -1965,7 +1965,7 @@ pub fn selfExeDirPath(allocator: *mem.Allocator) ![]u8 {
19651965
// the executable was in when it was run.
19661966
const full_exe_path = try readLink(allocator, "/proc/self/exe");
19671967
errdefer allocator.free(full_exe_path);
1968-
const dir = path.dirname(full_exe_path);
1968+
const dir = path.dirname(full_exe_path) orelse ".";
19691969
return allocator.shrink(u8, full_exe_path, dir.len);
19701970
},
19711971
Os.windows, Os.macosx, Os.ios => {

‎std/os/path.zig‎

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -648,18 +648,18 @@ fn testResolvePosix(paths: []const []const u8) []u8 {
648648
}
649649

650650
/// If the path is a file in the current directory (no directory component)
651-
/// then the returned slice has .len = 0.
652-
pub fn dirname(path: []const u8) []const u8 {
651+
/// then returns null
652+
pub fn dirname(path: []const u8) ?[]const u8 {
653653
if (is_windows) {
654654
return dirnameWindows(path);
655655
} else {
656656
return dirnamePosix(path);
657657
}
658658
}
659659

660-
pub fn dirnameWindows(path: []const u8) []const u8 {
660+
pub fn dirnameWindows(path: []const u8) ?[]const u8 {
661661
if (path.len == 0)
662-
return path[0..0];
662+
return null;
663663

664664
const root_slice = diskDesignatorWindows(path);
665665
if (path.len == root_slice.len)
@@ -671,26 +671,29 @@ pub fn dirnameWindows(path: []const u8) []const u8 {
671671

672672
while ((path[end_index] == '/' or path[end_index] == '\\') and end_index > root_slice.len) {
673673
if (end_index == 0)
674-
return path[0..0];
674+
return null;
675675
end_index -= 1;
676676
}
677677

678678
while (path[end_index] != '/' and path[end_index] != '\\' and end_index > root_slice.len) {
679679
if (end_index == 0)
680-
return path[0..0];
680+
return null;
681681
end_index -= 1;
682682
}
683683

684684
if (have_root_slash and end_index == root_slice.len) {
685685
end_index += 1;
686686
}
687687

688+
if (end_index == 0)
689+
return null;
690+
688691
return path[0..end_index];
689692
}
690693

691-
pub fn dirnamePosix(path: []const u8) []const u8 {
694+
pub fn dirnamePosix(path: []const u8) ?[]const u8 {
692695
if (path.len == 0)
693-
return path[0..0];
696+
return null;
694697

695698
var end_index: usize = path.len - 1;
696699
while (path[end_index] == '/') {
@@ -701,13 +704,16 @@ pub fn dirnamePosix(path: []const u8) []const u8 {
701704

702705
while (path[end_index] != '/') {
703706
if (end_index == 0)
704-
return path[0..0];
707+
return null;
705708
end_index -= 1;
706709
}
707710

708711
if (end_index == 0 and path[end_index] == '/')
709712
return path[0..1];
710713

714+
if (end_index == 0)
715+
return null;
716+
711717
return path[0..end_index];
712718
}
713719

@@ -717,10 +723,10 @@ test "os.path.dirnamePosix" {
717723
testDirnamePosix("/a", "/");
718724
testDirnamePosix("/", "/");
719725
testDirnamePosix("////", "/");
720-
testDirnamePosix("", "");
721-
testDirnamePosix("a", "");
722-
testDirnamePosix("a/", "");
723-
testDirnamePosix("a//", "");
726+
testDirnamePosix("", null);
727+
testDirnamePosix("a", null);
728+
testDirnamePosix("a/", null);
729+
testDirnamePosix("a//", null);
724730
}
725731

726732
test "os.path.dirnameWindows" {
@@ -742,7 +748,7 @@ test "os.path.dirnameWindows" {
742748
testDirnameWindows("c:foo\\bar", "c:foo");
743749
testDirnameWindows("c:foo\\bar\\", "c:foo");
744750
testDirnameWindows("c:foo\\bar\\baz", "c:foo\\bar");
745-
testDirnameWindows("file:stream", "");
751+
testDirnameWindows("file:stream", null);
746752
testDirnameWindows("dir\\file:stream", "dir");
747753
testDirnameWindows("\\\\unc\\share", "\\\\unc\\share");
748754
testDirnameWindows("\\\\unc\\share\\foo", "\\\\unc\\share\\");
@@ -753,18 +759,26 @@ test "os.path.dirnameWindows" {
753759
testDirnameWindows("/a/b/", "/a");
754760
testDirnameWindows("/a/b", "/a");
755761
testDirnameWindows("/a", "/");
756-
testDirnameWindows("", "");
762+
testDirnameWindows("", null);
757763
testDirnameWindows("/", "/");
758764
testDirnameWindows("////", "/");
759-
testDirnameWindows("foo", "");
765+
testDirnameWindows("foo", null);
760766
}
761767

762-
fn testDirnamePosix(input: []const u8, expected_output: []const u8) void {
763-
assert(mem.eql(u8, dirnamePosix(input), expected_output));
768+
fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {
769+
if (dirnamePosix(input)) |output| {
770+
assert(mem.eql(u8, output, expected_output.?));
771+
} else {
772+
assert(expected_output == null);
773+
}
764774
}
765775

766-
fn testDirnameWindows(input: []const u8, expected_output: []const u8) void {
767-
assert(mem.eql(u8, dirnameWindows(input), expected_output));
776+
fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
777+
if (dirnameWindows(input)) |output| {
778+
assert(mem.eql(u8, output, expected_output.?));
779+
} else {
780+
assert(expected_output == null);
781+
}
768782
}
769783

770784
pub fn basename(path: []const u8) []const u8 {

0 commit comments

Comments
 (0)
Please sign in to comment.