Source
pub fn relativePosix(allocator: Allocator, from: []const u8, to: []const u8) ![]u8 {
const cwd = try process.getCwdAlloc(allocator);
defer allocator.free(cwd);
const resolved_from = try resolvePosix(allocator, &[_][]const u8{ cwd, from });
defer allocator.free(resolved_from);
const resolved_to = try resolvePosix(allocator, &[_][]const u8{ cwd, to });
defer allocator.free(resolved_to);
var from_it = mem.tokenizeScalar(u8, resolved_from, '/');
var to_it = mem.tokenizeScalar(u8, resolved_to, '/');
while (true) {
const from_component = from_it.next() orelse return allocator.dupe(u8, to_it.rest());
const to_rest = to_it.rest();
if (to_it.next()) |to_component| {
if (mem.eql(u8, from_component, to_component))
continue;
}
var up_count: usize = 1;
while (from_it.next()) |_| {
up_count += 1;
}
const up_index_end = up_count * "../".len;
const result = try allocator.alloc(u8, up_index_end + to_rest.len);
errdefer allocator.free(result);
var result_index: usize = 0;
while (result_index < up_index_end) {
result[result_index..][0..3].* = "../".*;
result_index += 3;
}
if (to_rest.len == 0) {
// shave off the trailing slash
return allocator.realloc(result, result_index - 1);
}
@memcpy(result[result_index..][0..to_rest.len], to_rest);
return result;
}
return [_]u8{};
}