authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-14 16:15:32-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-14 16:15:32-04:00
log6943cefebf94631ff02d6e28436c07f4030924c6
tree0f74832cd4549b4852299639cb2fb90fdb66a4cc
parent2219cc061229bdc69314616869ad731b592d9e96

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

5 files changed, 51 insertions(+), 35 deletions(-)

src-self-hosted/introspect.zig+1-1
......@@ -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+1-1
......@@ -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+9-7
......@@ -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
19471949fn 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+6-6
......@@ -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+34-20
......@@ -648,8 +648,8 @@ 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.
652pub fn dirname(path: []const u8) []const u8 {
651/// then returns null
652pub fn dirname(path: []const u8) ?[]const u8 {
653653 if (is_windows) {
654654 return dirnameWindows(path);
655655 } else {
......@@ -657,9 +657,9 @@ pub fn dirname(path: []const u8) []const u8 {
657657 }
658658}
659659
660pub fn dirnameWindows(path: []const u8) []const u8 {
660pub 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,13 +671,13 @@ 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
......@@ -685,12 +685,15 @@ pub fn dirnameWindows(path: []const u8) []const u8 {
685685 end_index += 1;
686686 }
687687
688 if (end_index == 0)
689 return null;
690
688691 return path[0..end_index];
689692}
690693
691pub fn dirnamePosix(path: []const u8) []const u8 {
694pub 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
726732test "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
762fn testDirnamePosix(input: []const u8, expected_output: []const u8) void {
763 assert(mem.eql(u8, dirnamePosix(input), expected_output));
768fn 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
766fn testDirnameWindows(input: []const u8, expected_output: []const u8) void {
767 assert(mem.eql(u8, dirnameWindows(input), expected_output));
776fn 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
770784pub fn basename(path: []const u8) []const u8 {