authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-03 17:57:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-04 17:42:22-07:00
log1bfbbe8b80c9155591766e302ffbc93c180b348a
tree44eb8251820c307c9adfe8178f8676b42f728c86
parentc3f2f93dbfec9060054c0cbafd7fbbdc63a249b3

std.fs.path: rename relative functions to relativeAlloc

introduce relativeAppend variants

1 files changed, 107 insertions(+), 25 deletions(-)

lib/std/fs/path.zig+107-25
......@@ -867,6 +867,13 @@ pub const resolveWindows = resolveAllocWindows;
867867/// Deprecated in favor of `resolveAllocPosix`.
868868pub const resolvePosix = resolveAllocPosix;
869869
870/// Deprecated in favor of `relativeAlloc`.
871pub const relative = relativeAlloc;
872/// Deprecated in favor of `relativeAllocPosix`.
873pub const relativePosix = relativeAllocPosix;
874/// Deprecated in favor of `relativeAllocWindows`.
875pub const relativeWindows = relativeAllocWindows;
876
870877/// On Windows, calls `resolveAllocWindows`; otherwise calls `resolveAllocPosix`.
871878pub fn resolveAlloc(gpa: Allocator, paths: []const []const u8) Allocator.Error![]u8 {
872879 switch (native_os) {
......@@ -1536,7 +1543,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) !void {
15361543///
15371544/// See `relativePosix` and `relativeWindows` for operating system specific
15381545/// details and for how `environ_map` is used.
1539pub fn relative(
1546pub fn relativeAlloc(
15401547 gpa: Allocator,
15411548 cwd: []const u8,
15421549 environ_map: ?*const std.process.Environ.Map,
......@@ -1544,9 +1551,36 @@ pub fn relative(
15441551 to: []const u8,
15451552) Allocator.Error![]u8 {
15461553 if (native_os == .windows) {
1547 return relativeWindows(gpa, cwd, environ_map, from, to);
1554 return relativeAllocWindows(gpa, cwd, environ_map, from, to);
1555 } else {
1556 return relativeAllocPosix(gpa, cwd, from, to);
1557 }
1558}
1559
1560/// Appends the non-absolute path from `from` to `to` to the provided array
1561/// list.
1562///
1563/// Other than modifying the provided array list, this is a pure function; the
1564/// result solely depends on the input parameters and no file system operations
1565/// are performed.
1566///
1567/// If `from` and `to` each resolve to the same path (after calling
1568/// `resolveAppend` on each), a zero-length string is returned.
1569///
1570/// See `relativeAppendPosix` and `relativeAppendWindows` for operating system
1571/// specific details and for how `environ_map` is used.
1572pub fn relativeAppend(
1573 gpa: Allocator,
1574 al: *std.ArrayList(u8),
1575 cwd: []const u8,
1576 environ_map: ?*const std.process.Environ.Map,
1577 from: []const u8,
1578 to: []const u8,
1579) Allocator.Error!void {
1580 if (native_os == .windows) {
1581 return relativeAppendWindows(gpa, al, cwd, environ_map, from, to);
15481582 } else {
1549 return relativePosix(gpa, cwd, from, to);
1583 return relativeAppendPosix(gpa, al, cwd, from, to);
15501584 }
15511585}
15521586
......@@ -1567,7 +1601,7 @@ pub fn relative(
15671601/// shell concept, so there's no guarantee that it'll be set or that it'll even
15681602/// be accurate. This is the only reason for the `environ_map` parameter. `null` is
15691603/// treated equivalent to the environment variable missing.
1570pub fn relativeWindows(
1604pub fn relativeAllocWindows(
15711605 gpa: Allocator,
15721606 cwd: []const u8,
15731607 environ_map: ?*const std.process.Environ.Map,
......@@ -1663,6 +1697,23 @@ pub fn relativeWindows(
16631697 return [_]u8{};
16641698}
16651699
1700pub fn relativeAppendWindows(
1701 gpa: Allocator,
1702 al: *std.ArrayList(u8),
1703 cwd: []const u8,
1704 environ_map: ?*const std.process.Environ.Map,
1705 from: []const u8,
1706 to: []const u8,
1707) Allocator.Error!void {
1708 _ = gpa;
1709 _ = al;
1710 _ = cwd;
1711 _ = environ_map;
1712 _ = from;
1713 _ = to;
1714 @panic("TODO");
1715}
1716
16661717fn windowsResolveAgainstCwd(
16671718 gpa: Allocator,
16681719 cwd: []const u8,
......@@ -1728,36 +1779,66 @@ fn windowsResolveAgainstCwd(
17281779 };
17291780}
17301781
1731/// Returns the non-absolute path from `from` to `to` according to Windows rules.
1782/// Returns the non-absolute path from `from` to `to` according to POSIX rules.
17321783///
17331784/// Other than memory allocation, this is a pure function; the result solely
17341785/// depends on the input parameters.
17351786///
17361787/// If `from` and `to` each resolve to the same path (after calling `resolve`
17371788/// on each), a zero-length string is returned.
1789pub fn relativeAllocPosix(gpa: Allocator, cwd: []const u8, from: []const u8, to: []const u8) Allocator.Error![]u8 {
1790 var buffer: std.ArrayList(u8) = .empty;
1791 defer buffer.deinit(gpa);
1792 try relativeAppendPosix(gpa, &buffer, cwd, from, to);
1793 try buffer.shrinkToLen(gpa);
1794 return buffer.toOwnedSliceAssert();
1795}
1796
1797/// Appends the non-absolute path from `from` to `to` according to POSIX rules
1798/// to the provided array list.
1799///
1800/// Other than modifying the provided array list, this is a pure function; the
1801/// result solely depends on the input parameters and it does no file system
1802/// operations.
17381803///
1739pub fn relativePosix(allocator: Allocator, cwd: []const u8, from: []const u8, to: []const u8) Allocator.Error![]u8 {
1740 const resolved_from = try resolveAllocPosix(allocator, &[_][]const u8{ cwd, from });
1741 defer allocator.free(resolved_from);
1742 const resolved_to = try resolveAllocPosix(allocator, &[_][]const u8{ cwd, to });
1743 defer allocator.free(resolved_to);
1744
1745 var from_it = mem.tokenizeScalar(u8, resolved_from, '/');
1746 var to_it = mem.tokenizeScalar(u8, resolved_to, '/');
1804/// If `from` and `to` each resolve to the same path (after calling
1805/// `resolveAppend` on each), nothing is appended to the array list.
1806pub fn relativeAppendPosix(
1807 gpa: Allocator,
1808 al: *std.ArrayList(u8),
1809 cwd: []const u8,
1810 from: []const u8,
1811 to: []const u8,
1812) Allocator.Error!void {
1813 const orig_len = al.items.len;
1814 errdefer al.items.len = orig_len;
1815
1816 const resolved_from_start = al.items.len;
1817 try resolveAppendPosix(gpa, al, &.{ cwd, from });
1818 const resolved_from_end = al.items.len;
1819
1820 const resolved_to_start = al.items.len;
1821 try resolveAppendPosix(gpa, al, &.{ cwd, to });
1822 const resolved_to_end = al.items.len;
1823
1824 var from_it = mem.tokenizeScalar(u8, al.items[resolved_from_start..resolved_from_end], '/');
1825 var to_it = mem.tokenizeScalar(u8, al.items[resolved_to_start..resolved_to_end], '/');
17471826 while (true) {
1748 const from_component = from_it.next() orelse return allocator.dupe(u8, to_it.rest());
1827 const from_component = from_it.next() orelse {
1828 const result = to_it.rest();
1829 @memmove(al.items[orig_len..][0..result.len], result);
1830 al.shrinkRetainingCapacity(orig_len + result.len);
1831 return;
1832 };
17491833 const to_rest = to_it.rest();
17501834 if (to_it.next()) |to_component| {
17511835 if (mem.eql(u8, from_component, to_component))
17521836 continue;
17531837 }
17541838 var up_count: usize = 1;
1755 while (from_it.next()) |_| {
1756 up_count += 1;
1757 }
1839 while (from_it.next()) |_| up_count += 1;
17581840 const up_index_end = up_count * "../".len;
1759 const result = try allocator.alloc(u8, up_index_end + to_rest.len);
1760 errdefer allocator.free(result);
1841 const result = al.items[orig_len..];
17611842
17621843 var result_index: usize = 0;
17631844 while (result_index < up_index_end) {
......@@ -1765,15 +1846,16 @@ pub fn relativePosix(allocator: Allocator, cwd: []const u8, from: []const u8, to
17651846 result_index += 3;
17661847 }
17671848 if (to_rest.len == 0) {
1768 // shave off the trailing slash
1769 return allocator.realloc(result, result_index - 1);
1849 // Shave off the trailing slash.
1850 al.shrinkRetainingCapacity(orig_len + result_index - 1);
1851 return;
17701852 }
1771
1772 @memcpy(result[result_index..][0..to_rest.len], to_rest);
1773 return result;
1853 @memmove(result[result_index..][0..to_rest.len], to_rest);
1854 al.shrinkRetainingCapacity(orig_len + result_index + to_rest.len);
1855 return;
17741856 }
17751857
1776 return [_]u8{};
1858 al.shrinkRetainingCapacity(orig_len);
17771859}
17781860
17791861test relative {