Skip to content

Commit 18d0f14

Browse files
committed
relative_to: add native method
1 parent 6ad45dd commit 18d0f14

File tree

8 files changed

+49
-24
lines changed

8 files changed

+49
-24
lines changed

+stdlib/+native/relative_to.m

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
%% NATIVE.RELATIVE_TO find relative path to target from base
2+
3+
function rel = relative_to(base, target)
4+
5+
% matlab.io.internal.filesystem.relativepath only works on Windows (!) and only
6+
% then with / filesep.
7+
8+
if stdlib.strempty(base) || stdlib.strempty(target)
9+
rel = "";
10+
return
11+
end
12+
13+
tp = strsplit(fullfile(target), filesep);
14+
bp = strsplit(fullfile(base), filesep);
15+
16+
% Find the common base portion
17+
n = 0;
18+
while n < length(tp) && n < length(bp) && strcmp(tp{n+1}, bp{n+1})
19+
n = n + 1;
20+
end
21+
22+
% Number of '..' needed
23+
numUp = length(bp) - n;
24+
25+
relParts = [repmat({'..'}, 1, numUp), tp(n+1:end)];
26+
27+
rel = fullfile(relParts{:});
28+
29+
if isempty(rel)
30+
rel = '.';
31+
end
32+
33+
rel = string(rel);
34+
35+
end

+stdlib/posix.m

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
%
55

66
function r = posix(p)
7-
arguments
8-
p {mustBeTextScalar}
9-
end
107

118
if ispc
129
r = strrep(p, '\', '/');

+stdlib/relative_to.m

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,10 @@
1616
other {mustBeTextScalar}
1717
end
1818

19-
if (stdlib.strempty(base) && stdlib.strempty(other)) || ...
20-
(stdlib.is_absolute(base) ~= stdlib.is_absolute(other))
21-
rel = "";
22-
return
23-
end
24-
2519
if stdlib.has_python()
2620
rel = stdlib.python.relative_to(base, other);
27-
elseif stdlib.dotnet_api() >= 5
28-
rel = stdlib.dotnet.relative_to(base, other);
2921
else
30-
rel = stdlib.sys.relative_to(base, other);
22+
rel = stdlib.native.relative_to(base, other);
3123
end
3224

3325
end
File renamed without changes.

+stdlib/+dotnet/relative_to.m renamed to example/dotnet/relative_to.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
%% DOTNET.RELATIVE_TO find the relative path to other from base
2+
%
3+
% not normally used because it's overly complex
24

35
function rel = relative_to(base, other)
46

7+
assert(stdlib.dotnet_api() >= 5)
8+
59
if stdlib.strempty(other)
610
rel = base;
711
return

+stdlib/+sys/relative_to.m renamed to example/sys/relative_to.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
%% SYS.RELATIVE_TO get relative path to other from base
2+
%
3+
% this works but is slow
4+
15
function r = relative_to(base, other)
26

37
r = "";
@@ -22,7 +26,7 @@
2226
r = string(strip(r));
2327

2428
if ispc()
25-
r = fullfile(stdlib.normalize(r));
29+
r = stdlib.normalize(r);
2630
end
2731

2832
end

test/TestRelative.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
properties (TestParameter)
88
pr = init_rel()
99
pp = init_prox()
10-
rel_fun = {@stdlib.relative_to, @stdlib.sys.relative_to, @stdlib.dotnet.relative_to, @stdlib.python.relative_to}
10+
rel_fun = {@stdlib.relative_to, @stdlib.native.relative_to, @stdlib.python.relative_to}
1111
end
1212

1313
methods(TestClassSetup)
@@ -44,8 +44,7 @@ function test_proximate_to(tc, pp)
4444

4545
p = {{"", "", ""}, ...
4646
{fileparts(pwd()), pwd(), "test"}, ...
47-
{root, fullfile(root, "test", mfilename() + ".m"), fullfile("test", mfilename + ".m")}, ...
48-
{"/", "/", "."}, ...
47+
{root, fullfile(root, "test", mfilename() + ".m"), fullfile("test", mfilename + ".m")}
4948
};
5049
% NOTE: ".." in relative_to(base) is ambiguous including for python.pathlib, C++ <filesystem>, etc.
5150

@@ -79,6 +78,7 @@ function test_proximate_to(tc, pp)
7978
else
8079

8180
p = [p, {
81+
{"/", "/", "."}, ...
8282
{"/dev/null", "/dev/null", "."}, ...
8383
}];
8484
end

test/is_capable.m

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ function is_capable(tc, f)
1616
tc.assumeTrue(ispc(), "Windows only function")
1717
end
1818

19-
if endsWith(n, "relative_to")
20-
tc.assumeGreaterThanOrEqual(dapi, 5)
21-
end
22-
2319
if endsWith(n, ["create_symlink", "ram_total", "read_symlink"])
2420
tc.assumeGreaterThanOrEqual(dapi, 6);
2521
end
@@ -50,10 +46,7 @@ function is_capable(tc, f)
5046
end
5147

5248
elseif contains(n, ".sys.")
53-
54-
if ismac() && endsWith(n, "relative_to")
55-
tc.assumeNotEmpty(stdlib.which("greadlink"), "brew install coreutils")
56-
end
49+
% pass
5750

5851
elseif contains(n, ".native.")
5952

0 commit comments

Comments
 (0)