Skip to content

Commit bd196c4

Browse files
committed
subprocess_run: add cwd option
extract_zstd: try with cmake, fallback zstd
1 parent 87400c9 commit bd196c4

File tree

4 files changed

+59
-12
lines changed

4 files changed

+59
-12
lines changed

+stdlib/+fileio/extract_zstd.m

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
function extract_zstd(archive, out_dir)
22
% extract a zstd file "archive" to "out_dir"
33
% out_dir need not exist yet, but its parent must
4-
% we do this in two steps to be reliable with old tar versions
5-
% https://www.scivision.dev/tar-extract-zstd
4+
% We do this with CMake to avoid problems with old system tar.
5+
% For our user audience, CMake is at least as likely to be installed as Zstd.
66

77
arguments
88
archive (1,1) string
99
out_dir (1,1) string
1010
end
1111

12-
import stdlib.fileio.expanduser
12+
import stdlib.fileio.absolute_path
1313
import stdlib.fileio.which
14+
import stdlib.sys.subprocess_run
1415

15-
archive = expanduser(archive);
16+
archive = absolute_path(archive);
17+
out_dir = absolute_path(out_dir);
1618

1719
assert(isfile(archive), "%s is not a file", archive)
20+
assert(isfolder(out_dir), "%s is not a folder", out_dir)
21+
22+
exe = which("cmake");
23+
if isempty(exe)
24+
extract_zstd_bin(archive, outdir)
25+
end
26+
27+
[ret, msg] = subprocess_run([exe, "-E", "tar", "xf", archive], "cwd", out_dir);
28+
assert(ret == 0, "problem extracting %s %s", archive, msg)
29+
30+
end
31+
32+
33+
function extract_zstd_bin(archive, out_dir)
34+
% Extract .zst in two steps .zst => .tar =>
35+
% to avoid problems with old system tar.
36+
arguments
37+
archive (1,1) string
38+
out_dir (1,1) string
39+
end
1840

1941
exe = which("zstd");
2042
assert(~isempty(exe), "need to have Zstd installed: https://github.com/facebook/zstd")
@@ -26,5 +48,4 @@ function extract_zstd(archive, out_dir)
2648

2749
untar(tar_arc, out_dir)
2850
delete(tar_arc)
29-
3051
end

+stdlib/+sys/subprocess_run.m

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function [status, msg] = subprocess_run(cmd_array, env)
1+
function [status, msg] = subprocess_run(cmd_array, opt)
22
% handle command lines with spaces
33
% input each segment of the command as an element in a string array
44
% this is how python subprocess.run works
@@ -7,12 +7,18 @@
77
% sys.subprocess_run(["mpiexec", "-help2"])
88
% sys.subprocess_run(["ls", "-l"])
99
% sys.subprocess_run(["dir", "/Q", "/L"])
10+
%
11+
% NOTE: if cwd option used, any paths must be absolute or relative to cwd.
12+
% otherwise, they are relative to pwd.
1013

1114
arguments
1215
cmd_array (1,:) string
13-
env (1,1) struct = struct()
16+
opt.env (1,1) struct = struct()
17+
opt.cwd string {mustBeScalarOrEmpty} = string.empty
1418
end
1519

20+
import stdlib.fileio.absolute_path
21+
1622
exe = space_quote(cmd_array(1));
1723

1824
if length(cmd_array) > 1
@@ -21,18 +27,29 @@
2127
cmd = exe;
2228
end
2329

24-
if ~isempty(fieldnames(env))
25-
for f = string(fieldnames(env)).'
30+
if ~isempty(fieldnames(opt.env))
31+
for f = string(fieldnames(opt.env)).'
2632
if ispc
27-
cmd = append("set ", f, "=", env.(f), " && ", cmd);
33+
cmd = append("set ", f, "=", opt.env.(f), " && ", cmd);
2834
else
29-
cmd = append(f, "=", env.(f), " ", cmd);
35+
cmd = append(f, "=", opt.env.(f), " ", cmd);
3036
end
3137
end
3238
end
3339

40+
if ~isempty(opt.cwd)
41+
cwd = absolute_path(opt.cwd);
42+
assert(isfolder(cwd), "subprocess_run: %s is not a folder", cwd)
43+
oldcwd = pwd;
44+
cd(cwd)
45+
end
46+
3447
[status, msg] = system(cmd);
3548

49+
if ~isempty(opt.cwd)
50+
cd(oldcwd)
51+
end
52+
3653
end
3754

3855

+stdlib/TestSys.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
methods (Test)
44

5+
function test_run(tc)
6+
if ispc
7+
cmd = 'dir';
8+
else
9+
cmd = 'ls';
10+
end
11+
tc.verifyEqual(stdlib.sys.subprocess_run(cmd), 0)
12+
end
13+
514
function test_find_fortran(tc)
615
import matlab.unittest.constraints.IsOfClass
716
tc.verifyThat(stdlib.sys.find_fortran_compiler(), IsOfClass('string'))

codemeta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"downloadUrl": "https://github.com/geospace-code/matlab-stdlib/releases",
99
"issueTracker": "https://github.com/geospace-code/matlab-stdlib/issues",
1010
"name": "matlab-stdlib",
11-
"version": "4.1.3",
11+
"version": "4.1.4",
1212
"identifier": "10.5281/zenodo.3964541",
1313
"description": "Matlab unofficial standard library, including HDF5 / NetCDF4 functions that should be included in Matlab.",
1414
"applicationCategory": "computation",

0 commit comments

Comments
 (0)