Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package charliecloud for openSUSE:Factory 
checked in at 2021-05-21 21:50:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/charliecloud (Old)
 and      /work/SRC/openSUSE:Factory/.charliecloud.new.2988 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "charliecloud"

Fri May 21 21:50:18 2021 rev:18 rq:894813 version:0.23

Changes:
--------
--- /work/SRC/openSUSE:Factory/charliecloud/charliecloud.changes        
2021-02-22 14:41:15.572677486 +0100
+++ /work/SRC/openSUSE:Factory/.charliecloud.new.2988/charliecloud.changes      
2021-05-21 21:50:31.122108554 +0200
@@ -1,0 +2,14 @@
+Mon May  3 16:37:44 UTC 2021 - Ferdinand Thiessen <[email protected]>
+
+- Update to version 0.23
+  * ch-image push: now works with Docker Hub
+  * ch-image:
+    * remove compatibility alias ch-grow
+    * new subcommand reset
+  * ch-image build: fix bugs in whitespace handling
+  * miscellaneous bug fixes and improvements
+  * Full changes:
+    https://github.com/hpc/charliecloud/compare/v0.22...v0.23
+- Only apply Replace-hardcode-path.patch if needed
+
+-------------------------------------------------------------------

Old:
----
  charliecloud-0.22.tar.gz

New:
----
  charliecloud-0.23.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ charliecloud.spec ++++++
--- /var/tmp/diff_new_pack.mET4Mt/_old  2021-05-21 21:50:32.602102424 +0200
+++ /var/tmp/diff_new_pack.mET4Mt/_new  2021-05-21 21:50:32.606102408 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           charliecloud
-Version:        0.22
+Version:        0.23
 Release:        0
 Summary:        User-defined software stacks (UDSS) for HPC centers
 License:        Apache-2.0
@@ -29,15 +29,15 @@
 # Recommend for ch-grow
 # used to build images
 Requires:       fakeroot
-Recommends:     docker
 Recommends:     buildah >= 1.11.2
+Recommends:     docker
 Recommends:     python3-requests >= 2.6.0
 Recommends:     squashfs >= 4.2
-%if !(0%{?sle_version} <= 120400 && 0%{?is_backports})
+%if !(0%{?sle_version} <= 120500 && !0%{?is_opensuse})
 Recommends:     python3-lark-parser >= 0.7.1
 %endif
 # Build the documentation
-%if !(0%{?sle_version} <= 120400 && 0%{?is_backports})
+%if !(0%{?sle_version} <= 120500 && !0%{?is_opensuse})
 BuildRequires:  python3-Sphinx
 BuildRequires:  python3-sphinx_rtd_theme
 BuildRequires:  rsync
@@ -80,7 +80,9 @@
 
 %prep
 %setup -q
+%if "%{_lib}" == "lib64"
 %patch0 -p 1
+%endif
 
 %build
 %configure --disable-test
@@ -90,7 +92,7 @@
 %make_install
 
 # Documentation won't build on SLE-12
-%if !(0%{?sle_version} <= 120400 && 0%{?is_backports})
+%if !(0%{?sle_version} <= 120500 && !0%{?is_opensuse})
 mv %{buildroot}%{_datadir}/doc/charliecloud/html .
 %endif
 
@@ -114,7 +116,7 @@
 %dir %{_libdir}/charliecloud/
 %{_libdir}/charliecloud/*
 
-%if !(0%{?sle_version} <= 120400 && 0%{?is_backports})
+%if !(0%{?sle_version} <= 120500 && !0%{?is_opensuse})
 %{_mandir}/man1/*
 %{_mandir}/man7/*
 

++++++ charliecloud-0.22.tar.gz -> charliecloud-0.23.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/.github/workflows/main.yml 
new/charliecloud-0.23/.github/workflows/main.yml
--- old/charliecloud-0.22/.github/workflows/main.yml    2021-01-27 
18:27:08.000000000 +0100
+++ new/charliecloud-0.23/.github/workflows/main.yml    2021-03-13 
01:13:51.000000000 +0100
@@ -14,7 +14,7 @@
     strategy:
       fail-fast: true  # if any job fails, cancel the rest immediately
       matrix:
-        builder: [none, docker, ch-image, buildah, buildah-runc, 
buildah-setuid]
+        builder: [none, docker, ch-image]
         keep_sudo:  # if false, remove self from sudoers after install/setup
           - false
         include:
@@ -68,6 +68,7 @@
           getconf _NPROCESSORS_ONLN
           free -m
           df -h
+          locale -a
 
       - name: lines of code
         if: ${{ matrix.builder == 'none' }}
@@ -89,21 +90,24 @@
           [[ $(command -v bats) == /usr/local/bin/bats ]]
           [[ $(bats --version) == 'Bats 0.4.0' ]]
 
-      - name: install/configure dependencies, all
-        run: |
-          # configure doesn't tell us about these.
-          sudo apt-get install pigz pv
-          # configure does tell us about these.
-          sudo apt-get install squashfs-tools squashfuse
-          # Track newest Sphinx in case it breaks things.
-          sudo su -c 'umask 0022 && pip3 install sphinx sphinx-rtd-theme'
-
       - name: install/configure dependencies, ch-image
         if: ${{ matrix.builder == 'ch-image' }}
         run: |
-          # Use most current Lark rather than the one in Ubuntu b/c new
-          # versions sometimes break things.
-          sudo su -c 'umask 0022 && pip3 install lark-parser'
+          # Install the minimum Python version we support (issue #959). Python
+          # is pretty quick to build, so this only takes a couple of minutes.
+          cd /usr/local/src
+          wget -nv 
https://www.python.org/ftp/python/3.6.12/Python-3.6.12.tar.xz
+          tar xf Python-3.6.12.tar.xz
+          cd Python-3.6.12
+          ./configure --prefix=/usr/local
+          make $ch_makej
+          sudo sh -c 'umask 0022 && make install'
+          command -v pip3
+          command -v python3
+          [[ $(command -v pip3) == /usr/local/bin/pip3 ]]
+          [[ $(command -v python3) == /usr/local/bin/python3 ]]
+          # Use most current packages b/c new versions sometimes break things.
+          sudo sh -c 'umask 0022 && pip3 install lark-parser requests'
 
       - name: install/configure dependencies, all Buildah
         if: ${{ startsWith(matrix.builder, 'buildah') }}
@@ -127,6 +131,15 @@
           sudo usermod --add-subuids 10000-65536 $USER
           sudo usermod --add-subgids 10000-65536 $USER
 
+      - name: install/configure dependencies, all
+        run: |
+          # configure doesn't tell us about these.
+          sudo apt-get install pigz pv
+          # configure does tell us about these.
+          sudo apt-get install squashfs-tools squashfuse
+          # Track newest Sphinx in case it breaks things.
+          sudo su -c 'umask 0022 && pip3 install sphinx sphinx-rtd-theme'
+
       - name: build/install from Git
         run: |
           ./autogen.sh
@@ -149,7 +162,12 @@
           bin/ch-run --version
           $ch_prefix/from-git/bin/ch-run --version
 
-      - name: late setup & validation
+      - name: late setup & validation, ch-image
+        if: ${{ matrix.builder == 'ch-image' }}
+        run: |
+          [[ $(bin/ch-image python-path) = /usr/local/bin/python3 ]]
+
+      - name: late setup & validation, all
         run: |
           bin/ch-test --is-pedantic all
           bin/ch-test --is-sudo all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/VERSION 
new/charliecloud-0.23/VERSION
--- old/charliecloud-0.22/VERSION       2021-02-08 18:55:08.000000000 +0100
+++ new/charliecloud-0.23/VERSION       2021-04-17 00:24:56.000000000 +0200
@@ -1 +1 @@
-0.22
+0.23
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/Makefile.am 
new/charliecloud-0.23/bin/Makefile.am
--- old/charliecloud-0.22/bin/Makefile.am       2021-01-20 23:15:34.000000000 
+0100
+++ new/charliecloud-0.23/bin/Makefile.am       2021-03-16 18:10:00.000000000 
+0100
@@ -33,15 +33,14 @@
 
 ## Python scripts - need text processing
 
-bin_SCRIPTS = ch-run-oci          # scripts to build
-EXTRA_SCRIPTS = ch-image ch-grow  # more scripts that *may* be built
+bin_SCRIPTS = ch-run-oci  # scripts to build
+EXTRA_SCRIPTS = ch-image  # more scripts that *may* be built
 if ENABLE_CH_IMAGE
-bin_SCRIPTS += ch-image ch-grow
+bin_SCRIPTS += ch-image
 endif
-EXTRA_DIST = ch-grow.py.in ch-image.py.in ch-run-oci.py.in
+EXTRA_DIST = ch-image.py.in ch-run-oci.py.in
 CLEANFILES = $(bin_SCRIPTS) $(EXTRA_SCRIPTS)
 
-ch-grow: ch-grow.py.in
 ch-image: ch-image.py.in
 ch-run-oci: ch-run-oci.py.in
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/Makefile.in 
new/charliecloud-0.23/bin/Makefile.in
--- old/charliecloud-0.22/bin/Makefile.in       2021-02-08 19:11:07.000000000 
+0100
+++ new/charliecloud-0.23/bin/Makefile.in       2021-04-17 00:25:06.000000000 
+0200
@@ -94,7 +94,7 @@
 build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = ch-checkns$(EXEEXT) ch-run$(EXEEXT) ch-ssh$(EXEEXT)
-@ENABLE_CH_IMAGE_TRUE@am__append_1 = ch-image ch-grow
+@ENABLE_CH_IMAGE_TRUE@am__append_1 = ch-image
 subdir = bin
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/misc/m4/ax_check_compile_flag.m4 \
@@ -370,8 +370,8 @@
                    ch-umount
 
 bin_SCRIPTS = ch-run-oci $(am__append_1)
-EXTRA_SCRIPTS = ch-image ch-grow  # more scripts that *may* be built
-EXTRA_DIST = ch-grow.py.in ch-image.py.in ch-run-oci.py.in
+EXTRA_SCRIPTS = ch-image  # more scripts that *may* be built
+EXTRA_DIST = ch-image.py.in ch-run-oci.py.in
 CLEANFILES = $(bin_SCRIPTS) $(EXTRA_SCRIPTS)
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
@@ -849,7 +849,6 @@
 .PRECIOUS: Makefile
 
 
-ch-grow: ch-grow.py.in
 ch-image: ch-image.py.in
 ch-run-oci: ch-run-oci.py.in
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/ch-build 
new/charliecloud-0.23/bin/ch-build
--- old/charliecloud-0.22/bin/ch-build  2021-01-26 19:29:41.000000000 +0100
+++ new/charliecloud-0.23/bin/ch-build  2021-03-16 18:10:00.000000000 +0100
@@ -11,7 +11,8 @@
 
   $ $(basename "$0") [-b BUILDER] [--builder-info] -t TAG [ARGS ...] CONTEXT
 
-BUILDER is one of: buildah ch-image docker.
+BUILDER is "ch-image" or "docker"
+        (or experimentally: "buildah", "buildah-runc", "buildah-setuid")
 ARGS are passed unchanged to the underlying builder.
 EOF
 )
@@ -48,7 +49,7 @@
         buildah*)
             buildah --version
             ;;
-        ch-image|ch-grow)
+        ch-image)
             "${ch_bin}/ch-image" --version
             ;;
         docker)
@@ -123,7 +124,7 @@
                     "$@"
         fi
         ;;
-    ch-image|ch-grow)
+    ch-image)
         "${ch_bin}/ch-image" build "$@"
         ;;
     docker)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/ch-builder2tar 
new/charliecloud-0.23/bin/ch-builder2tar
--- old/charliecloud-0.22/bin/ch-builder2tar    2021-01-27 18:27:08.000000000 
+0100
+++ new/charliecloud-0.23/bin/ch-builder2tar    2021-03-16 18:10:00.000000000 
+0100
@@ -130,7 +130,7 @@
 
     ;;
 
-ch-image|ch-grow)
+ch-image)
 
     echo "exporting"
     storage=$("${ch_bin}/ch-image" storage-path)/img/$(tag_to_path "$image")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/ch-grow.py.in 
new/charliecloud-0.23/bin/ch-grow.py.in
--- old/charliecloud-0.22/bin/ch-grow.py.in     2020-12-10 00:16:47.000000000 
+0100
+++ new/charliecloud-0.23/bin/ch-grow.py.in     1970-01-01 01:00:00.000000000 
+0100
@@ -1,20 +0,0 @@
-#!%PYTHON_SHEBANG%
-
-import subprocess
-import sys
-
-ch_image = sys.path[0] + "/ch-image"
-rc = subprocess.call([ch_image] + sys.argv[1:])
-
-print("""\
-
-
-******************************************************************************
-
-NOTE: This program is now called ch-image. We plan to remove the ch-grow name
-in Charliecloud version 0.23.
-
-******************************************************************************
-""", end="", file=sys.stderr)
-
-sys.exit(rc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/ch-image.py.in 
new/charliecloud-0.23/bin/ch-image.py.in
--- old/charliecloud-0.22/bin/ch-image.py.in    2021-02-04 00:15:39.000000000 
+0100
+++ new/charliecloud-0.23/bin/ch-image.py.in    2021-04-09 21:49:04.000000000 
+0200
@@ -171,6 +171,19 @@
    sp.add_argument("dest_ref", metavar="DEST_REF", nargs="?",
                    help="destination image reference (default: IMAGE_REF)")
 
+   # python-path
+   help="print path to python interpreter in use"
+   sp = sps.add_parser("python-path", help=help, description=help,
+                       formatter_class=ch.HelpFormatter)
+   sp.set_defaults(func=misc.python_path)
+
+   # reset
+   help="delete everything in ch-image builder storage"
+   sp = sps.add_parser("reset", help=help, description=help,
+                       formatter_class=ch.HelpFormatter)
+   sp.set_defaults(func=misc.reset)
+   add_opts(sp, common_opts, True)
+
    # storage-path
    help="print storage directory path"
    sp = sps.add_parser("storage-path", help=help, description=help,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/bin/ch-test 
new/charliecloud-0.23/bin/ch-test
--- old/charliecloud-0.22/bin/ch-test   2021-01-22 23:36:01.000000000 +0100
+++ new/charliecloud-0.23/bin/ch-test   2021-03-16 18:10:00.000000000 +0100
@@ -64,7 +64,7 @@
 builder_check () {
     printf 'checking builder ...\n'
     case $CH_BUILDER in
-    ch-image|ch-grow)
+    ch-image)
         if ! "${ch_bin}/ch-image" --dependencies; then
             fatal 'builder: ch-image: missing dependencies'
         fi
@@ -113,25 +113,6 @@
         builder_choose
         method='default'
     fi
-    if [[ $CH_BUILDER == ch-grow ]]; then
-        export CH_BUILDER=ch-image
-        cat <<'EOF' 1>&2
-
-WARNING: ch-grow is now called ch-image. We plan to remove the ch-grow name in
-Charliecloud version 0.23.
-
-EOF
-    fi
-    if [[ -n $CH_GROW_STORAGE ]]; then
-        export CH_IMAGE_STORAGE=$CH_GROW_STORAGE
-        unset CH_GROW_STORAGE
-        cat <<'EOF' 1>&2
-
-WARNING: $CH_GROW_STORAGE is now called $CH_IMAGE_STORAGE. We plan to remove
-the old name in Charliecloud version 0.23.
-
-EOF
-    fi
     printf "%-*s %s (%s)\n" "$width" 'builder:' "$CH_BUILDER" "$method"
     if [[ $CH_BUILDER == ch-image ]]; then
         vset CH_IMAGE_STORAGE '' "$CH_IMAGE_STORAGE" "/var/tmp/$USER/ch-image" 
\
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/configure 
new/charliecloud-0.23/configure
--- old/charliecloud-0.22/configure     2021-02-08 19:11:06.000000000 +0100
+++ new/charliecloud-0.23/configure     2021-04-17 00:25:05.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Charliecloud 0.22.
+# Generated by GNU Autoconf 2.69 for Charliecloud 0.23.
 #
 # Report bugs to <https://github.com/hpc/charliecloud>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='Charliecloud'
 PACKAGE_TARNAME='charliecloud'
-PACKAGE_VERSION='0.22'
-PACKAGE_STRING='Charliecloud 0.22'
+PACKAGE_VERSION='0.23'
+PACKAGE_STRING='Charliecloud 0.23'
 PACKAGE_BUGREPORT='https://github.com/hpc/charliecloud'
 PACKAGE_URL=''
 
@@ -1301,7 +1301,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Charliecloud 0.22 to adapt to many kinds of systems.
+\`configure' configures Charliecloud 0.23 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1372,7 +1372,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Charliecloud 0.22:";;
+     short | recursive ) echo "Configuration of Charliecloud 0.23:";;
    esac
   cat <<\_ACEOF
 
@@ -1480,7 +1480,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Charliecloud configure 0.22
+Charliecloud configure 0.23
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1660,7 +1660,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Charliecloud $as_me 0.22, which was
+It was created by Charliecloud $as_me 0.23, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2628,7 +2628,7 @@
 
 # Define the identity of the package.
  PACKAGE='charliecloud'
- VERSION='0.22'
+ VERSION='0.23'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6233,7 +6233,7 @@
 $as_echo "$have_nvidia_libs" >&6; }
 
 # Python
-vmin_python=3.4
+vmin_python=3.6
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"$PYTHON_SHEBANG\" 
starts with slash" >&5
 $as_echo_n "checking if \"$PYTHON_SHEBANG\" starts with slash... " >&6; }
 case $PYTHON_SHEBANG in #(
@@ -7794,7 +7794,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Charliecloud $as_me 0.22, which was
+This file was extended by Charliecloud $as_me 0.23, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7860,7 +7860,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Charliecloud config.status 0.22
+Charliecloud config.status 0.23
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/configure.ac 
new/charliecloud-0.23/configure.ac
--- old/charliecloud-0.22/configure.ac  2021-01-27 18:27:08.000000000 +0100
+++ new/charliecloud-0.23/configure.ac  2021-03-13 01:13:51.000000000 +0100
@@ -315,7 +315,7 @@
 AC_MSG_RESULT($have_nvidia_libs)
 
 # Python
-vmin_python=3.4
+vmin_python=3.6
 AC_MSG_CHECKING([if "$PYTHON_SHEBANG" starts with slash])
 AS_CASE([$PYTHON_SHEBANG],
   [/*], [AC_MSG_RESULT([ok])],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/Makefile.am 
new/charliecloud-0.23/doc/Makefile.am
--- old/charliecloud-0.22/doc/Makefile.am       2021-01-27 18:27:08.000000000 
+0100
+++ new/charliecloud-0.23/doc/Makefile.am       2021-03-16 18:10:00.000000000 
+0100
@@ -35,8 +35,6 @@
 ch-dir2squash.rst \
 ch-fromhost_desc.rst \
 ch-fromhost.rst \
-ch-grow_desc.rst \
-ch-grow.rst \
 ch-image_desc.rst \
 ch-image.rst \
 ch-mount_desc.rst \
@@ -82,7 +80,6 @@
 man/ch-checkns.1 \
 man/ch-dir2squash.1 \
 man/ch-fromhost.1 \
-man/ch-grow.1 \
 man/ch-image.1 \
 man/ch-mount.1 \
 man/ch-pull2dir.1 \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/Makefile.in 
new/charliecloud-0.23/doc/Makefile.in
--- old/charliecloud-0.22/doc/Makefile.in       2021-02-08 19:11:07.000000000 
+0100
+++ new/charliecloud-0.23/doc/Makefile.in       2021-04-17 00:25:06.000000000 
+0200
@@ -311,8 +311,6 @@
 ch-dir2squash.rst \
 ch-fromhost_desc.rst \
 ch-fromhost.rst \
-ch-grow_desc.rst \
-ch-grow.rst \
 ch-image_desc.rst \
 ch-image.rst \
 ch-mount_desc.rst \
@@ -357,7 +355,6 @@
 @ENABLE_MAN_TRUE@man/ch-checkns.1 \
 @ENABLE_MAN_TRUE@man/ch-dir2squash.1 \
 @ENABLE_MAN_TRUE@man/ch-fromhost.1 \
-@ENABLE_MAN_TRUE@man/ch-grow.1 \
 @ENABLE_MAN_TRUE@man/ch-image.1 \
 @ENABLE_MAN_TRUE@man/ch-mount.1 \
 @ENABLE_MAN_TRUE@man/ch-pull2dir.1 \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/ch-build_desc.rst 
new/charliecloud-0.23/doc/ch-build_desc.rst
--- old/charliecloud-0.22/doc/ch-build_desc.rst 2020-12-10 00:06:07.000000000 
+0100
+++ new/charliecloud-0.23/doc/ch-build_desc.rst 2021-03-01 22:54:16.000000000 
+0100
@@ -20,14 +20,18 @@
 
 Supported builders, unprivileged:
 
-  * :code:`buildah`: Buildah in "rootless" mode with no setuid helpers, using
-    :code:`ch-run` (via :code:`ch-run-oci`) for :code:`RUN` instructions. This
-    requires Buildah v1.10.1+; see the install instructions.
-
   * :code:`ch-image`: Our internal builder.
 
 Supported builders, privileged:
 
+  * :code:`docker`: Docker.
+
+Experimental builders (i.e., the code is there but not tested much):
+
+  * :code:`buildah`: Buildah in "rootless" mode with no setuid helpers, using
+    :code:`ch-run` (via :code:`ch-run-oci`) for :code:`RUN` instructions. This
+    mode is fully unprivileged.
+
   * :code:`buildah-runc`: Buildah in "rootless" mode with setuid
     helpers, using the default :code:`runc` for :code:`RUN` instructions.
 
@@ -35,8 +39,6 @@
     using :code:`ch-run` (via :code:`ch-run-oci`) for :code:`RUN`
     instructions.
 
-  * :code:`docker`: Docker.
-
 Specifying the builder, in descending order of priority:
 
   :code:`-b`, :code:`--builder BUILDER`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/ch-grow.rst 
new/charliecloud-0.23/doc/ch-grow.rst
--- old/charliecloud-0.22/doc/ch-grow.rst       2020-04-15 21:31:09.000000000 
+0200
+++ new/charliecloud-0.23/doc/ch-grow.rst       1970-01-01 01:00:00.000000000 
+0100
@@ -1,8 +0,0 @@
-:orphan:
-
-ch-grow man page
-++++++++++++++++
-
-.. include:: ./ch-grow_desc.rst
-.. include:: ./bugs.rst
-.. include:: ./see_also.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/ch-grow_desc.rst 
new/charliecloud-0.23/doc/ch-grow_desc.rst
--- old/charliecloud-0.22/doc/ch-grow_desc.rst  2020-12-10 00:22:56.000000000 
+0100
+++ new/charliecloud-0.23/doc/ch-grow_desc.rst  1970-01-01 01:00:00.000000000 
+0100
@@ -1,4 +0,0 @@
-Synopsis
-========
-
-Deprecated name for :code:`ch-image`; will be removed in version 0.23.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/ch-image_desc.rst 
new/charliecloud-0.23/doc/ch-image_desc.rst
--- old/charliecloud-0.22/doc/ch-image_desc.rst 2021-02-05 21:09:13.000000000 
+0100
+++ new/charliecloud-0.23/doc/ch-image_desc.rst 2021-04-09 21:49:04.000000000 
+0200
@@ -8,6 +8,7 @@
    $ ch-image [...] list
    $ ch-image [...] pull [...] IMAGE_REF [IMAGE_DIR]
    $ ch-image [...] push [--image DIR] IMAGE_REF [DEST_REF]
+   $ ch-image [...] reset
    $ ch-image [...] storage-path
    $ ch-image { --help | --version | --dependencies }
 
@@ -290,6 +291,11 @@
     Use the unpacked image located at :code:`DIR` rather than an image in the
     storage directory named :code:`IMAGE_REF`.
 
+:code:`reset`
+-------------
+
+Delete all images and cache from ch-image builder storage.
+
 :code:`storage-path`
 --------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/charliecloud.rst 
new/charliecloud-0.23/doc/charliecloud.rst
--- old/charliecloud-0.22/doc/charliecloud.rst  2020-12-10 00:06:07.000000000 
+0100
+++ new/charliecloud-0.23/doc/charliecloud.rst  2021-03-16 18:10:00.000000000 
+0100
@@ -17,7 +17,6 @@
 ch-checkns(1),
 ch-dir2squash(1),
 ch-fromhost(1),
-ch-grow(1),
 ch-image(1),
 ch-mount(1),
 ch-pull2dir(1),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/command-usage.rst 
new/charliecloud-0.23/doc/command-usage.rst
--- old/charliecloud-0.22/doc/command-usage.rst 2020-12-10 00:06:07.000000000 
+0100
+++ new/charliecloud-0.23/doc/command-usage.rst 2021-03-16 18:10:00.000000000 
+0100
@@ -54,13 +54,6 @@
 
 .. include:: ./ch-builder2squash_desc.rst
 
-ch-grow
-+++++++
-
-Deprecated name for :code:`ch-image`; will be removed in version 0.23.
-
-.. include:: ./ch-grow_desc.rst
-
 ch-fromhost
 +++++++++++
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/conf.py 
new/charliecloud-0.23/doc/conf.py
--- old/charliecloud-0.22/doc/conf.py   2020-12-10 00:06:07.000000000 +0100
+++ new/charliecloud-0.23/doc/conf.py   2021-03-16 18:10:00.000000000 +0100
@@ -262,9 +262,6 @@
    ("ch-dir2squash", "ch-dir2squash",
     "Create a SquashFS file from an image directory",
     [], 1),
-   ("ch-grow", "ch-grow",
-    'Deprecated name for "ch-image"; will be removed in version 0.23.',
-    [], 1),
    ("ch-fromhost", "ch-fromhost",
     "Inject files from the host into an image directory, with various magic",
     [], 1),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/doc/dev.rst 
new/charliecloud-0.23/doc/dev.rst
--- old/charliecloud-0.22/doc/dev.rst   2020-12-09 01:49:33.000000000 +0100
+++ new/charliecloud-0.23/doc/dev.rst   2021-03-16 18:10:00.000000000 +0100
@@ -71,11 +71,13 @@
 Peer review
 -----------
 
-**Issues and pull requests.** The standard workflow is to introduce a
-change in an issue, get consensus on what to do, and then create a `pull
+**Issues and pull requests.** The standard workflow is to introduce a change
+in an issue, get consensus on what to do, and then create a *draft* `pull
 request <https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project>`_
-(PR) for the implementation. The issue, not the PR, should be tagged and
-milestoned so a given change shows up only once in the various views.
+(PR) for the implementation.
+
+The issue, not the PR, should be tagged and milestoned so a given change shows
+up only once in the various views.
 
 If consensus is obtained through other means (e.g., in-person discussion),
 then open a PR directly. In this case, the PR should be tagged and milestoned,
@@ -105,22 +107,24 @@
 log). Instead, use "addresses", and we'll edit the keywords into the commit
 message(s) at merge time if needed.
 
-**PR review procedure.** When your PR is ready for review ?????which may or may
-not be when you want it considered for merging ??? do one or both of:
+**PR review procedure.** When your draft PR is ready for review ?????which may 
or
+may not be when you want it considered for merging! ??? do one or both of:
 
 * Request review from the person(s) you want to look at it. If you think it
   may be ready for merge, that should include the project lead. The purpose of
-  requsting review is so the person is notified you need their help.
+  requesting review is so the person is notified you need their help.
 
 * If you think it may be ready to merge (even if you're not sure), then also
-  tag the PR :code:`ready to merge`. The purpose of this is so the project
-  lead can see which PRs are ready to consider for merging. If the project
-  lead decides it's ready, they will merge; otherwise, they'll untag.
+  mark the PR "ready to review". The purpose of this is so the project lead
+  can see which PRs are ready to consider for merging (green icon) and which
+  are not (gray icon). If the project lead decides it's ready, they will
+  merge; otherwise, they'll change it back to draft.
 
 In both cases, the person from whom you requested review now owns the branch,
 and you should stop work on it unless and until you get it back.
 
-Do not hesitate to pester your reviewer if you haven't heard back promptly.
+Do not hesitate to pester your reviewer if you haven't heard back promptly,
+say within 24 hours.
 
 *Special case 1:* Often, the review consists of code changes, and the reviewer
 will want you to assess those changes. GitHub doesn't let you request review
@@ -280,12 +284,6 @@
   error. Often (or usually) there is a documentation or usability bug that
   caused the "user error".*
 
-:code:`ready to merge`
-  PRs only. Adding this tag speculates that the PR is complete and requests it
-  be considered for merging to master. If the project lead requests changes,
-  they'll remove the tag. Re-add it when you're ready to try again. Lead
-  removes tag after merging.
-
 :code:`wontfix`
   We are not going to do this, and we won't merge PRs. Close issue after
   tagging, though sometimes you'll want to leave a few days to allow for
@@ -477,7 +475,7 @@
 ------------
 
   * charliecloud
-  * Python 3.4+
+  * Python 3.6+
   * Either:
 
     * the provided example :code:`centos7` or :code:`centos8` image
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/examples/spark/slurm.sh 
new/charliecloud-0.23/examples/spark/slurm.sh
--- old/charliecloud-0.22/examples/spark/slurm.sh       2020-04-15 
21:31:09.000000000 +0200
+++ new/charliecloud-0.23/examples/spark/slurm.sh       2021-03-16 
18:10:00.000000000 +0100
@@ -59,6 +59,7 @@
 SPARK_WORKER_DIR=/tmp/spark
 SPARK_LOCAL_IP=127.0.0.1
 SPARK_MASTER_HOST=${master_ip}
+JAVA_HOME=/usr/lib/jvm/default-java/
 EOF
 mysecret=$(cat /dev/urandom | tr -dc '0-9a-f' | head -c 48)
 cat <<EOF > "${conf}/spark-defaults.sh"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/examples/spark/test.bats 
new/charliecloud-0.23/examples/spark/test.bats
--- old/charliecloud-0.22/examples/spark/test.bats      2020-11-17 
21:35:54.000000000 +0100
+++ new/charliecloud-0.23/examples/spark/test.bats      2021-03-16 
18:10:00.000000000 +0100
@@ -31,22 +31,21 @@
     spark_config=$spark_dir
     spark_log=/tmp/sparklog
     if [[ $ch_multinode ]]; then
-        # Use the last non-loopback IP address. This is a barely educated
-        # guess and shouldn't be relied on for real code, but hopefully it
-        # works for testing.
-        master_ip=$(  ip -o -f inet addr show \
-                    | grep -F 'scope global' \
-                    | tail -1 \
-                    | sed -r 's/^.+inet ([0-9.]+).+/\1/')
+        # We use hostname to determine the interface to use for this test,
+        # avoiding complicated logic determining which interface is the HSN.
+        # In many environments this likely results in the tests running over
+        # the slower management interface, which is fine for testing, but
+        # should be avoided for large scale runs.
+        master_host="$(hostname)"
         # Start Spark workers using pdsh. We would really prefer to do this
         # using srun, but that doesn't work; see issue #230.
         command -v pdsh >/dev/null 2>&1 || pedantic_fail "pdsh not in path"
         pernode="pdsh -R ssh -w ${SLURM_NODELIST} -- PATH='${PATH}'"
     else
-        master_ip=127.0.0.1
+        master_host=localhost
         pernode=
     fi
-    master_url="spark://${master_ip}:7077"
+    master_url="spark://${master_host}:7077"
     master_log="${spark_log}/*master.Master*.out"
 }
 
@@ -58,12 +57,15 @@
     [[ $output = 'u=rwx,g=,o=' ]]
     # create config
     $ch_mpirun_node mkdir -p "$spark_config"
+    # We set JAVA_HOME in the spark environment file as this appears to be the
+    # idiomatic method for ensuring spark finds the java install.
     tee <<EOF > "${spark_config}/spark-env.sh"
 SPARK_LOCAL_DIRS=/tmp/spark
 SPARK_LOG_DIR=$spark_log
 SPARK_WORKER_DIR=/tmp/spark
 SPARK_LOCAL_IP=127.0.0.1
-SPARK_MASTER_HOST=${master_ip}
+SPARK_MASTER_HOST=${master_host}
+JAVA_HOME=/usr/lib/jvm/default-java/
 EOF
     my_secret=$(cat /dev/urandom | tr -dc '0-9a-f' | head -c 48)
     tee <<EOF > "${spark_config}/spark-defaults.conf"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/lib/base.sh 
new/charliecloud-0.23/lib/base.sh
--- old/charliecloud-0.22/lib/base.sh   2021-01-27 18:27:08.000000000 +0100
+++ new/charliecloud-0.23/lib/base.sh   2021-03-16 18:10:00.000000000 +0100
@@ -22,7 +22,7 @@
         fi
     fi
     case $CH_BUILDER in
-        buildah|buildah-runc|buildah-setuid|ch-image|ch-grow|docker|none)
+        buildah|buildah-runc|buildah-setuid|ch-image|docker|none)
             ;;
         *)
             echo "unknown builder: $CH_BUILDER" 1>&2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/lib/build.py 
new/charliecloud-0.23/lib/build.py
--- old/charliecloud-0.22/lib/build.py  2021-02-05 21:09:13.000000000 +0100
+++ new/charliecloud-0.23/lib/build.py  2021-04-06 01:51:43.000000000 +0200
@@ -590,7 +590,7 @@
    def __init__(self, *args):
       super().__init__(*args)
       self.key = ch.tree_terminal(self.tree, "WORD")
-      value = ch.tree_terminal(self.tree, "LINE")
+      value = ch.tree_terminals_cat(self.tree, "LINE_CHUNK")
       if (not value.startswith('"')):
          value = '"' + value + '"'
       self.value = unescape(value)
@@ -651,8 +651,8 @@
                                         cli.force, cli.no_force_detect)
 
    def str_(self):
-      alias = "AS %s" % self.alias if self.alias else ""
-      return "%s %s" % (self.base_ref, alias)
+      alias = " AS %s" % self.alias if self.alias else ""
+      return "%s%s" % (self.base_ref, alias)
 
 
 class Run(Instruction):
@@ -690,19 +690,22 @@
 
 class I_run_shell(Run):
 
+   # Note re. line continuations and whitespace: Whitespace before the
+   # backslash is passed verbatim to the shell, while the newline and any
+   # whitespace between the newline and baskslash are deleted.
+
    def __init__(self, *args):
       super().__init__(*args)
-      # FIXME: Can't figure out how to remove continuations at parse time.
-      cmd = ch.tree_terminal(self.tree, "LINE").replace("\\\n", "")
+      cmd = ch.tree_terminals_cat(self.tree, "LINE_CHUNK")
       self.cmd = env.shell + [cmd]
 
 class I_shell(Instruction):
- 
+
    def __init__(self, *args):
       super().__init__(*args)
       self.shell = [variables_sub(unescape(i), env.env_build)
                     for i in ch.tree_terminals(self.tree, "STRING_QUOTED")]
-  
+
    def str_(self):
       return str(self.shell)
 
@@ -713,7 +716,7 @@
 
    def __init__(self, *args):
       super().__init__(*args)
-      self.path = variables_sub(ch.tree_terminal(self.tree, "LINE"),
+      self.path = variables_sub(ch.tree_terminals_cat(self.tree, "LINE_CHUNK"),
                                 env.env_build)
 
    def str_(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/lib/charliecloud.py 
new/charliecloud-0.23/lib/charliecloud.py
--- old/charliecloud-0.22/lib/charliecloud.py   2021-02-05 21:09:13.000000000 
+0100
+++ new/charliecloud-0.23/lib/charliecloud.py   2021-04-09 21:49:04.000000000 
+0200
@@ -104,7 +104,7 @@
 
 ?instruction: _WS? ( arg | copy | env | from_ | run | shell | workdir | 
uns_forever | uns_yet )
 
-directive.2: _WS? "#" _WS? DIRECTIVE_NAME "=" LINE _NEWLINES
+directive.2: _WS? "#" _WS? DIRECTIVE_NAME "=" _line _NEWLINES
 DIRECTIVE_NAME: ( "escape" | "syntax" )
 comment: _WS? _COMMENT_BODY _NEWLINES
 _COMMENT_BODY: /#[^\n]*/
@@ -118,7 +118,7 @@
 arg_equals: WORD "=" ( WORD | STRING_QUOTED )
 
 env: "ENV"i _WS ( env_space | env_equalses ) _NEWLINES
-env_space: WORD _WS LINE
+env_space: WORD _WS _line
 env_equalses: env_equals ( _WS env_equals )*
 env_equals: WORD "=" ( WORD | STRING_QUOTED )
 
@@ -127,16 +127,16 @@
 
 run: "RUN"i _WS ( run_exec | run_shell ) _NEWLINES
 run_exec.2: _string_list
-run_shell: LINE
+run_shell: _line
 
 shell: "SHELL"i _WS _string_list _NEWLINES
 
-workdir: "WORKDIR"i _WS LINE _NEWLINES
+workdir: "WORKDIR"i _WS _line _NEWLINES
 
-uns_forever: UNS_FOREVER _WS LINE _NEWLINES
+uns_forever: UNS_FOREVER _WS _line _NEWLINES
 UNS_FOREVER: ( "EXPOSE"i | "HEALTHCHECK"i | "MAINTAINER"i | "STOPSIGNAL"i | 
"USER"i | "VOLUME"i )
 
-uns_yet: UNS_YET _WS LINE _NEWLINES
+uns_yet: UNS_YET _WS _line _NEWLINES
 UNS_YET: ( "ADD"i | "CMD"i | "ENTRYPOINT"i | "LABEL"i | "ONBUILD"i )
 
 /// Common ///
@@ -145,15 +145,29 @@
 OPTION_KEY: /[a-z]+/
 OPTION_VALUE: /[^ \t\n]+/
 
+// Matching lines in the face of continuations is surprisingly hairy. Notes:
+//
+//   1. The underscore prefix means the rule is always inlined (i.e., removed
+//      and children become children of its parent).
+//
+//   2. LINE_CHUNK must not match any characters that _LINE_CONTINUE does.
+//
+//   3. This is very sensitive to the location of repetition. Moving the plus
+//      either to the entire regex (i.e., ???/(...)+/???) or outside the regex
+//      (i.e., ???/.../+???) gave parse errors.
+//
+_line: ( _LINE_CONTINUE | LINE_CHUNK )+
+LINE_CHUNK: /[^\\\n]+|(\\(?![ \t]+\n))+/
+
 HEX_STRING: /[0-9A-Fa-f]+/
-LINE: ( _LINE_CONTINUE | /[^\n]/ )+
 WORD: /[^ \t\n=]/+
 
 _string_list: "[" _WS? STRING_QUOTED ( "," _WS? STRING_QUOTED )* _WS? "]"
 
-_NEWLINES: _WS? "\n"+
-_WS: /[ \t]|\\\n/+
-_LINE_CONTINUE: "\\\n"
+_WSH: /[ \t]/+                   // sequence of horizontal whitespace
+_LINE_CONTINUE: "\\" _WSH? "\n"  // line continuation
+_WS: ( _WSH | _LINE_CONTINUE )+  // horizontal whitespace w/ line continuations
+_NEWLINES: ( _WS? "\n" )+        // sequence of newlines
 
 %import common.ESCAPED_STRING -> STRING_QUOTED
 """
@@ -667,7 +681,10 @@
       try:
          tree = class_.parser.parse(s)
       except lark.exceptions.UnexpectedInput as x:
-         FATAL("image ref syntax, char %d: %s" % (x.column, s))
+         if (x.column == -1):
+            FATAL("image ref syntax, at end: %s" % s)
+         else:
+            FATAL("image ref syntax, char %d: %s" % (x.column, s))
       except lark.exceptions.UnexpectedEOF as x:
          # We get UnexpectedEOF because of Lark issue #237. This exception
          # doesn't have a column location.
@@ -974,11 +991,19 @@
    def blob_exists_p(self, digest):
       """Return true if a blob with digest (hex string) exists in the
          remote repository, false otherwise."""
+      # Gotchas:
+      #
+      # 1. HTTP 401 means both unauthorized *or* not found, I assume to avoid
+      #    information leakage about the presence of stuff one isn't allowed
+      #    to see. By the time it gets here, we should be authenticated, so
+      #    interpret it as not found.
+      #
+      # 2. Sometimes we get 301 Moved Permanently. It doesn't bubble up to
+      #    here because requests.request() follows redirects. However,
+      #    requests.head() does not follow redirects, and it seems like a
+      #    weird status, so I worry there is a gotcha I haven't figured out.
       url = self._url_of("blobs", "sha256:%s" % digest)
-      # FIXME: Sometimes we get 301 Moved Permanently. requests.head() doesn't
-      # follow redirects (but requests.request("HEAD", ...) does), and I
-      # wasn't able to figure out why. So possibly there is some gotcha here.
-      res = self.request("HEAD", url, {200,404})
+      res = self.request("HEAD", url, {200,401,404})
       return (res.status_code == 200)
 
    def blob_to_file(self, digest, path):
@@ -1062,7 +1087,6 @@
          Use current session if there is one, or start a new one if not. If
          authentication fails (or isn't initialized), then authenticate and
          re-try the request."""
-      VERBOSE("%s: %s" % (method, url))
       self.session_init_maybe()
       VERBOSE("auth: %s" % self.auth)
       res = self.request_raw(method, url, statuses | {401}, **kwargs)
@@ -1087,7 +1111,7 @@
          Session must already exist. If auth arg given, use it; otherwise, use
          object's stored authentication if initialized; otherwise, use no
          authentication."""
-      DEBUG("%s: %s" % (method, url))
+      VERBOSE("%s: %s" % (method, url))
       if (auth is None):
          auth = self.auth
       try:
@@ -1152,23 +1176,31 @@
 
    @staticmethod
    def root_env():
+      if ("CH_GROW_STORAGE" in os.environ):
+         # Avoid surprises if user still has $CH_GROW_STORAGE set (see #906).
+         FATAL("$CH_GROW_STORAGE no longer supported; use $CH_IMAGE_STORAGE")
       try:
          return os.environ["CH_IMAGE_STORAGE"]
       except KeyError:
-         try:
-            p = os.environ["CH_GROW_STORAGE"]
-            WARNING("$CH_GROW_STORAGE is deprecated in favor of 
$CH_IMAGE_STORAGE")
-            WARNING("the old name will be removed in Charliecloud version 
0.23")
-            return p
-         except KeyError:
-            return None
+         return None
 
    def manifest_for_download(self, image_ref):
       return self.download_cache // ("%s.manifest.json" % image_ref.for_path)
 
+   def reset(self):
+      if (self.valid_p()):
+         rmtree(self.root)
+      else:
+         FATAL("%s not a builder storage" % (self.root));
+
    def unpack(self, image_ref):
       return self.unpack_base // image_ref.for_path
 
+   def valid_p(self):
+      "Return True if storage present and seems valid, False otherwise."
+      return (os.path.isdir(self.unpack_base) and
+              os.path.isdir(self.download_cache))
+
 
 class TarFile(tarfile.TarFile):
 
@@ -1545,12 +1577,17 @@
    return None
 
 def tree_terminals(tree, tname):
-   """Yield values of all child terminals of type type_, or empty list if none
+   """Yield values of all child terminals named tname, or empty list if none
       found."""
    for j in tree.children:
       if (isinstance(j, lark.lexer.Token) and j.type == tname):
          yield j.value
 
+def tree_terminals_cat(tree, tname):
+   """Return the concatenated values of all child terminals named tname as a
+      string, with no delimiters. If none, return the empty string."""
+   return "".join(tree_terminals(tree, tname))
+
 def unlink(path, *args, **kwargs):
    "Error-checking wrapper for os.unlink()."
    ossafe(os.unlink, "can't unlink: %s" % path, path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/lib/misc.py 
new/charliecloud-0.23/lib/misc.py
--- old/charliecloud-0.22/lib/misc.py   2021-02-04 00:15:39.000000000 +0100
+++ new/charliecloud-0.23/lib/misc.py   2021-04-09 21:49:04.000000000 +0200
@@ -45,5 +45,11 @@
    for img in sorted(imgs):
       print(ch.Image_Ref(img))
 
+def python_path(cli):
+   print(sys.executable)
+
+def reset(cli):
+   ch.storage.reset()
+
 def storage_path(cli):
    print(ch.storage.root)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/packaging/vagrant/Vagrantfile 
new/charliecloud-0.23/packaging/vagrant/Vagrantfile
--- old/charliecloud-0.22/packaging/vagrant/Vagrantfile 2020-12-10 
00:06:07.000000000 +0100
+++ new/charliecloud-0.23/packaging/vagrant/Vagrantfile 2021-03-01 
22:54:16.000000000 +0100
@@ -196,7 +196,7 @@
   EOF
 
   # Install Buildah.
-  c.vm.provision "buildah", type: "shell", privileged: false,
+  c.vm.provision "buildah", type: "shell", run: "never", privileged: false,
                  inline: <<-EOF
     set -e
     cd /usr/local/src
@@ -328,7 +328,7 @@
         user=vagrant
     fi
     sudo -iu $user -- sh -c "ch-test --pedantic yes -b docker all"
-    sudo -iu $user -- sh -c "ch-test --pedantic yes -b buildah all"
+    #sudo -iu $user -- sh -c "ch-test --pedantic yes -b buildah all"
     sudo -iu $user -- sh -c "ch-test --pedantic yes -b ch-image all"
   EOF
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/test/build/40_pull.bats 
new/charliecloud-0.23/test/build/40_pull.bats
--- old/charliecloud-0.22/test/build/40_pull.bats       2021-02-05 
21:09:13.000000000 +0100
+++ new/charliecloud-0.23/test/build/40_pull.bats       2021-03-13 
01:13:51.000000000 +0100
@@ -285,6 +285,8 @@
 
     # nVidia NGC: https://ngc.nvidia.com
     # FIXME: 96 MiB unpacked; also kind of slow
+    # FIXME: Can't pull this image with LC_ALL=C (issue #970).
+    LC_ALL=en_US.utf-8 \
     ch-image pull nvcr.io/hpc/foldingathome/fah-gpu:7.6.21
 
     # Things not here (yet?):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/test/build/50_ch-image.bats 
new/charliecloud-0.23/test/build/50_ch-image.bats
--- old/charliecloud-0.22/test/build/50_ch-image.bats   2021-02-05 
21:09:13.000000000 +0100
+++ new/charliecloud-0.23/test/build/50_ch-image.bats   2021-04-09 
21:49:04.000000000 +0200
@@ -63,6 +63,42 @@
     [[ $output = *"00_tiny"* ]]
 }
 
+@test 'ch-image reset' {
+   export CH_IMAGE_STORAGE="$BATS_TMPDIR"/reset
+
+   # Ensure our test storage dir doesn't exist yet.
+   [[ ! -e $CH_IMAGE_STORAGE ]]
+
+   # Put an image innit.
+   ch-image pull alpine:3.9
+   ls "$CH_IMAGE_STORAGE"
+
+   # List images; should be only the one we just pulled.
+   run ch-image list
+   echo "$output"
+   [[ $status -eq 0 ]]
+   [[ $output = "alpine:3.9" ]]
+
+   # Reset.
+   ch-image reset
+
+   # Image storage directory should be gone.
+   ls "$CH_IMAGE_STORAGE" || true
+   [[ ! -e $CH_IMAGE_STORAGE ]]
+
+   # List images; should error with not found.
+   run ch-image list
+   echo "$output"
+   [[ $status -eq 1 ]]
+   [[ $output = *"$CH_IMAGE_STORAGE/img: No such file or directory"* ]]
+
+   # Reset again; should error.
+   run ch-image reset
+   echo "$output"
+   [[ $status -eq 1 ]]
+   [[ $output = *"$CH_IMAGE_STORAGE not a builder storage"* ]]
+}
+
 @test 'ch-image storage-path' {
     run ch-image storage-path
     echo "$output"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/charliecloud-0.22/test/build/50_dockerfile.bats 
new/charliecloud-0.23/test/build/50_dockerfile.bats
--- old/charliecloud-0.22/test/build/50_dockerfile.bats 2021-02-05 
21:09:13.000000000 +0100
+++ new/charliecloud-0.23/test/build/50_dockerfile.bats 2021-04-06 
01:51:43.000000000 +0200
@@ -1,5 +1,6 @@
 load ../common
 
+
 @test 'Dockerfile: syntax quirks' {
     # These should all yield an output image, but we don't actually care about
     # it, so re-use the same one.
@@ -40,9 +41,119 @@
   # multiple before
        # tab before
 EOF
+
     echo "$output"
     [[ $status -eq 0 ]]
     [[ $(echo "$output" | grep -Fc 'comment') -eq 6 ]]
+
+    # Whitespace and newlines (turn on whitespace highlighting in your editor):
+    run ch-image build -t syntax-quirks -f - . <<'EOF'
+FROM 00_tiny
+
+# trailing whitespace: shell sees it verbatim
+RUN true 
+
+# whitespace-only line: ignored
+ 
+# two in a row
+ 
+ 
+
+# line continuation, no whitespace: shell sees one word
+RUN echo test1\
+a
+# two in a row
+RUN echo test1\
+b\
+c
+
+# whitespace before line continuation: shell sees whitespace verbatim
+RUN echo test2  \
+a
+# two in a row
+RUN echo test2  \
+b  \
+c
+
+# whitespace after line continuation: shell sees one word
+RUN echo test3\  
+a
+# two in a row
+RUN echo test3\  
+b\  
+c
+
+# whitespace before & after line continuation: shell sees before only
+RUN echo test4   \  
+a
+# two in a row
+RUN echo test4   \  
+b   \  
+c
+
+# whitespace on continued line: shell sees continued line's whitespace
+RUN echo test5\
+  a
+# two in a row
+RUN echo test5\
+  b\
+  c
+
+# whitespace-only continued line: shell sees whitespace verbatim
+RUN echo test6\
+  \
+a
+# two in a row
+RUN echo test6\
+  \
+  \
+b
+
+# backslash that is not a continuation: shell sees it verbatim
+RUN echo test\ 7\
+a
+# two in a row
+RUN echo test\ 7\ \
+b
+EOF
+    echo "$output"
+    [[ $status -eq 0 ]]
+    output_expected=$(cat <<'EOF'
+warning: not yet supported, ignored: issue #777: .dockerignore file
+  1 FROM 00_tiny
+  4 RUN ['/bin/sh', '-c', 'true ']
+ 13 RUN ['/bin/sh', '-c', 'echo test1a']
+test1a
+ 16 RUN ['/bin/sh', '-c', 'echo test1bc']
+test1bc
+ 21 RUN ['/bin/sh', '-c', 'echo test2  a']
+test2 a
+ 24 RUN ['/bin/sh', '-c', 'echo test2  b  c']
+test2 b c
+ 29 RUN ['/bin/sh', '-c', 'echo test3a']
+test3a
+ 32 RUN ['/bin/sh', '-c', 'echo test3bc']
+test3bc
+ 37 RUN ['/bin/sh', '-c', 'echo test4   a']
+test4 a
+ 40 RUN ['/bin/sh', '-c', 'echo test4   b   c']
+test4 b c
+ 45 RUN ['/bin/sh', '-c', 'echo test5  a']
+test5 a
+ 48 RUN ['/bin/sh', '-c', 'echo test5  b  c']
+test5 b c
+ 53 RUN ['/bin/sh', '-c', 'echo test6  a']
+test6 a
+ 57 RUN ['/bin/sh', '-c', 'echo test6    b']
+test6 b
+ 63 RUN ['/bin/sh', '-c', 'echo test\\ 7a']
+test 7a
+ 66 RUN ['/bin/sh', '-c', 'echo test\\ 7\\ b']
+test 7 b
+grown in 16 instructions: syntax-quirks
+EOF
+)
+    diff -u <(echo "$output_expected") <(echo "$output")
 }
 
 
@@ -61,7 +172,6 @@
     [[ $output = *"can't parse: -:2,1"* ]]
     # internal blabber
     [[ $output = *"No terminal defined for 'W' at line 2 col 1"* ]]
-    [[ $output = *'Expecting: {'* ]]
 
     # Bad long option.
     run ch-image build -t foo -f - . <<'EOF'

Reply via email to