Skip to content

Commit aeafafa

Browse files
committed
samepath: functionalize improve path, canonical() strict option
remove java as unstable for Java 8 or 11
1 parent d983fab commit aeafafa

File tree

5 files changed

+68
-36
lines changed

5 files changed

+68
-36
lines changed

+stdlib/+python/samepath.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function y = samepath(path1, path2)
2+
3+
try
4+
y = py.os.path.samefile(path1, path2);
5+
catch e
6+
if contains(e.message, "FileNotFoundError")
7+
y = false;
8+
else
9+
rethrow(e);
10+
end
11+
end
12+
13+
end

+stdlib/+sys/samepath.m

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function y = samepath(path1, path2)
2+
3+
4+
if ispc()
5+
y = strcmp(stdlib.canonical(path1, true), stdlib.canonical(path2, true));
6+
return
7+
end
8+
9+
if ismac()
10+
flag = '-f';
11+
else
12+
flag = '-c';
13+
end
14+
15+
cmd = strcat('s1=$(stat ', flag, ' %d:%i ', path1, '); ', ...
16+
's2=$(stat ', flag, ' %d:%i ', path2, '); ', ...
17+
'[ "$s1" = "$s2" ]; echo $?');
18+
19+
[s, ~] = system(cmd);
20+
y = s == 0;
21+
22+
end

+stdlib/canonical.m

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
%
99
%%% Inputs
1010
% * p: path to make canonical
11+
% * strict: if true, only return canonical path if it exists. If false, return normalized path if path does not exist.
1112
%%% Outputs
1213
% * c: canonical path, if determined
1314

14-
function c = canonical(p)
15+
function c = canonical(p, strict)
1516
arguments
1617
p {mustBeTextScalar}
18+
strict logical = false
1719
end
1820

1921
if strempty(p)
@@ -22,11 +24,11 @@
2224
end
2325

2426
if isMATLABReleaseOlderThan('R2024a')
25-
c = acanon(p);
27+
c = acanon(p, strict);
2628
else
2729
pth = matlab.io.internal.filesystem.resolvePath(p);
2830
c = pth.ResolvedPath;
29-
if strempty(c)
31+
if ~strict && strempty(c)
3032
c = stdlib.normalize(p);
3133
end
3234
end
@@ -36,15 +38,17 @@
3638
end
3739

3840

39-
function c = acanon(p)
41+
function c = acanon(p, strict)
4042

41-
if strempty(p), c = ''; return, end
43+
c = "";
44+
45+
if strempty(p), return, end
4246

4347
[s, r] = fileattrib(p);
4448

4549
if s == 1
4650
c = r.Name;
47-
else
51+
elseif ~strict
4852
c = stdlib.normalize(p);
4953
end
5054

+stdlib/samepath.m

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,10 @@
1616
path2 {mustBeTextScalar}
1717
end
1818

19-
y = stdlib.exists(path1) && stdlib.exists(path2);
20-
21-
if ~y, return; end
22-
23-
if ~ispc() && stdlib.isoctave()
24-
[r1, e1] = stat(path1);
25-
[r2, e2] = stat(path2);
26-
27-
y = e1 == 0 && e2 == 0 && ...
28-
r1.ino == r2.ino && r1.dev == r2.dev;
29-
30-
elseif stdlib.has_dotnet()
31-
separators = [System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar];
32-
f1 = System.IO.Path.GetFullPath(path1).TrimEnd(separators);
33-
f2 = System.IO.Path.GetFullPath(path2).TrimEnd(separators);
34-
y = System.String.Equals(f1, f2, System.StringComparison.OrdinalIgnoreCase);
35-
elseif stdlib.java_api() >= 11
36-
% https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/nio/file/Files.html#isSameFile(java.nio.file.Path,java.nio.file.Path)
37-
% Java 1.8 is buggy in some corner cases, so we require at least 11.
38-
y = java.nio.file.Files.isSameFile(javaPathObject(path1), javaPathObject(path2));
39-
19+
if stdlib.has_python()
20+
y = stdlib.python.samepath(path1, path2);
4021
else
41-
42-
y = strcmp(stdlib.canonical(path1), stdlib.canonical(path2));
43-
22+
y = stdlib.sys.samepath(path1, path2);
4423
end
4524

4625
%!assert(samepath(".", "."))

test/TestFileImpure.m

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
ph = {{0, '"stdin"'}, {1, '"stdout"'}, {2, '"stderr"'}, {fopen(tempname()), ''}}
1010

1111
p_file_size = {mfilename("fullpath") + ".m"}
12+
13+
same_fun = {@stdlib.samepath, @stdlib.sys.samepath, @stdlib.python.samepath}
14+
end
15+
16+
17+
methods(TestClassSetup)
18+
function pkg_path(tc)
19+
p = matlab.unittest.fixtures.PathFixture(fileparts(fileparts(mfilename('fullpath'))));
20+
tc.applyFixture(p)
21+
end
1222
end
1323

1424

@@ -31,19 +41,23 @@ function test_makedir(tc)
3141
import matlab.unittest.constraints.IsFolder
3242
d = tempname();
3343
stdlib.makedir(d)
34-
tc.assertThat(d, IsFolder)
44+
tc.verifyThat(d, IsFolder)
3545
rmdir(d)
3646
end
3747

3848
%%
39-
function test_samepath(tc, p_same)
40-
tc.verifyTrue(stdlib.samepath(p_same{1}, p_same{2}))
49+
function test_samepath(tc, p_same, same_fun)
50+
is_capable(tc, same_fun)
51+
52+
tc.verifyTrue(same_fun(p_same{1}, p_same{2}))
4153
end
4254

43-
function test_samepath_notexist(tc)
44-
tc.verifyFalse(stdlib.samepath("", ""))
55+
function test_samepath_notexist(tc, same_fun)
56+
is_capable(tc, same_fun)
57+
58+
tc.verifyFalse(same_fun("", ""))
4559
t = tempname();
46-
tc.verifyFalse(stdlib.samepath(t, t))
60+
tc.verifyFalse(same_fun(t, t))
4761
end
4862

4963

0 commit comments

Comments
 (0)