Skip to content

Commit da5bcb0

Browse files
committed
test:{read,is}_symlink param fun
1 parent a12e4be commit da5bcb0

File tree

9 files changed

+79
-70
lines changed

9 files changed

+79
-70
lines changed

+stdlib/+dotnet/read_symlink.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function r = read_symlink(p)
2+
3+
try
4+
h = System.IO.FileInfo(p);
5+
r = string(h.LinkTarget);
6+
catch
7+
r = string.empty;
8+
end
9+
10+
end

+stdlib/+java/is_symlink.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function ok = is_symlink(p)
2+
3+
ok = java.nio.file.Files.isSymbolicLink(javaPathObject(stdlib.absolute(p)));
4+
5+
end

+stdlib/+java/read_symlink.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function r = read_symlink(p)
2+
3+
if stdlib.is_symlink(p)
4+
% must be absolute path
5+
% must not be .canonical or symlink is gobbled!
6+
r = stdlib.absolute(p);
7+
% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/file/Files.html#readSymbolicLink(java.nio.file.Path)
8+
r = string(java.nio.file.Files.readSymbolicLink(javaPathObject(r)));
9+
else
10+
r = string.empty;
11+
end
12+
13+
end

+stdlib/+python/read_symlink.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
function r = read_symlink(p)
22

3+
r = string.empty;
4+
5+
if ~stdlib.is_symlink(p), return, end
6+
37
% https://docs.python.org/3/library/pathlib.html#pathlib.Path.readlink
48
try
59
r = string(py.os.readlink(p));
@@ -8,7 +12,6 @@
812
end
913
catch e
1014
warning(e.identifier, "read_symlink(%s) failed: %s", p, e.message);
11-
r = string.empty;
1215
end
1316

1417
end

+stdlib/+sys/read_symlink.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
r = string.empty;
44

5+
if ~stdlib.is_symlink(p), return, end
6+
57
if isunix()
68
cmd = sprintf('readlink -fn %s', p);
79
else
@@ -10,7 +12,10 @@
1012

1113
[s, m] = system(cmd);
1214
if s == 0
13-
r = strip(string(m));
15+
m = strip(string(m));
16+
if strlength(m) > 0
17+
r = m;
18+
end
1419
end
1520

1621
end

+stdlib/is_symlink.m

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,19 @@
55
p {mustBeTextScalar}
66
end
77

8-
if strempty(p)
9-
ok = false;
10-
return
11-
end
12-
13-
try
8+
if ~isMATLABReleaseOlderThan('R2024b')
149
ok = isSymbolicLink(p);
15-
return
16-
catch e
17-
switch e.identifier
18-
case "MATLAB:UndefinedFunction"
19-
if stdlib.has_dotnet()
20-
ok = stdlib.dotnet.is_symlink(p);
21-
elseif stdlib.has_java()
22-
ok = java.nio.file.Files.isSymbolicLink(javaPathObject(stdlib.absolute(p)));
23-
elseif stdlib.has_python()
24-
ok = stdlib.python.is_symlink(p);
25-
end
26-
case "Octave:undefined-function"
27-
% use lstat() to work with a broken symlink, like Matlab isSymbolicLink
28-
[s, err] = lstat(p);
29-
ok = err == 0 && S_ISLNK(s.mode);
30-
otherwise, rethrow(e)
31-
end
32-
end
33-
34-
if ~ok
10+
elseif stdlib.has_dotnet()
11+
ok = stdlib.dotnet.is_symlink(p);
12+
elseif stdlib.has_java()
13+
ok = stdlib.java.is_symlink(p);
14+
elseif stdlib.has_python()
15+
ok = stdlib.python.is_symlink(p);
16+
elseif stdlib.isoctave()
17+
% use lstat() to work with a broken symlink, like Matlab isSymbolicLink
18+
[s, err] = lstat(p);
19+
ok = err == 0 && S_ISLNK(s.mode);
20+
else
3521
ok = stdlib.sys.is_symlink(p);
3622
end
3723

+stdlib/read_symlink.m

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,21 @@
88
p {mustBeTextScalar}
99
end
1010

11-
r = string.empty;
12-
13-
try
11+
if ~isMATLABReleaseOlderThan('R2024b')
1412
[ok, r] = isSymbolicLink(p);
15-
if ~ok, r = string.empty; end
16-
catch e
17-
switch e.identifier
18-
case "Octave:undefined-function", r = readlink(p);
19-
case "MATLAB:UndefinedFunction"
20-
if strempty(p) || ~stdlib.is_symlink(p)
21-
return
22-
end
23-
24-
if stdlib.dotnet_api() >= 6
25-
r = string(System.IO.FileInfo(p).LinkTarget);
26-
elseif stdlib.has_java()
27-
% must be absolute path
28-
% must not be .canonical or symlink is gobbled!
29-
r = stdlib.absolute(p);
30-
% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/file/Files.html#readSymbolicLink(java.nio.file.Path)
31-
r = string(java.nio.file.Files.readSymbolicLink(javaPathObject(r)));
32-
elseif stdlib.has_python()
33-
r = stdlib.python.read_symlink(p);
34-
end
35-
otherwise, rethrow(e)
36-
end
37-
38-
if strempty(r) && stdlib.exists(r)
39-
r = stdlib.sys.read_symlink(p);
13+
if ~ok
14+
r = string.empty;
4015
end
16+
elseif stdlib.dotnet_api() >= 6
17+
r = stdlib.dotnet.read_symlink(p);
18+
elseif stdlib.has_java()
19+
r = stdlib.java.read_symlink(p);
20+
elseif stdlib.has_python()
21+
r = stdlib.python.read_symlink(p);
22+
elseif stdlib.isoctave()
23+
r = readlink(p);
24+
else
25+
r = stdlib.sys.read_symlink(p);
4126
end
4227

4328
end

test/TestSymlink.m

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
p = {{"not-exist", false}, ...
1111
{mfilename("fullpath") + ".m", false}, ...
1212
{"", false}};
13+
is_symlink_fun = {@stdlib.is_symlink, @stdlib.sys.is_symlink, @stdlib.dotnet.is_symlink, @stdlib.java.is_symlink, @stdlib.python.is_symlink}
14+
read_symlink_fun = {@stdlib.read_symlink, @stdlib.sys.read_symlink, @stdlib.dotnet.read_symlink, @stdlib.java.read_symlink, @stdlib.python.read_symlink}
1315
end
1416

1517

@@ -48,22 +50,23 @@ function remove_temp_wd(tc)
4850

4951
methods (Test, TestTags=["impure", "symlink"])
5052

51-
function test_is_symlink(tc, p)
52-
fprintf("is_symlink mex: %d\n", stdlib.is_mex_fun("stdlib.is_symlink"))
53-
tc.verifyTrue(stdlib.is_symlink(tc.link), "failed to detect own link")
54-
tc.verifyEqual(stdlib.is_symlink(p{1}), p{2}, p{1})
53+
function test_is_symlink(tc, p, is_symlink_fun)
54+
is_capable(tc, is_symlink_fun)
55+
56+
tc.verifyTrue(is_symlink_fun(tc.link), "failed to detect own link")
57+
tc.verifyEqual(is_symlink_fun(p{1}), p{2}, p{1})
5558
end
5659

5760

58-
function test_read_symlink(tc)
59-
fprintf("read_symlink mex: %d\n", stdlib.is_mex_fun("stdlib.read_symlink"))
60-
tc.verifyEmpty(stdlib.read_symlink(""))
61-
tc.verifyEmpty(stdlib.read_symlink(''))
62-
tc.verifyEmpty(stdlib.read_symlink(tempname))
63-
tc.verifyEmpty(stdlib.read_symlink(tc.target))
61+
function test_read_symlink(tc, read_symlink_fun)
62+
is_capable(tc, read_symlink_fun)
6463

64+
tc.verifyEmpty(read_symlink_fun(""))
65+
tc.verifyEmpty(read_symlink_fun(''))
66+
tc.verifyEmpty(read_symlink_fun(tempname))
67+
tc.verifyEmpty(read_symlink_fun(tc.target))
6568

66-
link_read = stdlib.read_symlink(tc.link);
69+
link_read = read_symlink_fun(tc.link);
6770

6871
targ = string(tc.target);
6972

@@ -87,4 +90,3 @@ function test_create_symlink(tc)
8790

8891
end
8992
end
90-

test/is_capable.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function is_capable(tc, f)
1212

1313
tc.assumeGreaterThan(dapi, 0)
1414

15-
if endsWith(n, "ram_total")
15+
if endsWith(n, ["ram_total", "read_symlink"])
1616
tc.assumeGreaterThanOrEqual(dapi, 6);
1717
end
1818

@@ -32,7 +32,7 @@ function is_capable(tc, f)
3232

3333
has_psutil = pvt_psutil();
3434

35-
if contains(n, ["ram_free", "ram_total"])
35+
if endsWith(n, ["ram_free", "ram_total"])
3636
tc.assumeTrue(has_psutil, "need Python psutil package")
3737
end
3838

0 commit comments

Comments
 (0)