changeset 27331:3bf19af20af8

tar, untar, unpack: Add support for BSD tar (bug #53695) * tar_is_bsd.m: New function. * tar.m: Use it to determine how to run tar and parse command output. * unpack.m: Likewise.
author Andrew Janke <andrew@apjanke.net>
date Mon, 21 Jan 2019 20:07:28 -0500
parents e449134870fb
children c80ba7295b5e
files scripts/miscellaneous/private/tar_is_bsd.m scripts/miscellaneous/tar.m scripts/miscellaneous/unpack.m
diffstat 3 files changed, 60 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/private/tar_is_bsd.m	Mon Jan 21 20:07:28 2019 -0500
@@ -0,0 +1,42 @@
+## Copyright (C) 2019 Andrew Janke
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{out} =} tar_is_bsd ()
+## True if the default tar command is BSD tar.
+##
+## Checks whether the default tar command (the one invoked when an un-prefixed
+## @code{tar} is executed) is BSD tar or another tar. Caches the results for
+## performance.
+##
+## Returns true if the detected tar is BSD tar, and false otherwise. Errors if
+## @code{tar --version} does not succeed.
+## @end deftypefn
+
+function out = tar_is_bsd ()
+  ## BSD tar needs to be handled differently from GNU tar
+  persistent cache
+  if isempty (cache)
+    [status, tar_ver_str] = system ("tar --version");
+    if (status)
+      error ("tar: Failed executing tar --version (status = %d)", status);
+    endif
+    cache = ! isempty (regexp (tar_ver_str, "bsdtar"));
+  endif
+  out = cache;
+endfunction
--- a/scripts/miscellaneous/tar.m	Wed Aug 07 19:21:35 2019 +0200
+++ b/scripts/miscellaneous/tar.m	Mon Jan 21 20:07:28 2019 -0500
@@ -60,8 +60,14 @@
     tarfile = __w2mpth__ (tarfile);
   endif
 
-  cmd = sprintf ("tar cvf %s -C %s %s",
-                          tarfile, rootdir, sprintf (" %s", files{:}));
+  ## BSD tar emits progress on stderr
+  if (tar_is_bsd ())
+    cmd = sprintf ("tar cvf %s -C %s %s 2>&1",
+                            tarfile, rootdir, sprintf (" '%s'", files{:}));
+  else
+    cmd = sprintf ("tar cvf %s -C %s %s",
+                            tarfile, rootdir, sprintf (" %s", files{:}));
+  end
 
   ## Save and restore the TAR_OPTIONS environment variable used by GNU tar.
   tar_options_env = getenv ("TAR_OPTIONS");
@@ -81,6 +87,11 @@
   if (nargout > 0)
     filelist = ostrsplit (output, "\r\n", true);
     filelist = filelist';
+
+    ## BSD tar emits file actions in the first 2 columns
+    if (tar_is_bsd ())
+      filelist = cellfun (@(x) x(3:end), filelist, 'UniformOutput', false);
+    endif
   endif
 
 endfunction
--- a/scripts/miscellaneous/unpack.m	Wed Aug 07 19:21:35 2019 +0200
+++ b/scripts/miscellaneous/unpack.m	Mon Jan 21 20:07:28 2019 -0500
@@ -308,7 +308,11 @@
 endfunction
 
 function output = __parse_tar__ (output)
-  ## This is a no-op, but it makes things simpler for other cases.
+  ## BSD tar emits file actions in the first 2 columns
+
+  if (tar_is_bsd ())
+    output = cellfun (@(x) x(3:end), output, 'UniformOutput', false);
+  endif
 endfunction
 
 function files = __parse_gzip__ (output)