Skip to content

Commit

Permalink
distinguish absolute() and resolve()
Browse files Browse the repository at this point in the history
  • Loading branch information
scivision committed Sep 25, 2024
1 parent 5173fff commit 5a2ae56
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 44 deletions.
40 changes: 40 additions & 0 deletions +stdlib/absolute.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function c = absolute(p, base, expand_tilde)
%% absolute(p)
% path need not exist
% absolute path will be relative to pwd if not exist
%
%%% Inputs
% * p: path to make absolute
% * base: if present, base on this instead of cwd
% * expand_tilde: expand ~ to username if present
%%% Outputs
% * c: resolved path
% does not normalize
% non-existant path is made absolute relative to pwd
arguments
p (1,1) string
base string {mustBeScalarOrEmpty}=string.empty
expand_tilde (1,1) logical=true
end

if expand_tilde
c = stdlib.expanduser(p);
else
c = p;
end

if ~stdlib.is_absolute(c)
% .getAbsolutePath(), .toAbsolutePath()
% default is Documents/Matlab, which is probably not wanted.
if isempty(base) || strlength(base) == 0
c = stdlib.join(pwd, c);
else
c = stdlib.join(stdlib.absolute(base), c);
end
end

% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html#getAbsolutePath()

c = stdlib.posix(java.io.File(c).getAbsolutePath());

end % function
1 change: 1 addition & 0 deletions +stdlib/canonical.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
%
%%% Inputs
% * p: path to make canonical
% * expand_tilde: expand ~ to username if present
%%% Outputs
% * c: canonical path, if determined
% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html#getCanonicalPath()
Expand Down
4 changes: 2 additions & 2 deletions +stdlib/extract_zstd.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ function extract_zstd(archive, out_dir)
out_dir (1,1) string {mustBeFolder}
end

archive = stdlib.canonical(archive);
out_dir = stdlib.canonical(out_dir);
archive = stdlib.absolute(archive);
out_dir = stdlib.absolute(out_dir);

exe = stdlib.which("cmake");
if isempty(exe)
Expand Down
2 changes: 2 additions & 0 deletions +stdlib/is_exe.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
file (1,1) string
end

% doesn't need absolute path like other Java functions

ok = java.io.File(file).canExecute();

% more complicated
Expand Down
5 changes: 4 additions & 1 deletion +stdlib/is_readable.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
file (1,1) string
end

ok = java.nio.file.Files.isReadable(java.io.File(stdlib.canonical(file)).toPath());
% needs absolute()
file = stdlib.absolute(file);

ok = java.nio.file.Files.isReadable(java.io.File(file).toPath());

end
4 changes: 2 additions & 2 deletions +stdlib/is_regular_file.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

opt = java.nio.file.LinkOption.values;

% not correct without canonical(). Normalize() doesn't help.
p = stdlib.canonical(p);
% needs absolute()
p = stdlib.absolute(p);

isreg = java.nio.file.Files.isRegularFile(java.io.File(p).toPath(), opt);

Expand Down
4 changes: 2 additions & 2 deletions +stdlib/is_symlink.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

if isMATLABReleaseOlderThan("R2024b")
% must be absolute path
% must be .resolve, NOT .canonical or symlink is gobbled!
p = stdlib.resolve(p);
% NOT .canonical or symlink is gobbled!
p = stdlib.absolute(p);
ok = java.nio.file.Files.isSymbolicLink(java.io.File(p).toPath());
else
ok = isSymbolicLink(p);
Expand Down
5 changes: 4 additions & 1 deletion +stdlib/is_writable.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
file (1,1) string
end

ok = java.nio.file.Files.isWritable(java.io.File(stdlib.canonical(file)).toPath());
% needs absolute()
file = stdlib.absolute(file);

ok = java.nio.file.Files.isWritable(java.io.File(file).toPath());

end
2 changes: 1 addition & 1 deletion +stdlib/read_symlink.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

% must be absolute path
% must not be .canonical or symlink is gobbled!
r = stdlib.resolve(p);
r = stdlib.absolute(p);

% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/file/Files.html#readSymbolicLink(java.nio.file.Path)
r = stdlib.posix(...
Expand Down
39 changes: 7 additions & 32 deletions +stdlib/resolve.m
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
function c = resolve(p, expand_tilde)
%% resolve(p)
% path need not exist--absolute path will be relative to pwd if not exist
% if path exists, same result as canonical()
%
% NOTE: some network file systems are not resolvable by Matlab Java
% subsystem, but are sometimes still valid--so return
% unmodified path if this occurs.
%
% This also resolves Windows short paths to full long paths.
%
function r = resolve(p, expand_tilde)
% resolve path, to cwd if relative
% effectively canonical(absolute(p))
%%% Inputs
% * p: path to resolve
% * p: path to make absolute
% * expand_tilde: expand ~ to username if present
%%% Outputs
% * c: resolved path
% distinct from canonical(), resolve() always returns absolute path
Expand All @@ -20,24 +13,6 @@
expand_tilde (1,1) logical=true
end

if expand_tilde
c = stdlib.expanduser(p);
else
c = p;
end

if ispc && startsWith(c, "\\")
% UNC path is not canonicalized
return
end

if ~stdlib.is_absolute(c)
% .toAbsolutePath() default is Documents/Matlab, which is probably not wanted.
c = stdlib.join(pwd, c);
end

% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html#getAbsolutePath()

c = stdlib.posix(java.io.File(java.io.File(c).getAbsolutePath()).toPath().normalize());
r = stdlib.canonical(stdlib.absolute(p, expand_tilde), false);

end % function
end
6 changes: 3 additions & 3 deletions +stdlib/samepath.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
return
end

% not correct without canonical(). Normalize() doesn't help.
path1 = stdlib.canonical(path1);
path2 = stdlib.canonical(path2);
% needs absolute
path1 = stdlib.absolute(path1);
path2 = stdlib.absolute(path2);

issame = java.nio.file.Files.isSameFile(...
java.io.File(path1).toPath(), ...
Expand Down
19 changes: 19 additions & 0 deletions test/TestFileImpure.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ function test_touch_modtime(tc)
end


function test_absolute(tc)
import matlab.unittest.fixtures.TemporaryFolderFixture
import matlab.unittest.fixtures.CurrentFolderFixture
import matlab.unittest.constraints.StartsWithSubstring
import matlab.unittest.constraints.EndsWithSubstring

td = tc.applyFixture(TemporaryFolderFixture).Folder;
tc.applyFixture(CurrentFolderFixture(td))

tc.verifyEqual(stdlib.absolute(""), string(td))
tc.verifyEqual(stdlib.absolute("",""), string(td))
tc.verifyEqual(stdlib.absolute("hi"), stdlib.join(td, "hi"))
tc.verifyEqual(stdlib.absolute("", "hi"), stdlib.join(td, "hi"))
tc.verifyEqual(stdlib.absolute("there", "hi"), stdlib.join(td, "hi/there"))

end



function test_canonical(tc)
import matlab.unittest.fixtures.TemporaryFolderFixture
import matlab.unittest.fixtures.CurrentFolderFixture
Expand Down

0 comments on commit 5a2ae56

Please sign in to comment.