diff --git a/1984/1984.tar.bz2 b/1984/1984.tar.bz2 index 2219958d4..c799cd568 100644 Binary files a/1984/1984.tar.bz2 and b/1984/1984.tar.bz2 differ diff --git a/1985/1985.tar.bz2 b/1985/1985.tar.bz2 index 36232dfcc..5c85c0014 100644 Binary files a/1985/1985.tar.bz2 and b/1985/1985.tar.bz2 differ diff --git a/1986/1986.tar.bz2 b/1986/1986.tar.bz2 index f34ea25d2..f584292a3 100644 Binary files a/1986/1986.tar.bz2 and b/1986/1986.tar.bz2 differ diff --git a/1987/1987.tar.bz2 b/1987/1987.tar.bz2 index 9150522e6..73a7552c1 100644 Binary files a/1987/1987.tar.bz2 and b/1987/1987.tar.bz2 differ diff --git a/1988/1988.tar.bz2 b/1988/1988.tar.bz2 index a77f18b03..74a3a4c19 100644 Binary files a/1988/1988.tar.bz2 and b/1988/1988.tar.bz2 differ diff --git a/1989/1989.tar.bz2 b/1989/1989.tar.bz2 index d5d046584..27c5d7781 100644 Binary files a/1989/1989.tar.bz2 and b/1989/1989.tar.bz2 differ diff --git a/1990/1990.tar.bz2 b/1990/1990.tar.bz2 index 420cf08dd..b56b63c05 100644 Binary files a/1990/1990.tar.bz2 and b/1990/1990.tar.bz2 differ diff --git a/1991/1991.tar.bz2 b/1991/1991.tar.bz2 index 097a93534..9f1d56bdb 100644 Binary files a/1991/1991.tar.bz2 and b/1991/1991.tar.bz2 differ diff --git a/1992/1992.tar.bz2 b/1992/1992.tar.bz2 index 8e444d0d3..86afeff22 100644 Binary files a/1992/1992.tar.bz2 and b/1992/1992.tar.bz2 differ diff --git a/1992/gson/1992_gson.tar.bz2 b/1992/gson/1992_gson.tar.bz2 index e19f22e53..039f93904 100644 Binary files a/1992/gson/1992_gson.tar.bz2 and b/1992/gson/1992_gson.tar.bz2 differ diff --git a/1993/1993.tar.bz2 b/1993/1993.tar.bz2 index fc53377a7..98791ce24 100644 Binary files a/1993/1993.tar.bz2 and b/1993/1993.tar.bz2 differ diff --git a/1994/1994.tar.bz2 b/1994/1994.tar.bz2 index 533de62c1..6083d6605 100644 Binary files a/1994/1994.tar.bz2 and b/1994/1994.tar.bz2 differ diff --git a/1995/1995.tar.bz2 b/1995/1995.tar.bz2 index e18f57766..861966736 100644 Binary files a/1995/1995.tar.bz2 and b/1995/1995.tar.bz2 differ diff --git a/1996/1996.tar.bz2 b/1996/1996.tar.bz2 index 23ded8044..ce70d5c6d 100644 Binary files a/1996/1996.tar.bz2 and b/1996/1996.tar.bz2 differ diff --git a/1998/1998.tar.bz2 b/1998/1998.tar.bz2 index 32d53ec4b..3fd504ce4 100644 Binary files a/1998/1998.tar.bz2 and b/1998/1998.tar.bz2 differ diff --git a/2000/2000.tar.bz2 b/2000/2000.tar.bz2 index b17f284e1..b3f840641 100644 Binary files a/2000/2000.tar.bz2 and b/2000/2000.tar.bz2 differ diff --git a/2001/2001.tar.bz2 b/2001/2001.tar.bz2 index dab5f9c3e..b09067045 100644 Binary files a/2001/2001.tar.bz2 and b/2001/2001.tar.bz2 differ diff --git a/2004/2004.tar.bz2 b/2004/2004.tar.bz2 index ab7b9146d..a2c14b7cb 100644 Binary files a/2004/2004.tar.bz2 and b/2004/2004.tar.bz2 differ diff --git a/2005/2005.tar.bz2 b/2005/2005.tar.bz2 index aabeebe72..e1dbc531b 100644 Binary files a/2005/2005.tar.bz2 and b/2005/2005.tar.bz2 differ diff --git a/2006/2006.tar.bz2 b/2006/2006.tar.bz2 index d74029ac1..2bd27c514 100644 Binary files a/2006/2006.tar.bz2 and b/2006/2006.tar.bz2 differ diff --git a/2011/2011.tar.bz2 b/2011/2011.tar.bz2 index 994462856..a89abbca8 100644 Binary files a/2011/2011.tar.bz2 and b/2011/2011.tar.bz2 differ diff --git a/2011/akari/2011_akari.tar.bz2 b/2011/akari/2011_akari.tar.bz2 index 9f9185df5..a508d77a8 100644 Binary files a/2011/akari/2011_akari.tar.bz2 and b/2011/akari/2011_akari.tar.bz2 differ diff --git a/2011/blakely/2011_blakely.tar.bz2 b/2011/blakely/2011_blakely.tar.bz2 index f2425aed6..d86166c07 100644 Binary files a/2011/blakely/2011_blakely.tar.bz2 and b/2011/blakely/2011_blakely.tar.bz2 differ diff --git a/2011/borsanyi/2011_borsanyi.tar.bz2 b/2011/borsanyi/2011_borsanyi.tar.bz2 index 71f61f9c5..e8186b282 100644 Binary files a/2011/borsanyi/2011_borsanyi.tar.bz2 and b/2011/borsanyi/2011_borsanyi.tar.bz2 differ diff --git a/2011/hamaji/2011_hamaji.tar.bz2 b/2011/hamaji/2011_hamaji.tar.bz2 index b175325c2..43f3419fe 100644 Binary files a/2011/hamaji/2011_hamaji.tar.bz2 and b/2011/hamaji/2011_hamaji.tar.bz2 differ diff --git a/2011/hou/2011_hou.tar.bz2 b/2011/hou/2011_hou.tar.bz2 index 0e3d8ffb2..0cf4d9abc 100644 Binary files a/2011/hou/2011_hou.tar.bz2 and b/2011/hou/2011_hou.tar.bz2 differ diff --git a/2011/konno/2011_konno.tar.bz2 b/2011/konno/2011_konno.tar.bz2 index 2688d7108..f9d68b481 100644 Binary files a/2011/konno/2011_konno.tar.bz2 and b/2011/konno/2011_konno.tar.bz2 differ diff --git a/2011/zucker/2011_zucker.tar.bz2 b/2011/zucker/2011_zucker.tar.bz2 index 1a7b4c601..5b73e76e5 100644 Binary files a/2011/zucker/2011_zucker.tar.bz2 and b/2011/zucker/2011_zucker.tar.bz2 differ diff --git a/2012/2012.tar.bz2 b/2012/2012.tar.bz2 index f2d81db31..9d5d03326 100644 Binary files a/2012/2012.tar.bz2 and b/2012/2012.tar.bz2 differ diff --git a/2012/zeitak/2012_zeitak.tar.bz2 b/2012/zeitak/2012_zeitak.tar.bz2 index 5f444517a..479c9fecc 100644 Binary files a/2012/zeitak/2012_zeitak.tar.bz2 and b/2012/zeitak/2012_zeitak.tar.bz2 differ diff --git a/2013/2013.tar.bz2 b/2013/2013.tar.bz2 index 60fa19492..4cfdd10a9 100644 Binary files a/2013/2013.tar.bz2 and b/2013/2013.tar.bz2 differ diff --git a/2014/2014.tar.bz2 b/2014/2014.tar.bz2 index dfa5dc3e6..4f62de89e 100644 Binary files a/2014/2014.tar.bz2 and b/2014/2014.tar.bz2 differ diff --git a/2015/2015.tar.bz2 b/2015/2015.tar.bz2 index ff3d8fd32..03aa249a3 100644 Binary files a/2015/2015.tar.bz2 and b/2015/2015.tar.bz2 differ diff --git a/2018/2018.tar.bz2 b/2018/2018.tar.bz2 index 0e168a72e..430d689a3 100644 Binary files a/2018/2018.tar.bz2 and b/2018/2018.tar.bz2 differ diff --git a/2019/2019.tar.bz2 b/2019/2019.tar.bz2 index a44e76e94..d9a51a1e9 100644 Binary files a/2019/2019.tar.bz2 and b/2019/2019.tar.bz2 differ diff --git a/2020/2020.tar.bz2 b/2020/2020.tar.bz2 index ac8eb0c45..26f0cb7c3 100644 Binary files a/2020/2020.tar.bz2 and b/2020/2020.tar.bz2 differ diff --git a/Makefile b/Makefile index 07b8eb452..a5f85d922 100644 --- a/Makefile +++ b/Makefile @@ -54,9 +54,10 @@ GEN_LOCATION= bin/gen-location.sh GEN_YEARS= bin/gen-years.sh GEN_YEAR_INDEX= bin/gen-year-index.sh CHK_ENTRY= bin/chk-entry.sh -TAR_ENTRY= bin/tar-entry.sh README2INDEX= bin/readme2index.sh QUICK_README2INDEX= bin/quick-readme2index.sh +TAR_ENTRY= bin/tar-entry.sh +TAR_YEAR= bin/tar-year.sh ############# @@ -235,8 +236,9 @@ indent.c: # XXX - The rules in this section are undergoing development and change. # They might not even work (right now). :-) -.PHONY: help verify_entry_files genpath gen_authors gen_location gen_years \ - entry_index quick_entry_index form_entry_tarball gen_year_index quick_www www +.PHONY: help genpath genfilelist verify_entry_files gen_authors gen_location gen_years \ + entry_index quick_entry_index form_entry_tarball form_year_tarball \ + gen_year_index quick_www www # Suggest rules in this section # @@ -245,8 +247,9 @@ indent.c: # reminder to those who understand it. For all else, there is "RTFS". :-) # help: - @echo make verify_entry_files @echo make genpath + @echo make genfilelist + @echo make verify_entry_files @echo make gen_authors @echo make gen_location @echo make gen_years @@ -254,18 +257,14 @@ help: @echo make gen_year_index @echo make quick_entry_index @echo make form_entry_tarball + @echo make form_year_tarball @echo make quick_www @echo make www -# check to be sure all files in all entries exist -# -verify_entry_files: ${ALL_RUN} ${CHK_ENTRY} - @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' - ${ALL_RUN} -v 3 ${CHK_ENTRY} - @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' - # form the top level .top, YYYY level .year and winner level .path files # +# IMPORTANT: This file assumes that make clobber was previously done. +# genpath: @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' @${RM} -f .tmp.genpath @@ -284,6 +283,33 @@ genpath: fi @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' +# generate YYYY level .filelist +# +# IMPORTANT: This file assumes that make clobber was previously done. +# +genfilelist: + @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' + @-for i in ${YEARS}; do \ + rm -f "$$i/.genfilelist.tmp"; \ + find "$$i" -mindepth 1 -maxdepth 1 -type f ! -path "$$i/.genfilelist.tmp" | sort -d -u > "$$i/.genfilelist.tmp"; \ + if ${CMP} -s "$$i/.genfilelist.tmp" "$$i/.filelist"; then \ + ${RM} -f "$$i/.genfilelist.tmp"; \ + echo "$$i/.filelist already up to date"; \ + else \ + ${MV} -f "$$i/.genfilelist.tmp" "$$i/.filelist"; \ + ${CHMOD} 0444 "$$i/.filelist"; \ + echo "updated $$i/.filelist"; \ + fi; \ + done + @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' + +# check to be sure all files in all entries exist +# +verify_entry_files: ${ALL_RUN} ${CHK_ENTRY} + @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' + ${ALL_RUN} -v 3 ${CHK_ENTRY} + @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' + # generate the top level authors.html page using the # ${GEN_AUTHORS} tool (bin/gen-authors.sh). # @@ -347,6 +373,17 @@ form_entry_tarball: ${ALL_RUN} ${TAR_ENTRY} ${ALL_RUN} -v 3 ${TAR_ENTRY} -v 1 -W @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' +# form all IOCCC year level compressed tarballs +# +# XXX - We also use -W because some entry files don't yet exist - XXX +# XXX - Remove -W when make verify_entry_files runs without err - XXX +# XXX - We do not yet form year level and the top level tarball - XXX +# +form_year_tarball: ${ALL_YEARS} ${TAR_YEAR} + @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' + ${ALL_YEARS} -v 3 ${TAR_YEAR} -v 1 -W + @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' + # do work to build HTML content for the web site # # This rule uses quick_entry_index, not slow_entry_index, so @@ -357,6 +394,9 @@ form_entry_tarball: ${ALL_RUN} ${TAR_ENTRY} # quick_www: @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' + ${MAKE} clobber + ${MAKE} genpath + ${MAKE} genfilelist -${MAKE} verify_entry_files # remove - when all files exist ${MAKE} gen_authors ${MAKE} gen_location @@ -364,6 +404,7 @@ quick_www: ${MAKE} gen_year_index ${MAKE} quick_entry_index ${MAKE} form_entry_tarball + ${MAKE} form_year_tarball @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' # do everything needed to build HTML content for the web site @@ -372,6 +413,9 @@ quick_www: # www: @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-=' + ${MAKE} clobber + ${MAKE} genpath + ${MAKE} genfilelist -${MAKE} verify_entry_files # remove - when all files exist ${MAKE} gen_authors ${MAKE} gen_location @@ -379,6 +423,7 @@ www: ${MAKE} gen_year_index ${MAKE} entry_index ${MAKE} form_entry_tarball + ${MAKE} form_year_tarball @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-=' diff --git a/bin/README.md b/bin/README.md index c5dd6ea7c..c1dc1e483 100644 --- a/bin/README.md +++ b/bin/README.md @@ -260,6 +260,23 @@ bin/all-run.sh -v 3 bin/tar-entry.sh -v 1 -W ``` +## [tar-year.sh](tar-year.sh) + +Form a compress tarball for an IOCCC year. + +Usage: + +```sh +bin/tar-year.sh -v 1 YYYY +``` + +Suggested usage: + +```sh +bin/all-years.sh -v 3 bin/tar-year.sh -v 1 -W +``` + + # How IOCCC HTML content is built The [md2html.sh](md2html.sh) tool is the primary tool that diff --git a/bin/tar-year.sh b/bin/tar-year.sh new file mode 100755 index 000000000..66784db51 --- /dev/null +++ b/bin/tar-year.sh @@ -0,0 +1,788 @@ +#!/usr/bin/env bash +# +# tar-year.sh - tar files belonging a given year +# +# Copyright (c) 2024 by Landon Curt Noll. All Rights Reserved. +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose and without fee is hereby granted, +# provided that the above copyright, this permission notice and text +# this comment, and the disclaimer below appear in all of the following: +# +# supporting documentation +# source copies +# source works derived from this source +# binaries derived from this source or from derived source +# +# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +# chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ +# +# Share and enjoy! :-) + +# firewall - must be bash with a version 4.2 or later +# +# We must declare arrays with -ag or -Ag, and we need loops to "export" modified variables. +# +if [[ -z ${BASH_VERSINFO[0]} || ${BASH_VERSINFO[0]} -lt 4 || ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 2 ]]; then + echo "$0: ERROR: bash version must be >= 4.2: $BASH_VERSION" 1>&2 + exit 4 +fi + +# setup bash file matching +# +# Requires bash with a version 4.2 or later +# +shopt -s nullglob # enable expanded to nothing rather than remaining unexpanded +shopt -u failglob # disable error message if no matches are found +shopt -u dotglob # disable matching files starting with . +shopt -s globskipdots # enable never matching . or .. +shopt -u nocaseglob # disable strict case matching +shopt -u extglob # enable extended globbing patterns +shopt -s globstar # enable ** to match all files and zero or more directories and subdirectories + +# set variables referenced in the usage message +# +export VERSION="1.0 2024-02-17" +NAME=$(basename "$0") +export NAME +export V_FLAG=0 +GIT_TOOL=$(type -P git) +export GIT_TOOL +if [[ -z "$GIT_TOOL" ]]; then + echo "$0: FATAL: git tool is not installed or not in \$PATH" 1>&2 + exit 210 +fi +"$GIT_TOOL" rev-parse --is-inside-work-tree >/dev/null 2>&1 +status="$?" +if [[ $status -eq 0 ]]; then + TOPDIR=$("$GIT_TOOL" rev-parse --show-toplevel) +fi +export TOPDIR +export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc" +export CAP_W_FLAG_FOUND= +GTAR_TOOL=$(type -P gtar) +export GTAR_TOOL +if [[ -z "$GIT_TOOL" ]]; then + echo "$0: FATAL: gtar (gnu tar) tool is not installed or not in \$PATH" 1>&2 + exit 9 +fi + +# set usage message +# +export USAGE="usage: $0 [-h] [-v level] [-V] [-d topdir] [-D docroot/] [-n] [-N] + [-p tool] [-u repo_url] [-w site_url] [-W] + YYYY + + -h print help message and exit + -v level set verbosity level (def level: 0) + -V print version string and exit + + -d topdir set topdir (def: $TOPDIR) + -D docroot/ This option is ignored + + -n go thru the actions, but do not update any files (def: do the action) + -N do not process file, just parse arguments and ignore the file (def: process the file) + + -p tool This option is ignored + + -u repo_url This option is ignored + -w site_url This option is ignored + + -W Warn if a file in the manifest is missing: (def: error if a file is missing) + + YYYY IOCCC year + +Exit codes: + 0 all OK + 1 a file listed in .entry.json or .filelist is missing and -W was not used, or no files were found + 2 -h and help string printed or -V and version string printed + 3 command line error + 4 bash version is < 4.2 + 5 YYYY/dir is not a entry directory, or YYYY is not an IOCCC year + 6 bin/filelist.entry.json.awk is not a non-empty readable file + 7 error in trying to determine files used by the year + 8 missing critical top level file or missing .filelist file + 9 gnu tar is missing or execution failed + >= 10 < 210 ((not used)) + >= 210 internal tool error + +$NAME version: $VERSION" + +# setup +# +export NOOP= +export DO_NOT_PROCESS= +export EXIT_CODE="0" + +# parse command line +# +while getopts :hv:Vd:D:nNp:u:U:w:W flag; do + case "$flag" in + h) echo "$USAGE" 1>&2 + exit 2 + ;; + v) V_FLAG="$OPTARG" + ;; + V) echo "$VERSION" + exit 2 + ;; + d) TOPDIR="$OPTARG" + ;; + D) ;; + n) NOOP="-n" + ;; + N) DO_NOT_PROCESS="-N" + ;; + p) ;; + u) ;; + U) ;; + w) ;; + W) CAP_W_FLAG_FOUND="true" + ;; + \?) echo "$0: ERROR: invalid option: -$OPTARG" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + :) echo "$0: ERROR: option -$OPTARG requires an argument" 1>&2 + echo 1>&2 + echo "$USAGE" 1>&2 + exit 3 + ;; + *) echo "$0: ERROR: unexpected value from getopts: $flag" 1>&2 + echo 1>&2 + echo "$USAGE" 1>&2 + exit 3 + ;; + esac +done + +# parse the command line arguments +# +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: debug level: $V_FLAG" 1>&2 +fi +# +shift $(( OPTIND - 1 )); +# +if [[ $V_FLAG -ge 5 ]]; then + echo "$0: debug[5]: file argument count: $#" 1>&2 +fi +if [[ $# -ne 1 ]]; then + echo "$0: ERROR: expected 1 arg, found: $#" 1>&2 + exit 3 +fi +# +export YYYY="$1" + +# verify that we have a topdir directory +# +REPO_NAME=$(basename "$REPO_URL") +export REPO_NAME +if [[ -z $TOPDIR ]]; then + echo "$0: ERROR: cannot find top of git repo directory" 1>&2 + echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2 + exit 220 +fi +if [[ ! -e $TOPDIR ]]; then + echo "$0: ERROR: TOPDIR does not exist: $TOPDIR" 1>&2 + echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2 + exit 221 +fi +if [[ ! -d $TOPDIR ]]; then + echo "$0: ERROR: TOPDIR is not a directory: $TOPDIR" 1>&2 + echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2 + exit 222 +fi + +# verify that we have an bin subdirectory +# +export BIN_PATH="$TOPDIR/bin" +if [[ ! -d $BIN_PATH ]]; then + echo "$0: ERROR: bin is not a directory under topdir: $BIN_PATH" 1>&2 + exit 223 +fi +export BIN_DIR="bin" + +# cd to topdir +# +if [[ ! -e $TOPDIR ]]; then + echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2 + exit 224 +fi +if [[ ! -d $TOPDIR ]]; then + echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2 + exit 225 +fi +export CD_FAILED +if [[ $V_FLAG -ge 5 ]]; then + echo "$0: debug[5]: about to: cd $TOPDIR" 1>&2 +fi +cd "$TOPDIR" || CD_FAILED="true" +if [[ -n $CD_FAILED ]]; then + echo "$0: ERROR: cd $TOPDIR failed" 1>&2 + exit 226 +fi +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2 +fi + +# determine the name of our tarball +# +export TARBALL="$YYYY/$YYYY.tar.bz2" + +# verify we have our awk tool +# +export FILELIST_ENTRY_JSON_AWK="$BIN_DIR/filelist.entry.json.awk" +if [[ ! -e $FILELIST_ENTRY_JSON_AWK ]]; then + echo "$0: ERROR: filelist.entry.json.awk does not exist: $FILELIST_ENTRY_JSON_AWK" 1>&2 + exit 6 +fi +if [[ ! -f $FILELIST_ENTRY_JSON_AWK ]]; then + echo "$0: ERROR: filelist.entry.json.awk is not a file: $FILELIST_ENTRY_JSON_AWK" 1>&2 + exit 6 +fi +if [[ ! -r $FILELIST_ENTRY_JSON_AWK ]]; then + echo "$0: ERROR: filelist.entry.json.awk is not a readable file: $FILELIST_ENTRY_JSON_AWK" 1>&2 + exit 6 +fi +if [[ ! -s $FILELIST_ENTRY_JSON_AWK ]]; then + echo "$0: ERROR: filelist.entry.json.awk is not a not a non-empty readable file: $FILELIST_ENTRY_JSON_AWK" 1>&2 + exit 6 +fi + +# verify we have non-empty readable ioccc.css file +# +export IOCCC_CSS="ioccc.css" +if [[ ! -e $IOCCC_CSS ]]; then + echo "$0: ERROR: ioccc.css does not exist: $IOCCC_CSS" 1>&2 + exit 8 +fi +if [[ ! -f $IOCCC_CSS ]]; then + echo "$0: ERROR: ioccc.css is not a file: $IOCCC_CSS" 1>&2 + exit 8 +fi +if [[ ! -r $IOCCC_CSS ]]; then + echo "$0: ERROR: ioccc.css is not a readable file: $IOCCC_CSS" 1>&2 + exit 8 +fi +if [[ ! -s $IOCCC_CSS ]]; then + echo "$0: ERROR: ioccc.css is not a not a non-empty readable file: $IOCCC_CSS" 1>&2 + exit 8 +fi + +# verify we have non-empty readable ioccc.css file +# +export VAR_MK="var.mk" +if [[ ! -e $VAR_MK ]]; then + echo "$0: ERROR: var.mk does not exist: $VAR_MK" 1>&2 + exit 8 +fi +if [[ ! -f $VAR_MK ]]; then + echo "$0: ERROR: var.mk is not a file: $VAR_MK" 1>&2 + exit 8 +fi +if [[ ! -r $VAR_MK ]]; then + echo "$0: ERROR: var.mk is not a readable file: $VAR_MK" 1>&2 + exit 8 +fi +if [[ ! -s $VAR_MK ]]; then + echo "$0: ERROR: var.mk is not a not a non-empty readable file: $VAR_MK" 1>&2 + exit 8 +fi + +# verify we have non-empty readable year level .filelist file +# +export FILELIST="$YYYY/.filelist" +if [[ ! -e $FILELIST ]]; then + echo "$0: ERROR: .filelist for $YYYY does not exist: $FILELIST" 1>&2 + exit 8 +fi +if [[ ! -f $FILELIST ]]; then + echo "$0: ERROR: .filelist for $YYYY is not a file: $FILELIST" 1>&2 + exit 8 +fi +if [[ ! -r $FILELIST ]]; then + echo "$0: ERROR: .filelist for $YYYY is not a readable file: $FILELIST" 1>&2 + exit 8 +fi +if [[ ! -s $FILELIST ]]; then + echo "$0: ERROR: .filelist for $YYYY is not a not a non-empty readable file: $FILELIST" 1>&2 + exit 8 +fi + +# parameter debugging +# +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: VERSION=$VERSION" 1>&2 + echo "$0: debug[3]: NAME=$NAME" 1>&2 + echo "$0: debug[3]: V_FLAG=$V_FLAG" 1>&2 + echo "$0: debug[3]: GIT_TOOL=$GIT_TOOL" 1>&2 + echo "$0: debug[3]: GTAR_TOOL=$GTAR_TOOL" 1>&2 + echo "$0: debug[3]: TOPDIR=$TOPDIR" 1>&2 + echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2 + echo "$0: debug[3]: NOOP=$NOOP" 1>&2 + echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2 + echo "$0: debug[3]: CAP_W_FLAG_FOUND=$CAP_W_FLAG_FOUND" 1>&2 + echo "$0: debug[3]: EXIT_CODE=$EXIT_CODE" 1>&2 + echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2 + echo "$0: debug[3]: BIN_PATH=$BIN_PATH" 1>&2 + echo "$0: debug[3]: BIN_DIR=$BIN_DIR" 1>&2 + echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2 + echo "$0: debug[3]: TARBALL=$TARBALL" 1>&2 + echo "$0: debug[3]: FILELIST_ENTRY_JSON_AWK=$FILELIST_ENTRY_JSON_AWK" 1>&2 + echo "$0: debug[3]: IOCCC_CSS=$IOCCC_CSS" 1>&2 + echo "$0: debug[3]: VAR_MK=$VAR_MK" 1>&2 + echo "$0: debug[3]: FILELIST=$FILELIST" 1>&2 +fi + +# If -N, time to exit +# +if [[ -n $DO_NOT_PROCESS ]]; then + if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: arguments parsed, -N given, exit 0" 1>&2 + fi + exit 0 +fi + +# create a temporary file manifest list +# +TMP_MANIFEST_LIST=".$NAME.$$.manifest.list" +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: temporary file manifest list: $TMP_MANIFEST_LIST" 1>&2 +fi +if [[ -z $NOOP ]]; then + trap 'rm -f $TMP_MANIFEST_LIST; exit' 0 1 2 3 15 + rm -f "$TMP_MANIFEST_LIST" + if [[ -e $TMP_MANIFEST_LIST ]]; then + echo "$0: ERROR: cannot remove temporary file manifest list: $TMP_MANIFEST_LIST" 1>&2 + exit 227 + fi + :> "$TMP_MANIFEST_LIST" + if [[ ! -e $TMP_MANIFEST_LIST ]]; then + echo "$0: ERROR: cannot create temporary file manifest list: $TMP_MANIFEST_LIST" 1>&2 + exit 228 + fi +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary file manifest list is not used: $TMP_MANIFEST_LIST" 1>&2 +fi + +# create a temporary sort list of files to tar +# +TMP_TAR_LIST=".$NAME.$$.tar.list" +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: temporary file tar list: $TMP_TAR_LIST" 1>&2 +fi +if [[ -z $NOOP ]]; then + trap 'rm -f $TMP_MANIFEST_LIST $TMP_TAR_LIST; exit' 0 1 2 3 15 + rm -f "$TMP_TAR_LIST" + if [[ -e $TMP_TAR_LIST ]]; then + echo "$0: ERROR: cannot remove temporary file tar list: $TMP_TAR_LIST" 1>&2 + exit 231 + fi + :> "$TMP_TAR_LIST" + if [[ ! -e $TMP_TAR_LIST ]]; then + echo "$0: ERROR: cannot create temporary file tar list: $TMP_TAR_LIST" 1>&2 + exit 232 + fi +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary file tar list is not used: $TMP_TAR_LIST" 1>&2 +fi + +# create a temporary exit code +# +# It is a pain to set the EXIT_CODE deep inside a loop, so we write the EXIT_CODE into a file +# and read the file (setting EXIT_CODE again) after the loop. A hack, but good enough for our needs. +# +TMP_EXIT_CODE=".$NAME.$$.exit.code" +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: temporary exit code: $TMP_EXIT_CODE" 1>&2 +fi +if [[ -z $NOOP ]]; then + trap 'rm -f $TMP_MANIFEST_LIST $TMP_TAR_LIST $TMP_EXIT_CODE; exit' 0 1 2 3 15 + rm -f "$TMP_EXIT_CODE" + if [[ -e $TMP_EXIT_CODE ]]; then + echo "$0: ERROR: cannot remove temporary exit code: $TMP_EXIT_CODE" 1>&2 + exit 233 + fi + echo "$EXIT_CODE" > "$TMP_EXIT_CODE" + if [[ ! -e $TMP_EXIT_CODE ]]; then + echo "$0: ERROR: cannot create temporary exit code: $TMP_EXIT_CODE" 1>&2 + exit 234 + fi +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary exit code is not used: $TMP_EXIT_CODE" 1>&2 +fi + +# create a temporary tarball +# +TMP_TARBALL=".$NAME.$$.tar.bz2" +if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: temporary tarball: $TMP_TARBALL" 1>&2 +fi +if [[ -z $NOOP ]]; then + trap 'rm -f $TMP_MANIFEST_LIST $TMP_TAR_LIST $TMP_EXIT_CODE $TMP_TARBALL; exit' 0 1 2 3 15 + rm -f "$TMP_TARBALL" + if [[ -e $TMP_TARBALL ]]; then + echo "$0: ERROR: cannot remove temporary tarball: $TMP_TARBALL" 1>&2 + exit 231 + fi + :> "$TMP_TARBALL" + if [[ ! -e $TMP_TARBALL ]]; then + echo "$0: ERROR: cannot create temporary tarball: $TMP_TARBALL" 1>&2 + exit 232 + fi +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary tarball is not used: $TMP_TARBALL" 1>&2 +fi + +# generate sorted list of entry files from the IOCCC years manifest +# +# We also add ioccc.css and var.mk from the top level. +# +if [[ -z $NOOP ]]; then + + # load the year level and top level files into the IOCCC year's manifest + # + { + grep -F -v "$TARBALL" "$FILELIST" + echo "$IOCCC_CSS" + echo "$VAR_MK" + } >> "$TMP_MANIFEST_LIST" + + # verify that YYYY is a readable directory + # + if [[ ! -e $YYYY ]]; then + echo "$0: ERROR: YYYY does not exist: $YYYY" 1>&2 + exit 7 + fi + if [[ ! -d $YYYY ]]; then + echo "$0: ERROR: YYYY is not a directory: $YYYY" 1>&2 + exit 7 + fi + if [[ ! -r $YYYY ]]; then + echo "$0: ERROR: YYYY is not an readable directory: $YYYY" 1>&2 + exit 7 + fi + + # verify that YYYY has a non-empty readable .year file + # + export YEAR_FILE="$YYYY/.year" + if [[ ! -e $YEAR_FILE ]]; then + echo "$0: ERROR: YYYY/.year does not exist: $YEAR_FILE" 1>&2 + exit 7 + fi + if [[ ! -f $YEAR_FILE ]]; then + echo "$0: ERROR: YYYY/.year is not a regular file: $YEAR_FILE" 1>&2 + exit 7 + fi + if [[ ! -r $YEAR_FILE ]]; then + echo "$0: ERROR: YYYY/.year is not an readable file: $YEAR_FILE" 1>&2 + exit 7 + fi + if [[ ! -s $YEAR_FILE ]]; then + echo "$0: ERROR: YYYY/.year is not a non-empty readable file: $YEAR_FILE" 1>&2 + exit 7 + fi + + # process each entry directory under YYYY + # + export YYYY_DIR + for YYYY_DIR in $(< "$YEAR_FILE"); do + + # debug YYYY + # + if [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: starting to process year/dir: $YYYY_DIR" 1>&2 + fi + + # parse YYYY_DIR + # + if [[ ! -d $YYYY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR is not a directory: $YYYY_DIR" 1>&2 + EXIT_CODE="7" # exit 7 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ ! -w $YYYY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR is not a writable directory: $YYYY_DIR" 1>&2 + EXIT_CODE="7" # exit 7 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + export YEAR_DIR=${YYYY_DIR%%/*} + if [[ -z $YEAR_DIR ]]; then + echo "$0: ERROR: YYYY_DIR not in YYYY/dir form: $YYYY_DIR" 1>&2 + EXIT_CODE="7" # exit 7 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + export ENTRY_DIR=${YYYY_DIR#*/} + if [[ -z $ENTRY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR not in $YEAR_DIR/dir form: $YYYY_DIR" 1>&2 + EXIT_CODE="7" # exit 7 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ $ENTRY_DIR = */* ]]; then + echo "$0: ERROR: YYYY_DIR: $YYYY_DIR dir contains a /: $ENTRY_DIR" 1>&2 + EXIT_CODE="7" # exit 7 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + + # verify that YYYY_DIR is a writable directory + # + if [[ ! -e $YYYY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR does not exist: $YYYY_DIR" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ ! -d $YYYY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR is not a directory: $YYYY_DIR" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ ! -w $YYYY_DIR ]]; then + echo "$0: ERROR: YYYY_DIR is not an writable directory: $YYYY_DIR" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + + # verify YYYY/dir/.path + # + export DOT_PATH="$YYYY_DIR/.path" + if [[ ! -s $DOT_PATH ]]; then + echo "$0: ERROR: not a non-empty file: $DOT_PATH" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + DOT_PATH_CONTENT=$(< "$DOT_PATH") + if [[ $YYYY_DIR != "$DOT_PATH_CONTENT" ]]; then + echo "$0: ERROR: arg: $YYYY_DIR does not match $DOT_PATH contents: $DOT_PATH_CONTENT" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + export ENTRY_JSON="$YYYY_DIR/.entry.json" + if [[ ! -e $ENTRY_JSON ]]; then + echo "$0: ERROR: .entry.json does not exist: $ENTRY_JSON" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ ! -f $ENTRY_JSON ]]; then + echo "$0: ERROR: .entry.json is not a file: $ENTRY_JSON" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + if [[ ! -r $ENTRY_JSON ]]; then + echo "$0: ERROR: .entry.json is not a readable file: $ENTRY_JSON" 1>&2 + EXIT_CODE="8" # exit 8 + echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2 + continue + fi + + # use the entry's manifest to add files to the IOCCC year's manifest, excluding the entry's tarball file + # + awk -f "$FILELIST_ENTRY_JSON_AWK" "$ENTRY_JSON" >> "$TMP_MANIFEST_LIST" + status="$?" + if [[ $status -ne 0 ]]; then + echo "$0: ERROR: awk -f $FILELIST_ENTRY_JSON_AWK $ENTRY_JSON >> $TMP_MANIFEST_LIST failed, error: $status" 1>&2 + exit 7 + fi + + # remove entry's tarball from the IOCCC year's manifest + # + export ENTRY_ID="${YEAR_DIR}_${ENTRY_DIR}" + sed -i '' -e "/$ENTRY_ID\.tar\.bz2$/d" "$TMP_MANIFEST_LIST" + status="$?" + if [[ $status -ne 0 ]]; then + echo "$0: ERROR: sed -i '' -e '/$ENTRY_ID.tar.bz2/d' $TMP_MANIFEST_LIST failed, error: $status" 1>&2 + exit 7 + fi + done + + # sort the manifest list + # + sort -d -u "$TMP_MANIFEST_LIST" -o "$TMP_MANIFEST_LIST" + status="$?" + if [[ $status -ne 0 ]]; then + echo "$0: ERROR: sort -d -u $TMP_MANIFEST_LIST -o $TMP_MANIFEST_LIST failed, error: $status" 1>&2 + exit 7 + fi + +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary file manifest list was not formed: $TMP_MANIFEST_LIST" 1>&2 +fi + +# generate sorted list of found entry files +# +# We exclude the compressed tarball itself because we are writing it. +# +if [[ -z $NOOP ]]; then + + # exclude the compressed tarball from the tarlist + # + grep -F -v "$TARBALL" < "$TMP_MANIFEST_LIST" | while read -r file; do + + # if file does not exist, warn + # + if [[ ! -e $file ]]; then + echo "$0: Warning: missing $YYYY_DIR file: $file" 1>&2 + # unless -W, missing files cause this tool to exit 1 + if [[ -z $CAP_W_FLAG_FOUND ]]; then + echo 1 > "$TMP_EXIT_CODE" # exit 1 + fi + else + echo "$file" + fi + done > "$TMP_TAR_LIST" + if [[ $V_FLAG -ge 7 ]]; then + echo "$0: debug[7]: list of files to tar start below" 1>&2 + cat "$TMP_TAR_LIST" 1>&2 + echo "$0: debug[7]: list of files to tar ends above" 1>&2 + fi +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary file tar list was not formed: $TMP_MANIFEST_LIST" 1>&2 +fi +if [[ ! -s "$TMP_TAR_LIST" ]]; then + echo "$0: ERROR: no files found to tar for: $ENTRY_JSON" 1>&2 + exit 1 +fi +EXIT_CODE=$(< "$TMP_EXIT_CODE") +if [[ -z $EXIT_CODE ]]; then + echo "$0: ERROR: temporary exit file is empty: $TMP_EXIT_CODE" 1>&2 + exit 233 +fi + +# form the tarball +# +# We use gnu tar to form the bzip2 compressed tarball with careful arguments +# so that the resulting tarball is the same, byte for byte. +# +if [[ -z $NOOP ]]; then + + # case: form the tarball verbosely if -v 3 or more + # + if [[ $V_FLAG -gt 3 ]]; then + echo "$0: debug[3]: about to execute:" \ + "$GTAR_TOOL --files-from=- --sparse --no-acls --sort=name" \ + "--owner=501 --group=20 --numeric-owner --totals" \ + "--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" \ + "-jcvf $TMP_TARBALL < $TMP_TAR_LIST" 1>&2 + "$GTAR_TOOL" --files-from=- --sparse --no-acls --sort=name \ + --owner=501 --group=20 --numeric-owner --totals \ + --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \ + -jcvf "$TMP_TARBALL" < "$TMP_TAR_LIST" + status="$?" + if [[ $status -ne 0 ]]; then + echo "$0: ERROR:" \ + "$GTAR_TOOL --files-from=- --sparse --no-acls --sort=name" \ + "--owner=501 --group=20 --numeric-owner --totals" \ + "--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" \ + "-jcvf $TMP_TARBALL < $TMP_TAR_LIST failed, error: $status" 1>&2 + EXIT_CODE=9 # exit 9 + fi + + # case: form the tarball silently + # + else + "$GTAR_TOOL" --files-from=- --sparse --no-acls --sort=name \ + --owner=501 --group=20 --numeric-owner \ + --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \ + -jcf "$TMP_TARBALL" < "$TMP_TAR_LIST" + status="$?" + if [[ $status -ne 0 ]]; then + echo "$0: ERROR:" \ + "$GTAR_TOOL --files-from=- --sparse --no-acls --sort=name" \ + "--owner=501 --group=20 --numeric-owner" \ + "--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" \ + "-jcf $TMP_TARBALL < $TMP_TAR_LIST failed, error: $status" 1>&2 + EXIT_CODE=9 # exit 9 + fi + fi + + # verify the tarball is not empty + # + if [[ ! -s $TMP_TARBALL ]]; then + echo "$0: ERROR: tarball is missing os empty: $TMP_TARBALL" 1>&2 + EXIT_CODE=9 # exit 9 + fi + +# case: -n +# +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, did not execute:" \ + "$GTAR_TOOL --files-from=- --sparse --no-acls --sort=name" \ + "--owner=501 --group=20 --numeric-owner --totals" \ + "--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" \ + "-jcvf $TMP_TARBALL < $TMP_TAR_LIST" 1>&2 +fi +EXIT_CODE=$(< "$TMP_EXIT_CODE") +if [[ -z $EXIT_CODE ]]; then + echo "$0: ERROR: temporary exit file has no contents: $TMP_EXIT_CODE" 1>&2 + exit 234 +fi + +# move the tarball in place only if different +# +if [[ -z $NOOP ]]; then + if cmp -s "$TMP_TARBALL" "$TARBALL"; then + + # case: tarball did not change + # + if [[ $V_FLAG -ge 5 ]]; then + echo "$0: debug[5]: file did not change: $TARBALL" 1>&2 + fi + + else + + # case: tarball changed, update the file + # + if [[ $V_FLAG -ge 5 ]]; then + echo "$0: debug[5]: mv -f -- $TMP_TARBALL $TARBALL" 1>&2 + fi + if [[ $V_FLAG -ge 3 ]]; then + mv -f -v -- "$TMP_TARBALL" "$TARBALL" + status="$?" + else + mv -f -- "$TMP_TARBALL" "$TARBALL" + status="$?" + fi + if [[ status -ne 0 ]]; then + echo "$0: ERROR: mv -f -- $TMP_TARBALL $TARBALL filed, error code: $status" 1>&2 + EXIT_CODE=9 # exit 9 + elif [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: built replaced HTML file: $TARBALL" 1>&2 + fi + if [[ ! -s $TARBALL ]]; then + echo "$0: ERROR: not a non-empty index HTML file: $TARBALL" 1>&2 + EXIT_CODE=9 # exit 9 + fi + fi + +elif [[ $V_FLAG -ge 3 ]]; then + echo "$0: debug[3]: because of -n, temporary file manifest list was not formed: $TMP_MANIFEST_LIST" 1>&2 +fi + +# All Done!!! -- Jessica Noll, Age 2 +# +if [[ -z $NOOP ]]; then + rm -f "$TMP_MANIFEST_LIST" "$TMP_TAR_LIST" "$TMP_EXIT_CODE" "$TMP_TARBALL" +elif [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: -n disabled execution of: rm -f $TMP_MANIFEST_LIST $TMP_TAR_LIST $TMP_EXIT_CODE $TMP_TARBALL" 1>&2 +fi +exit "$EXIT_CODE"