Skip to content

Commit

Permalink
std.os.path.dirname: return null instead of empty slice
Browse files Browse the repository at this point in the history
for when there is no directory component. Makes it harder
to write bugs.

closes #1017
  • Loading branch information
andrewrk committed Jun 14, 2018
1 parent 2219cc0 commit 6943cef
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src-self-hosted/introspect.zig
Expand Up @@ -27,7 +27,7 @@ pub fn findZigLibDir(allocator: *mem.Allocator) ![]u8 {

var cur_path: []const u8 = self_exe_path;
while (true) {
const test_dir = os.path.dirname(cur_path);
const test_dir = os.path.dirname(cur_path) orelse ".";

if (mem.eql(u8, test_dir, cur_path)) {
break;
Expand Down
2 changes: 1 addition & 1 deletion src-self-hosted/main.zig
Expand Up @@ -249,7 +249,7 @@ fn cmdBuild(allocator: *Allocator, args: []const []const u8) !void {
defer build_args.deinit();

const build_file_basename = os.path.basename(build_file_abs);
const build_file_dirname = os.path.dirname(build_file_abs);
const build_file_dirname = os.path.dirname(build_file_abs) orelse ".";

var full_cache_dir: []u8 = undefined;
if (flags.single("cache-dir")) |cache_dir| {
Expand Down
16 changes: 9 additions & 7 deletions std/build.zig
Expand Up @@ -617,7 +617,7 @@ pub const Builder = struct {
warn("cp {} {}\n", source_path, dest_path);
}

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

const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
const cache_o_dir = os.path.dirname(cache_o_src);
try builder.makePath(cache_o_dir);
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir);
}
const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt());
cc_args.append("-o") catch unreachable;
cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable;
Expand Down Expand Up @@ -1509,8 +1510,9 @@ pub const LibExeObjStep = struct {
cc_args.append(abs_source_file) catch unreachable;

const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
const cache_o_dir = os.path.dirname(cache_o_src);
try builder.makePath(cache_o_dir);
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir);
}
const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt());
cc_args.append("-o") catch unreachable;
cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable;
Expand Down Expand Up @@ -1855,7 +1857,7 @@ pub const WriteFileStep = struct {
fn make(step: *Step) !void {
const self = @fieldParentPtr(WriteFileStep, "step", step);
const full_path = self.builder.pathFromRoot(self.file_path);
const full_path_dir = os.path.dirname(full_path);
const full_path_dir = os.path.dirname(full_path) orelse ".";
os.makePath(self.builder.allocator, full_path_dir) catch |err| {
warn("unable to make path {}: {}\n", full_path_dir, @errorName(err));
return err;
Expand Down Expand Up @@ -1945,7 +1947,7 @@ pub const Step = struct {
};

fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
const out_dir = os.path.dirname(output_path);
const out_dir = os.path.dirname(output_path) orelse ".";
const out_basename = os.path.basename(output_path);
// sym link for libfoo.so.1 to libfoo.so.1.2.3
const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable;
Expand Down
12 changes: 6 additions & 6 deletions std/os/index.zig
Expand Up @@ -714,7 +714,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
else => return err, // TODO zig should know this set does not include PathAlreadyExists
}

const dirname = os.path.dirname(new_path);
const dirname = os.path.dirname(new_path) orelse ".";

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

var rand_buf: [12]u8 = undefined;

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

if (dirname.len != 0) {
mem.copy(u8, tmp_path[0..], dirname);
tmp_path[dirname.len] = os.path.sep;
if (dirname) |dir| {
mem.copy(u8, tmp_path[0..], dir);
tmp_path[dir.len] = os.path.sep;
}

while (true) {
Expand Down Expand Up @@ -1965,7 +1965,7 @@ pub fn selfExeDirPath(allocator: *mem.Allocator) ![]u8 {
// the executable was in when it was run.
const full_exe_path = try readLink(allocator, "/proc/self/exe");
errdefer allocator.free(full_exe_path);
const dir = path.dirname(full_exe_path);
const dir = path.dirname(full_exe_path) orelse ".";
return allocator.shrink(u8, full_exe_path, dir.len);
},
Os.windows, Os.macosx, Os.ios => {
Expand Down
54 changes: 34 additions & 20 deletions std/os/path.zig
Expand Up @@ -648,18 +648,18 @@ fn testResolvePosix(paths: []const []const u8) []u8 {
}

/// If the path is a file in the current directory (no directory component)
/// then the returned slice has .len = 0.
pub fn dirname(path: []const u8) []const u8 {
/// then returns null
pub fn dirname(path: []const u8) ?[]const u8 {
if (is_windows) {
return dirnameWindows(path);
} else {
return dirnamePosix(path);
}
}

pub fn dirnameWindows(path: []const u8) []const u8 {
pub fn dirnameWindows(path: []const u8) ?[]const u8 {
if (path.len == 0)
return path[0..0];
return null;

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

while ((path[end_index] == '/' or path[end_index] == '\\') and end_index > root_slice.len) {
if (end_index == 0)
return path[0..0];
return null;
end_index -= 1;
}

while (path[end_index] != '/' and path[end_index] != '\\' and end_index > root_slice.len) {
if (end_index == 0)
return path[0..0];
return null;
end_index -= 1;
}

if (have_root_slash and end_index == root_slice.len) {
end_index += 1;
}

if (end_index == 0)
return null;

return path[0..end_index];
}

pub fn dirnamePosix(path: []const u8) []const u8 {
pub fn dirnamePosix(path: []const u8) ?[]const u8 {
if (path.len == 0)
return path[0..0];
return null;

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

while (path[end_index] != '/') {
if (end_index == 0)
return path[0..0];
return null;
end_index -= 1;
}

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

if (end_index == 0)
return null;

return path[0..end_index];
}

Expand All @@ -717,10 +723,10 @@ test "os.path.dirnamePosix" {
testDirnamePosix("/a", "/");
testDirnamePosix("/", "/");
testDirnamePosix("////", "/");
testDirnamePosix("", "");
testDirnamePosix("a", "");
testDirnamePosix("a/", "");
testDirnamePosix("a//", "");
testDirnamePosix("", null);
testDirnamePosix("a", null);
testDirnamePosix("a/", null);
testDirnamePosix("a//", null);
}

test "os.path.dirnameWindows" {
Expand All @@ -742,7 +748,7 @@ test "os.path.dirnameWindows" {
testDirnameWindows("c:foo\\bar", "c:foo");
testDirnameWindows("c:foo\\bar\\", "c:foo");
testDirnameWindows("c:foo\\bar\\baz", "c:foo\\bar");
testDirnameWindows("file:stream", "");
testDirnameWindows("file:stream", null);
testDirnameWindows("dir\\file:stream", "dir");
testDirnameWindows("\\\\unc\\share", "\\\\unc\\share");
testDirnameWindows("\\\\unc\\share\\foo", "\\\\unc\\share\\");
Expand All @@ -753,18 +759,26 @@ test "os.path.dirnameWindows" {
testDirnameWindows("/a/b/", "/a");
testDirnameWindows("/a/b", "/a");
testDirnameWindows("/a", "/");
testDirnameWindows("", "");
testDirnameWindows("", null);
testDirnameWindows("/", "/");
testDirnameWindows("////", "/");
testDirnameWindows("foo", "");
testDirnameWindows("foo", null);
}

fn testDirnamePosix(input: []const u8, expected_output: []const u8) void {
assert(mem.eql(u8, dirnamePosix(input), expected_output));
fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {
if (dirnamePosix(input)) |output| {
assert(mem.eql(u8, output, expected_output.?));
} else {
assert(expected_output == null);
}
}

fn testDirnameWindows(input: []const u8, expected_output: []const u8) void {
assert(mem.eql(u8, dirnameWindows(input), expected_output));
fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
if (dirnameWindows(input)) |output| {
assert(mem.eql(u8, output, expected_output.?));
} else {
assert(expected_output == null);
}
}

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

0 comments on commit 6943cef

Please sign in to comment.