When jparse is not found it did not show how to install it, which is needed for the script to function. It might be worth pointing out that it does not use the jparse repo as that requires one to install the libraries needed, whereas the mkiocccentry clone of the repo has the libraries needed as part of its ecosystem.
2345 lines
71 KiB
Bash
Executable File
2345 lines
71 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# cvt-submission.sh - convert a submission into an entry
|
|
#
|
|
# Given a submission (that has won the IOCCC), with a `.auth.json`
|
|
# and `.info.json` and NO `.entry.json` file, we convert the
|
|
# `.auth.json` and `.info.json` into a new `.entry.json` file.
|
|
#
|
|
# We will form, as needed, new `author/author_handle.json`
|
|
# files for new authors, and update `author/author_handle.json`
|
|
# for authors who won previously.
|
|
#
|
|
# 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 - run only with a bash that is version 5.1.8 or later
|
|
#
|
|
# The "/usr/bin/env bash" command must result in using a bash that
|
|
# is version 5.1.8 or later.
|
|
#
|
|
# We could relax this version and insist on version 4.2 or later. Versions
|
|
# of bash between 4.2 and 5.1.7 might work. However, to be safe, we will require
|
|
# bash version 5.1.8 or later.
|
|
#
|
|
# WHY 5.1.8 and not 4.2? This safely is done because macOS Homebrew bash we
|
|
# often use is "version 5.2.26(1)-release" or later, and the RHEL Linux bash we
|
|
# use often use is "version 5.1.8(1)-release" or later. These versions are what
|
|
# we initially tested. We recommend you either upgrade bash or install a newer
|
|
# version of bash and adjust your $PATH so that "/usr/bin/env bash" finds a bash
|
|
# that is version 5.1.8 or later.
|
|
#
|
|
# NOTE: The macOS shipped, as of 2024 March 15, a version of bash is something like
|
|
# bash "version 3.2.57(1)-release". That macOS shipped version of bash
|
|
# will NOT work. For users of macOS we recommend you install Homebrew,
|
|
# (see https://brew.sh), and then run "brew install bash" which will
|
|
# typically install it into /opt/homebrew/bin/bash, and then arrange your $PATH
|
|
# so that "/usr/bin/env bash" finds "/opt/homebrew/bin" (or whatever the
|
|
# Homebrew bash is).
|
|
#
|
|
# NOTE: And while MacPorts might work, we noticed a number of subtle differences
|
|
# with some of their ported tools to suggest you might be better off
|
|
# with installing Homebrew (see https://brew.sh). No disrespect is intended
|
|
# to the MacPorts team as they do a commendable job. Nevertheless we ran
|
|
# into enough differences with MacPorts environments to suggest you
|
|
# might find a better experience with this tool under Homebrew instead.
|
|
#
|
|
if [[ -z ${BASH_VERSINFO[0]} ||
|
|
${BASH_VERSINFO[0]} -lt 5 ||
|
|
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -lt 1 ||
|
|
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -eq 1 && ${BASH_VERSINFO[2]} -lt 8 ]]; then
|
|
echo "$0: ERROR: bash version needs to be >= 5.1.8: $BASH_VERSION" 1>&2
|
|
echo "$0: Warning: bash version >= 4.2 might work but 5.1.8 was the minimum we tested" 1>&2
|
|
echo "$0: Notice: For macOS users: install Homebrew (see https://brew.sh), then run" \
|
|
""brew install bash" and then modify your \$PATH so that \"#!/usr/bin/env bash\"" \
|
|
"finds the Homebrew installed (usually /opt/homebrew/bin/bash) version of bash" 1>&2
|
|
exit 4
|
|
fi
|
|
|
|
|
|
# setup bash file matching
|
|
#
|
|
# We must declare arrays with -ag or -Ag, and we need loops to "export" modified variables.
|
|
# This requires a bash with a version 4.2 or later. See the larger comment above about bash versions.
|
|
#
|
|
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 -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.3.1 2024-11-16"
|
|
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 5
|
|
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
|
|
#
|
|
CHKENTRY_TOOL=$(type -P chkentry)
|
|
export CHKENTRY_TOOL
|
|
if [[ -z "$CHKENTRY_TOOL" ]]; then
|
|
echo "$0: FATAL: chkentry tool is not installed or not in \$PATH" 1>&2
|
|
echo "$0: Notice: if needed: $GIT_TOOL clone $MKIOCCCENTRY_REPO; cd mkiocccentry" 1>&2
|
|
echo "$0: Notice: then if needed: make clobber all install" 1>&2
|
|
exit 5
|
|
fi
|
|
#
|
|
VERGE=$(type -P verge)
|
|
export VERGE
|
|
if [[ -z $VERGE ]]; then
|
|
echo "$0: FATAL: verge is not installed or not in \$PATH" 1>&2
|
|
echo "$0: notice: to install verge:" 1>&2
|
|
echo "$0: notice: run: git clone https://github.com/ioccc-src/mkiocccentry.git" 1>&2
|
|
echo "$0: notice: then: cd mkiocccentry && make clobber all" 1>&2
|
|
echo "$0: notice: then: cd jparse && sudo make install clobber" 1>&2
|
|
exit 5
|
|
fi
|
|
#
|
|
JSTRDECODE=$(type -P jstrdecode)
|
|
export JSTRDECODE
|
|
if [[ -z $JSTRDECODE ]]; then
|
|
echo "$0: FATAL: jstrdecode is not installed or not in \$PATH" 1>&2
|
|
echo "$0: notice: to install jstrdecode:" 1>&2
|
|
echo "$0: notice: run: git clone https://github.com/ioccc-src/mkiocccentry.git" 1>&2
|
|
echo "$0: notice: then: cd mkiocccentry && make clobber all" 1>&2
|
|
echo "$0: notice: then: cd jparse && sudo make install clobber" 1>&2
|
|
exit 5
|
|
fi
|
|
export MIN_JSTRDECODE_VERSION="2.1.2"
|
|
JSTRDECODE_VERSION=$("$JSTRDECODE" -V | head -1 | awk '{print $3;}')
|
|
if ! "$VERGE" "$JSTRDECODE_VERSION" "$MIN_JSTRDECODE_VERSION"; then
|
|
echo "$0: FATAL: jstrdecode version: $JSTRDECODE_VERSION < minimum version: $MIN_JSTRDECODE_VERSION" 1>&2
|
|
echo "$0: notice: consider updating jstrdecode from mkiocccentry repo" 1>&2
|
|
echo "$0: notice: run: git clone https://github.com/ioccc-src/mkiocccentry.git" 1>&2
|
|
echo "$0: notice: then: cd mkiocccentry && make clobber all" 1>&2
|
|
echo "$0: notice: then: cd jparse && sudo make install clobber" 1>&2
|
|
exit 5
|
|
fi
|
|
#
|
|
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 5
|
|
fi
|
|
#
|
|
export TOPDIR
|
|
export REPO_TOP_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
|
# GitHub puts individual files under the "blob/master" sub-directory.
|
|
export REPO_URL="$REPO_TOP_URL/blob/master"
|
|
JPARSE_TOOL=$(type -P jparse)
|
|
export JPARSE_TOOL
|
|
if [[ -z "$JPARSE_TOOL" ]]; then
|
|
echo "$0: FATAL: jparse tool is not installed or not in \$PATH" 1>&2
|
|
echo "$0: notice: to install jparse:" 1>&2
|
|
echo "$0: notice: run: git clone https://github.com/ioccc-src/mkiocccentry.git" 1>&2
|
|
echo "$0: notice: then: cd mkiocccentry && make clobber all" 1>&2
|
|
echo "$0: notice: then: cd jparse && sudo make install clobber" 1>&2
|
|
exit 5
|
|
fi
|
|
export MKIOCCCENTRY_REPO="https://github.com/ioccc-src/mkiocccentry"
|
|
export INPUT_DATA_FILE
|
|
#
|
|
export NO_COMMENT="mandatory comment: because comments were removed from the original JSON spec"
|
|
export ENTRY_JSON_FORMAT_VERSION="1.2 2024-09-25"
|
|
export AUTHOR_JSON_FORMAT_VERSION="1.1 2024-02-11"
|
|
#
|
|
export NOOP=
|
|
export DO_NOT_PROCESS=
|
|
#
|
|
export TARBALL_DIR="/var/tmp"
|
|
#
|
|
export X_3="X""X""X"
|
|
|
|
|
|
# usage
|
|
#
|
|
export USAGE="usage: $0 [-h] [-v level] [-V] [-d topdir]
|
|
[-c chkentry] [-T tarball_dir]
|
|
[-i input_data] [-n] [-N] YYYY/dir
|
|
|
|
-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)
|
|
-c chkentry path to the chkentry tool (def: $CHKENTRY_TOOL)
|
|
|
|
-T tarball_dir where to form the compressed tarball of modified files (def: $TARBALL_DIR)
|
|
|
|
-i input_data read data from file and disable asking if correct (def: from stdin)
|
|
|
|
-n go thru the actions, but do not update any files (def: do the action)
|
|
-N do not process anything, just parse arguments (def: process something)
|
|
|
|
YYYY/dir path from topdir to entry directory
|
|
|
|
Exit codes:
|
|
0 all OK
|
|
1 invalid user input
|
|
2 -h and help string printed or -V and version string printed
|
|
3 command line error
|
|
4 bash version is too old
|
|
5 some internal tool is not found or not an executable file
|
|
6 problems found with or in the topdir or topdir/YYYY directory
|
|
7 invalid or missing .info.json and/or .auth.json files
|
|
>= 10 internal error
|
|
|
|
$NAME version: $VERSION"
|
|
|
|
|
|
# prompt_string
|
|
#
|
|
# Prompt the user for a string and output as a decoded JSON string.
|
|
#
|
|
# If "-i input_data: is used, the printing of the prompt is disabled,
|
|
# and the query of correctness is also disabled.
|
|
#
|
|
# usage:
|
|
# prompt_string item_name
|
|
#
|
|
# returns:
|
|
# 0 ==> no errors detected
|
|
# > 0 ==> function error number
|
|
#
|
|
function prompt_string
|
|
{
|
|
local INPUT; # user input
|
|
local DECODED; # INPUT decoded as JSON string
|
|
local Y_OR_N; # y or n
|
|
local ITEM_NAME; # name of the item being prompted for
|
|
|
|
# parse args
|
|
#
|
|
if [[ $# -ne 1 ]]; then
|
|
echo "$0: ERROR: in prompt_string: expected 1 arg, found $#" 1>&2
|
|
return 1
|
|
fi
|
|
ITEM_NAME="$1"
|
|
if [[ -z $ITEM_NAME ]]; then
|
|
echo "$0: ERROR: in prompt_string: 1st arg is empty" 1>&2
|
|
return 2
|
|
fi
|
|
|
|
# obtain for the award
|
|
#
|
|
while :; do
|
|
|
|
# prompt for value
|
|
#
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo -n "Enter $ITEM_NAME: "
|
|
fi
|
|
read -r INPUT
|
|
if [[ -z "$INPUT" ]]; then
|
|
echo "$0: Warning: in prompt_string: $ITEM_NAME cannot be empty, try again" 1>&2
|
|
echo 1>&2
|
|
continue
|
|
fi
|
|
|
|
# JSON decode value
|
|
#
|
|
DECODED=$("$JSTRDECODE" -d -q -N -- "$INPUT")
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $DECODED ]]; then
|
|
echo "$0: ERROR: in prompt_string: $JSTRDECODE -d -q -N -- $INPUT failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# verify JSON decoded value
|
|
#
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo
|
|
echo "Verify decoded $ITEM_NAME: $DECODED" 1>&2
|
|
echo
|
|
echo -n 'Is that correct? [y,N]: '
|
|
read -r Y_OR_N
|
|
if [[ $Y_OR_N == y || $Y_OR_N == Y || $Y_OR_N == yes || $Y_OR_N == YES || $Y_OR_N == Yes ]]; then
|
|
break
|
|
fi
|
|
echo
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo
|
|
fi
|
|
|
|
# set VALUE to the JSON decoded string
|
|
#
|
|
VALUE="$DECODED"
|
|
return 0
|
|
}
|
|
|
|
|
|
# prompt_integer
|
|
#
|
|
# Prompt the user for an integer and output as a decoded JSON string.
|
|
#
|
|
# If "-i input_data: is used, the printing of the prompt is disabled,
|
|
# and the query of correctness is also disabled.
|
|
#
|
|
# usage:
|
|
# prompt_integer item_name
|
|
#
|
|
# returns:
|
|
# 0 ==> no errors detected
|
|
# > 0 ==> function error number
|
|
#
|
|
function prompt_integer
|
|
{
|
|
local INPUT; # user input
|
|
local DECODED; # INPUT decoded as JSON string
|
|
local Y_OR_N; # y or n
|
|
local ITEM_NAME; # name of the item being prompted for
|
|
|
|
# parse args
|
|
#
|
|
if [[ $# -ne 1 ]]; then
|
|
echo "$0: ERROR: in prompt_integer: expected 1 arg, found $#" 1>&2
|
|
return 1
|
|
fi
|
|
ITEM_NAME="$1"
|
|
if [[ -z $ITEM_NAME ]]; then
|
|
echo "$0: ERROR: in prompt_integer: 1st arg is empty" 1>&2
|
|
return 2
|
|
fi
|
|
|
|
# obtain for the award
|
|
#
|
|
while :; do
|
|
|
|
# prompt for value
|
|
#
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo -n "Enter $ITEM_NAME: "
|
|
fi
|
|
read -r INPUT
|
|
if [[ -z "$INPUT" ]]; then
|
|
echo "$0: Warning: in prompt_integer: $ITEM_NAME cannot be empty, try again" 1>&2
|
|
echo 1>&2
|
|
continue
|
|
fi
|
|
if [[ $INPUT =~ ^[[:digit:]]+$ && $INPUT -ge 0 && $INPUT -le 4294967295 ]]; then
|
|
# JSON decode value
|
|
#
|
|
DECODED=$("$JSTRDECODE" -d -q -N -- "$INPUT")
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $DECODED ]]; then
|
|
echo "$0: ERROR: in prompt_integer: $JSTRDECODE -d -q -N -- $INPUT failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "$0: Warning: in prompt_integer: $ITEM_NAME must be an integer >= 0 and <= 4294967295, try again" 1>&2
|
|
echo 1>&2
|
|
continue
|
|
fi
|
|
|
|
# verify JSON decoded value
|
|
#
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo
|
|
echo "Verify decoded $ITEM_NAME: $DECODED" 1>&2
|
|
echo
|
|
echo -n 'Is that correct? [y,N]: '
|
|
read -r Y_OR_N
|
|
if [[ $Y_OR_N == y || $Y_OR_N == Y || $Y_OR_N == yes || $Y_OR_N == YES || $Y_OR_N == Yes ]]; then
|
|
break
|
|
fi
|
|
echo
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
if [[ -z $INPUT_DATA_FILE ]]; then
|
|
echo
|
|
fi
|
|
|
|
# set VALUE to the JSON decoded string
|
|
#
|
|
VALUE="$DECODED"
|
|
return 0
|
|
}
|
|
|
|
|
|
# manifest_csv
|
|
#
|
|
# Write a manifest entry in CSV form to stdout.
|
|
#
|
|
# usage:
|
|
# manifest_csv file_path inventory_order OK_to_edit display_as display_via_github entry_text
|
|
#
|
|
# file_path path to the file relative to the entry directory
|
|
# inventory_order inventory order as displayed in the entry index.html file
|
|
# OK_to_edit boolean for if file should be modified, edited, replaced, or even removed
|
|
# display_as kind of file it is and in particular how to display it
|
|
# display_via_github boolean indicates whether the file should be viewed via GitHub or not
|
|
# entry_text summary of what the file purpose is
|
|
#
|
|
# returns:
|
|
# 0 ==> no errors detected, but output may be empty
|
|
# > 0 ==> function error number
|
|
#
|
|
function manifest_csv
|
|
{
|
|
local FILE_PATH; # path to the file relative to the entry directory
|
|
local INVENTORY_ORDER; # inventory order as displayed in the entry index.html file
|
|
local OK_TO_EDIT; # boolean for if file should be modified, edited, replaced, or even removed
|
|
local DISPLAY_AS; # kind of file it is and in particular how to display it
|
|
local DISPLAY_VIA_GITHUB; # boolean indicates whether the file should be viewed via GitHub or not
|
|
local ENTRY_TEXT; # summary of what the file purpose is
|
|
|
|
# parse args
|
|
#
|
|
if [[ $# -ne 6 ]]; then
|
|
echo "$0: ERROR: in manifest_entry: expected 6 args, found $#" 1>&2
|
|
return 1
|
|
fi
|
|
FILE_PATH="${1//,/%%COMMA%%}"
|
|
if [[ -z $FILE_PATH ]]; then
|
|
echo "$0: ERROR: in manifest_entry: file_path arg 1 is empty" 1>&2
|
|
return 2
|
|
fi
|
|
INVENTORY_ORDER="${2//,/%%COMMA%%}"
|
|
if [[ -z $INVENTORY_ORDER ]]; then
|
|
echo "$0: ERROR: in manifest_entry: inventory_order arg 2 is empty" 1>&2
|
|
return 3
|
|
fi
|
|
OK_TO_EDIT="${3//,/%%COMMA%%}"
|
|
if [[ -z $OK_TO_EDIT ]]; then
|
|
echo "$0: ERROR: in manifest_entry: OK_to_edit arg 3 is empty" 1>&2
|
|
return 4
|
|
fi
|
|
DISPLAY_AS="${4//,/%%COMMA%%}"
|
|
if [[ -z $DISPLAY_AS ]]; then
|
|
echo "$0: ERROR: in manifest_entry: display_as arg 4 is empty" 1>&2
|
|
return 5
|
|
fi
|
|
DISPLAY_VIA_GITHUB="${5//,/%%COMMA%%}"
|
|
if [[ -z $DISPLAY_VIA_GITHUB ]]; then
|
|
echo "$0: ERROR: in manifest_entry: display_via_github arg 5 is empty" 1>&2
|
|
return 6
|
|
fi
|
|
ENTRY_TEXT="${6//,/%%COMMA%%}"
|
|
if [[ -z $ENTRY_TEXT ]]; then
|
|
echo "$0: ERROR: in manifest_entry: entry_text arg 6 is empty" 1>&2
|
|
return 7
|
|
fi
|
|
|
|
# write CSV line
|
|
#
|
|
printf "%s,%s,%s,%s,%s,%s\n" "$FILE_PATH" "$INVENTORY_ORDER" "$OK_TO_EDIT" \
|
|
"$DISPLAY_AS" "$DISPLAY_VIA_GITHUB" "$ENTRY_TEXT"
|
|
|
|
return 0
|
|
}
|
|
|
|
|
|
# manifest_entry
|
|
#
|
|
# Write a manifest entry in JSON form to stdout.
|
|
#
|
|
# usage:
|
|
# manifest_entry file_path inventory_order OK_to_edit display_as display_via_github entry_text comma
|
|
#
|
|
# file_path path to the file relative to the entry directory
|
|
# inventory_order inventory order as displayed in the entry index.html file
|
|
# OK_to_edit boolean for if file should be modified, edited, replaced, or even removed
|
|
# display_as kind of file it is and in particular how to display it
|
|
# display_via_github boolean indicates whether the file should be viewed via GitHub or not
|
|
# entry_text summary of what the file purpose is
|
|
# comma "comma" ==> print comma after array element
|
|
#
|
|
# returns:
|
|
# 0 ==> no errors detected, but output may be empty
|
|
# > 0 ==> function error number
|
|
#
|
|
function manifest_entry
|
|
{
|
|
local FILE_PATH; # path to the file relative to the entry directory
|
|
local INVENTORY_ORDER; # inventory order as displayed in the entry index.html file
|
|
local OK_TO_EDIT; # boolean for if file should be modified, edited, replaced, or even removed
|
|
local DISPLAY_AS; # kind of file it is and in particular how to display it
|
|
local DISPLAY_VIA_GITHUB; # boolean indicates whether the file should be viewed via GitHub or not
|
|
local ENTRY_TEXT; # summary of what the file purpose is
|
|
local COMMA; # true ==> print comma after array element
|
|
|
|
# parse args
|
|
#
|
|
if [[ $# -ne 7 ]]; then
|
|
echo "$0: ERROR: in manifest_entry: expected 7 args, found $#" 1>&2
|
|
return 1
|
|
fi
|
|
FILE_PATH="${1///%%COMMA%%/,}"
|
|
if [[ -z $FILE_PATH ]]; then
|
|
echo "$0: ERROR: in manifest_entry: file_path arg 1 is empty" 1>&2
|
|
return 2
|
|
fi
|
|
INVENTORY_ORDER="${2///%%COMMA%%/,}"
|
|
if [[ -z $INVENTORY_ORDER ]]; then
|
|
echo "$0: ERROR: in manifest_entry: inventory_order arg 2 is empty" 1>&2
|
|
return 3
|
|
fi
|
|
OK_TO_EDIT="${3///%%COMMA%%/,}"
|
|
if [[ -z $OK_TO_EDIT ]]; then
|
|
echo "$0: ERROR: in manifest_entry: OK_to_edit arg 3 is empty" 1>&2
|
|
return 4
|
|
fi
|
|
DISPLAY_AS="${4///%%COMMA%%/,}"
|
|
if [[ -z $DISPLAY_AS ]]; then
|
|
echo "$0: ERROR: in manifest_entry: display_as arg 4 is empty" 1>&2
|
|
return 5
|
|
fi
|
|
DISPLAY_VIA_GITHUB="${5///%%COMMA%%/,}"
|
|
if [[ -z $DISPLAY_VIA_GITHUB ]]; then
|
|
echo "$0: ERROR: in manifest_entry: display_via_github arg 5 is empty" 1>&2
|
|
return 6
|
|
fi
|
|
ENTRY_TEXT="${6///%%COMMA%%/,}"
|
|
if [[ -z $ENTRY_TEXT ]]; then
|
|
echo "$0: ERROR: in manifest_entry: entry_text arg 6 is empty" 1>&2
|
|
return 7
|
|
fi
|
|
COMMA="$7"
|
|
|
|
# start of manifest entry
|
|
#
|
|
printf " {\n"
|
|
|
|
# output file_path
|
|
#
|
|
printf " \"file_path\" : \"%s\",\n" "$FILE_PATH"
|
|
|
|
# output inventory_order
|
|
#
|
|
printf " \"inventory_order\" : %s,\n" "$INVENTORY_ORDER"
|
|
|
|
# output OK_to_edit
|
|
#
|
|
printf " \"OK_to_edit\" : %s,\n" "$OK_TO_EDIT"
|
|
|
|
# output display_as
|
|
#
|
|
printf " \"display_as\" : \"%s\",\n" "$DISPLAY_AS"
|
|
|
|
# output display_via_github
|
|
#
|
|
printf " \"display_via_github\" : %s,\n" "$DISPLAY_VIA_GITHUB"
|
|
|
|
# output entry_text
|
|
#
|
|
printf " \"entry_text\" : \"%s\"\n" "$ENTRY_TEXT"
|
|
|
|
# end of manifest entry
|
|
#
|
|
# We do not issue a return, allowing either the next manifest entry or
|
|
# the end of the manifest array to close the array.
|
|
#
|
|
if [[ $COMMA == "comma" ]]; then
|
|
printf " },\n"
|
|
else
|
|
printf " }\n"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
|
|
# write_author_handle_file - update author_handle JSON file
|
|
#
|
|
# usage:
|
|
#
|
|
# write_author_handle_file AUTHOR_INFO ENTRY_ID_SET TMP_FILENAME JSON_FILENAME
|
|
#
|
|
# AUTHOR_INFO Associative array of author_handle JSON member names and values
|
|
# ENTRY_ID_SET Array of entry_id values
|
|
# TMP_FILENAME temporary JSON file to write into
|
|
# JSON_FILENAME author_handle JSON file to create or modify if needed
|
|
#
|
|
# return:
|
|
#
|
|
# 0 ==> all OK
|
|
# =! 0 ==> error
|
|
#
|
|
function write_author_handle_file
|
|
{
|
|
local -n AUTH_INFO; # name of array of author_handle JSON member names and values
|
|
local -n ENTRY_SET; # name of array of entry_id values
|
|
local TMP_FILENAME; # temporary JSON file to write into
|
|
local JSON_FILENAME; # author_handle JSON file to create or modify if needed
|
|
local entry_set_length; # length of the array of entry_id values
|
|
local final_comma; # 2nd to final index of the array of entry_id values
|
|
local i;
|
|
|
|
# parse args
|
|
#
|
|
if [[ $# -ne 4 ]]; then
|
|
echo "$0: ERROR: in write_author_handle_file: expected 4 args, found $#" 1>&2
|
|
return 1
|
|
fi
|
|
AUTH_INFO="$1"
|
|
ENTRY_SET="$2"
|
|
TMP_FILENAME="$3"
|
|
JSON_FILENAME="$4"
|
|
|
|
# write data to the temporary file
|
|
#
|
|
{
|
|
# write start of temporary author_handle JSON file
|
|
#
|
|
printf "{\n"
|
|
printf " \"no_comment\" : \"%s\",\n" "${AUTH_INFO[no_comment]}"
|
|
printf " \"author_JSON_format_version\" : \"%s\",\n" "${AUTH_INFO[author_JSON_format_version]}"
|
|
printf " \"author_handle\" : \"%s\",\n" "${AUTH_INFO[author_handle]}"
|
|
printf " \"full_name\" : \"%s\",\n" "${AUTH_INFO[name]}"
|
|
printf " \"sort_word\" : \"%s\",\n" "${AUTH_INFO[sort_word]}"
|
|
printf " \"location_code\" : \"%s\",\n" "${AUTH_INFO[location_code]}"
|
|
if [[ ${AUTH_INFO[email]} == null || -z ${AUTH_INFO[email]} ]]; then
|
|
printf " \"email\" : null,\n"
|
|
else
|
|
printf " \"email\" : \"%s\",\n" "${AUTH_INFO[email]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[url]} == null || -z ${AUTH_INFO[url]} ]]; then
|
|
printf " \"url\" : null,\n"
|
|
else
|
|
printf " \"url\" : \"%s\",\n" "${AUTH_INFO[url]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[alt_url]} == null || -z ${AUTH_INFO[alt_url]} ]]; then
|
|
printf " \"alt_url\" : null,\n"
|
|
else
|
|
printf " \"alt_url\" : \"%s\",\n" "${AUTH_INFO[alt_url]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[deprecated_twitter_handle]} == null || -z ${AUTH_INFO[deprecated_twitter_handle]} ]]; then
|
|
printf " \"deprecated_twitter_handle\" : null,\n"
|
|
else
|
|
printf " \"deprecated_twitter_handle\" : \"%s\",\n" "${AUTH_INFO[deprecated_twitter_handle]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[mastodon]} == null || -z ${AUTH_INFO[mastodon]} ]]; then
|
|
printf " \"mastodon\" : null,\n"
|
|
else
|
|
printf " \"mastodon\" : \"%s\",\n" "${AUTH_INFO[mastodon]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[mastodon_url]} == null || -z ${AUTH_INFO[mastodon_url]} ]]; then
|
|
printf " \"mastodon_url\" : null,\n"
|
|
else
|
|
printf " \"mastodon_url\" : \"%s\",\n" "${AUTH_INFO[mastodon_url]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[github]} == null || -z ${AUTH_INFO[github]} ]]; then
|
|
printf " \"github\" : null,\n"
|
|
else
|
|
printf " \"github\" : \"%s\",\n" "${AUTH_INFO[github]}"
|
|
fi
|
|
if [[ ${AUTH_INFO[affiliation]} == null || -z ${AUTH_INFO[affiliation]} ]]; then
|
|
printf " \"affiliation\" : null,\n"
|
|
else
|
|
printf " \"affiliation\" : \"%s\",\n" "${AUTH_INFO[affiliation]}"
|
|
fi
|
|
|
|
# write the winning_entry_set array to the temporary author_handle JSON file
|
|
#
|
|
printf " \"winning_entry_set\" : [\n"
|
|
entry_set_length=${#ENTRY_SET[@]}
|
|
case "$entry_set_length" in
|
|
0) echo "$0: ERROR: Array of entry_id values is empty";
|
|
return 1
|
|
;;
|
|
1) printf " {\n"
|
|
printf " \"entry_id\" : \"%s\"\n" "${ENTRY_SET[0]}"
|
|
printf " }\n"
|
|
;;
|
|
*) ((final_comma=entry_set_length-2))
|
|
((final=entry_set_length-1))
|
|
for j in $(seq 0 "$final_comma"); do
|
|
printf " {\n"
|
|
printf " \"entry_id\" : \"%s\"\n" "${ENTRY_SET[$j]}"
|
|
printf " },\n"
|
|
done
|
|
printf " {\n"
|
|
printf " \"entry_id\" : \"%s\"\n" "${ENTRY_SET[$final]}"
|
|
printf " }\n"
|
|
;;
|
|
esac
|
|
printf " ]\n"
|
|
|
|
# write the end of the temporary author_handle JSON file
|
|
#
|
|
printf "}\n"
|
|
|
|
} > "$TMP_FILENAME"
|
|
|
|
# update author_handle JSON file if needed
|
|
#
|
|
if cmp -s "$TMP_FILENAME" "$JSON_FILENAME"; then
|
|
|
|
# case: .entry.json did not change
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: author_handle JSON file file did not change: $JSON_FILENAME" 1>&2
|
|
fi
|
|
|
|
else
|
|
|
|
# case: .entry.json file changed, update the file
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to: mv -f -- $TMP_FILENAME $JSON_FILENAME" 1>&2
|
|
fi
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
mv -f -v -- "$TMP_FILENAME" "$JSON_FILENAME" 1>&2
|
|
status="$?"
|
|
else
|
|
mv -f -- "$TMP_FILENAME" "$JSON_FILENAME" 1>&2
|
|
status="$?"
|
|
fi
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: in write_author_handle_file: mv -f -- $TMP_FILENAME $JSON_FILENAME filed," \
|
|
"error code: $status" 1>&2
|
|
return 2
|
|
elif [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: updated author_handle JSON file: $JSON_FILENAME" 1>&2
|
|
fi
|
|
if [[ ! -s $JSON_FILENAME ]]; then
|
|
echo "$0: ERROR: in write_author_handle_file: not a non-empty author_handle JSON file: $JSON_FILENAME" 1>&2
|
|
return 3
|
|
fi
|
|
fi
|
|
|
|
# all OK
|
|
#
|
|
return 0
|
|
}
|
|
|
|
|
|
# parse command line
|
|
#
|
|
while getopts :hv:Vd:c:i:T:nN flag; do
|
|
case "$flag" in
|
|
h) echo "$USAGE" 1>&2
|
|
exit 2
|
|
;;
|
|
v) V_FLAG="$OPTARG"
|
|
;;
|
|
V) echo "$VERSION"
|
|
exit 2
|
|
;;
|
|
d) TOPDIR="$OPTARG"
|
|
;;
|
|
c) CHKENTRY_TOOL="$OPTARG"
|
|
;;
|
|
i) INPUT_DATA_FILE="$OPTARG"
|
|
;;
|
|
T) TARBALL_DIR="$OPTARG"
|
|
;;
|
|
n) NOOP="-n"
|
|
;;
|
|
N) DO_NOT_PROCESS="-N"
|
|
;;
|
|
\?) echo "$0: ERROR: invalid option: -$OPTARG" 1>&2
|
|
echo 1>&2
|
|
echo "$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
|
|
#
|
|
# remove the options
|
|
#
|
|
shift $(( OPTIND - 1 ));
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: file argument count: $#" 1>&2
|
|
fi
|
|
#
|
|
# verify arg count and parse args
|
|
#
|
|
if [[ $# -ne 1 ]]; then
|
|
echo "$0: ERROR: expected 1 arg, found: $#" 1>&2
|
|
echo 1>&2
|
|
echo "$USAGE" 1>&2
|
|
exit 3
|
|
fi
|
|
export ENTRY_PATH="$1"
|
|
|
|
|
|
# if -i input_data, replace stdin with the input data file
|
|
#
|
|
if [[ -n $INPUT_DATA_FILE ]]; then
|
|
if [[ ! -e $INPUT_DATA_FILE ]]; then
|
|
echo "$0: ERROR: input data file does not exist: $INPUT_DATA_FILE" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -f $INPUT_DATA_FILE ]]; then
|
|
echo "$0: ERROR: input data filetop is not a regular file: $INPUT_DATA_FILE" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -r $INPUT_DATA_FILE ]]; then
|
|
echo "$0: ERROR: input data filetop is not a readable file: $INPUT_DATA_FILE" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -s $INPUT_DATA_FILE ]]; then
|
|
echo "$0: ERROR: input data filetop is not a non-empty readable file: $INPUT_DATA_FILE" 1>&2
|
|
exit 3
|
|
fi
|
|
exec 0<"$INPUT_DATA_FILE"
|
|
fi
|
|
|
|
|
|
# verify that we have a topdir directory
|
|
#
|
|
REPO_NAME=$(basename "$REPO_TOP_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_TOP_URL; cd $REPO_NAME" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -e $TOPDIR ]]; then
|
|
echo "$0: ERROR: TOPDIR does not exist: $TOPDIR" 1>&2
|
|
echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_TOP_URL; cd $REPO_NAME" 1>&2
|
|
exit 6
|
|
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_TOP_URL; cd $REPO_NAME" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
# cd to topdir
|
|
#
|
|
if [[ ! -e $TOPDIR ]]; then
|
|
echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -d $TOPDIR ]]; then
|
|
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
|
exit 6
|
|
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 6
|
|
fi
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
|
fi
|
|
|
|
|
|
# verify we have a non-empty readable .top file
|
|
#
|
|
export TOP_FILE=".top"
|
|
if [[ ! -e $TOP_FILE ]]; then
|
|
echo "$0: ERROR: .top does not exist: $TOP_FILE" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $TOP_FILE ]]; then
|
|
echo "$0: ERROR: .top is not a regular file: $TOP_FILE" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -r $TOP_FILE ]]; then
|
|
echo "$0: ERROR: .top is not a readable file: $TOP_FILE" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -s $TOP_FILE ]]; then
|
|
echo "$0: ERROR: .top is not a non-empty readable file: $TOP_FILE" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
|
|
# verify that we have a 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 6
|
|
fi
|
|
export BIN_DIR="bin"
|
|
|
|
|
|
# verify that the bin/md2html.sh tool is executable
|
|
#
|
|
export MD2HTML_SH="$BIN_DIR/md2html.sh"
|
|
if [[ ! -e $MD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/md2html.sh does not exist: $MD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -f $MD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/md2html.sh is not a regular file: $MD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -x $MD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/md2html.sh is not an executable file: $MD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
|
|
|
|
# verify that the bin/othermd2html.sh tool is executable
|
|
#
|
|
export OTHERMD2HTML_SH="$BIN_DIR/othermd2html.sh"
|
|
if [[ ! -e $OTHERMD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/othermd2html.sh does not exist: $OTHERMD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -f $OTHERMD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/othermd2html.sh is not a regular file: $OTHERMD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -x $OTHERMD2HTML_SH ]]; then
|
|
echo "$0: ERROR: bin/othermd2html.sh is not an executable file: $OTHERMD2HTML_SH" 1>&2
|
|
exit 5
|
|
fi
|
|
|
|
|
|
# verify that the bin/jval-wrapper.sh tool is executable
|
|
#
|
|
JVAL_WRAPPER="$BIN_DIR/jval-wrapper.sh"
|
|
if [[ ! -e $JVAL_WRAPPER ]]; then
|
|
echo "$0: ERROR: bin/jval-wrapper.sh does not exist: $JVAL_WRAPPER" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -f $JVAL_WRAPPER ]]; then
|
|
echo "$0: ERROR: bin/jval-wrapper.sh is not a regular file: $JVAL_WRAPPER" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -x $JVAL_WRAPPER ]]; then
|
|
echo "$0: ERROR: bin/jval-wrapper.sh is not an executable file: $JVAL_WRAPPER" 1>&2
|
|
exit 5
|
|
fi
|
|
|
|
|
|
# verify that ENTRY_PATH is a entry directory
|
|
#
|
|
if [[ ! -d $ENTRY_PATH ]]; then
|
|
echo "$0: ERROR: arg is not a directory: $ENTRY_PATH" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -w $ENTRY_PATH ]]; then
|
|
echo "$0: ERROR: arg is not a writable directory: $ENTRY_PATH" 1>&2
|
|
exit 3
|
|
fi
|
|
export YEAR_DIR=${ENTRY_PATH%%/*}
|
|
if [[ -z $YEAR_DIR ]]; then
|
|
echo "$0: ERROR: arg not in YYYY/dir form: $ENTRY_PATH" 1>&2
|
|
exit 3
|
|
fi
|
|
export ENTRY_DIR=${ENTRY_PATH#*/}
|
|
if [[ -z $ENTRY_DIR ]]; then
|
|
echo "$0: ERROR: arg: $ENTRY_PATH not in $YEAR_DIR/dir form: $ENTRY_PATH" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ $ENTRY_DIR = */* ]]; then
|
|
echo "$0: ERROR: dir from arg: $ENTRY_PATH contains a /: $ENTRY_DIR" 1>&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -d $YEAR_DIR ]]; then
|
|
echo "$0: ERROR: YYYY from arg: $ENTRY_PATH is not a directory: $YEAR_DIR" 1>&2
|
|
exit 3
|
|
fi
|
|
export ENTRY_ID="${YEAR_DIR}_${ENTRY_DIR}"
|
|
export DOT_YEAR="$YEAR_DIR/.year"
|
|
# Now that we have moved to topdir, form and verify YYYY_DIR is a writable directory
|
|
export YYYY_DIR="$YEAR_DIR/$ENTRY_DIR"
|
|
if [[ ! -e $YYYY_DIR ]]; then
|
|
echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH does not exist: $YYYY_DIR" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -d $YYYY_DIR ]]; then
|
|
echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH is not a directory: $YYYY_DIR" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -w $YYYY_DIR ]]; then
|
|
echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH is not a writable directory: $YYYY_DIR" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
|
|
# determine files that are found in and/or will be created in an entry
|
|
#
|
|
export INFO_JSON="$YYYY_DIR/.info.json"
|
|
export AUTH_JSON="$YYYY_DIR/.auth.json"
|
|
export REMARKS_MD="$YYYY_DIR/remarks.md"
|
|
export TAR_BZ2="$YYYY_DIR/$ENTRY_ID.tar.bz2"
|
|
export ENTRY_JSON="$YYYY_DIR/.entry.json"
|
|
export DOT_GITIGNORE="$YYYY_DIR/.gitignore"
|
|
export DOT_PATH="$YYYY_DIR/.path"
|
|
export README_MD="$YYYY_DIR/README.md"
|
|
export INDEX_HTML="$YYYY_DIR/index.html"
|
|
|
|
|
|
# determine template files
|
|
#
|
|
export TEMPLATE_DIR="template"
|
|
export TEMPLATE_ENTRY_DIR="$TEMPLATE_DIR/entry"
|
|
export TEMPLATE_GITIGNORE="$TEMPLATE_ENTRY_DIR/gitignore"
|
|
export TEMPLATE_README_MD_HEAD="$TEMPLATE_ENTRY_DIR/README.md.head"
|
|
export TEMPLATE_README_MD_TAIL="$TEMPLATE_ENTRY_DIR/README.md.tail"
|
|
|
|
|
|
# determine TARBALL filename
|
|
#
|
|
NOW=$(date '+%Y%m%d.%H%M%S')
|
|
export NOW
|
|
export TARBALL="$TARBALL_DIR/$ENTRY_ID.mods.$NOW.tar.bz2"
|
|
|
|
|
|
# print running info if verbose
|
|
#
|
|
# If -v 3 or higher, print exported variables in order that they were exported.
|
|
#
|
|
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]: TOPDIR=$TOPDIR" 1>&2
|
|
echo "$0: debug[3]: CHKENTRY_TOOL=$CHKENTRY_TOOL" 1>&2
|
|
echo "$0: debug[3]: VERGE=$VERGE" 1>&2
|
|
echo "$0: debug[3]: JSTRDECODE=$JSTRDECODE" 1>&2
|
|
echo "$0: debug[3]: MIN_JSTRDECODE_VERSION=$MIN_JSTRDECODE_VERSION" 1>&2
|
|
echo "$0: debug[3]: JSTRDECODE_VERSION=$JSTRDECODE_VERSION" 1>&2
|
|
echo "$0: debug[3]: GTAR_TOOL=$GTAR_TOOL" 1>&2
|
|
echo "$0: debug[3]: REPO_TOP_URL=$REPO_TOP_URL" 1>&2
|
|
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
|
echo "$0: debug[3]: JPARSE_TOOL=$JPARSE_TOOL" 1>&2
|
|
echo "$0: debug[3]: MKIOCCCENTRY_REPO=$MKIOCCCENTRY_REPO" 1>&2
|
|
echo "$0: debug[3]: INPUT_DATA_FILE=$INPUT_DATA_FILE" 1>&2
|
|
echo "$0: debug[3]: NO_COMMENT=$NO_COMMENT" 1>&2
|
|
echo "$0: debug[3]: ENTRY_JSON_FORMAT_VERSION=$ENTRY_JSON_FORMAT_VERSION" 1>&2
|
|
echo "$0: debug[3]: AUTHOR_JSON_FORMAT_VERSION=$AUTHOR_JSON_FORMAT_VERSION" 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]: ENTRY_PATH=$ENTRY_PATH" 1>&2
|
|
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
|
echo "$0: debug[3]: CD_FAILED=$CD_FAILED" 1>&2
|
|
echo "$0: debug[3]: TOP_FILE=$TOP_FILE" 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]: MD2HTML_SH=$MD2HTML_SH" 1>&2
|
|
echo "$0: debug[3]: OTHERMD2HTML_SH=$OTHERMD2HTML_SH" 1>&2
|
|
echo "$0: debug[3]: JVAL_WRAPPER=$JVAL_WRAPPER" 1>&2
|
|
echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
|
|
echo "$0: debug[3]: ENTRY_DIR=$ENTRY_DIR" 1>&2
|
|
echo "$0: debug[3]: ENTRY_ID=$ENTRY_ID" 1>&2
|
|
echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
|
|
echo "$0: debug[3]: YYYY_DIR=$YYYY_DIR" 1>&2
|
|
echo "$0: debug[3]: INFO_JSON=$INFO_JSON" 1>&2
|
|
echo "$0: debug[3]: AUTH_JSON=$AUTH_JSON" 1>&2
|
|
echo "$0: debug[3]: REMARKS_MD=$REMARKS_MD" 1>&2
|
|
echo "$0: debug[3]: TAR_BZ2=$TAR_BZ2" 1>&2
|
|
echo "$0: debug[3]: ENTRY_JSON=$ENTRY_JSON" 1>&2
|
|
echo "$0: debug[3]: DOT_GITIGNORE=$DOT_GITIGNORE" 1>&2
|
|
echo "$0: debug[3]: DOT_PATH=$DOT_PATH" 1>&2
|
|
echo "$0: debug[3]: README_MD=$README_MD" 1>&2
|
|
echo "$0: debug[3]: INDEX_HTML=$INDEX_HTML" 1>&2
|
|
echo "$0: debug[3]: TEMPLATE_DIR=$TEMPLATE_DIR" 1>&2
|
|
echo "$0: debug[3]: TEMPLATE_ENTRY_DIR=$TEMPLATE_ENTRY_DIR" 1>&2
|
|
echo "$0: debug[3]: TEMPLATE_GITIGNORE=$TEMPLATE_GITIGNORE" 1>&2
|
|
echo "$0: debug[3]: TEMPLATE_README_MD_HEAD=$TEMPLATE_README_MD_HEAD" 1>&2
|
|
echo "$0: debug[3]: TEMPLATE_README_MD_TAIL=$TEMPLATE_README_MD_TAIL" 1>&2
|
|
echo "$0: debug[3]: TARBALL_DIR=$TARBALL_DIR" 1>&2
|
|
echo "$0: debug[3]: NOW=$NOW" 1>&2
|
|
echo "$0: debug[3]: TARBALL=$TARBALL" 1>&2
|
|
fi
|
|
|
|
|
|
# firewall - verify template files
|
|
#
|
|
if [[ ! -d $TEMPLATE_DIR ]]; then
|
|
echo "$0: ERROR: missing template directory: $TEMPLATE_DIR" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -d $TEMPLATE_ENTRY_DIR ]]; then
|
|
echo "$0: ERROR: missing template/entry directory: $TEMPLATE_ENTRY_DIR" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $TEMPLATE_GITIGNORE ]]; then
|
|
echo "$0: ERROR: missing template gitignore file: $TEMPLATE_GITIGNORE" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $TEMPLATE_README_MD_HEAD ]]; then
|
|
echo "$0: ERROR: missing template README.md.head file: $TEMPLATE_README_MD_HEAD" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $TEMPLATE_README_MD_TAIL ]]; then
|
|
echo "$0: ERROR: missing template README.md.tail file: $TEMPLATE_README_MD_TAIL" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
|
|
# firewall - verify chkentry tool
|
|
#
|
|
if [[ ! -e $CHKENTRY_TOOL ]]; then
|
|
echo "$0: ERROR: chkentry file does not exist: $CHKENTRY_TOOL" 1>&2
|
|
echo "$0: Notice: if needed: $GIT_TOOL clone $MKIOCCCENTRY_REPO; cd mkiocccentry" 1>&2
|
|
echo "$0: Notice: then if needed: make clobber all install" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -f $CHKENTRY_TOOL ]]; then
|
|
echo "$0: ERROR: chkentry is not a file: $CHKENTRY_TOOL" 1>&2
|
|
echo "$0: Notice: if needed: $GIT_TOOL clone $MKIOCCCENTRY_REPO; cd mkiocccentry" 1>&2
|
|
echo "$0: Notice: then if needed: make clobber all install" 1>&2
|
|
exit 5
|
|
fi
|
|
if [[ ! -x $CHKENTRY_TOOL ]]; then
|
|
echo "$0: ERROR: cannot find an executable chkentry tool: $CHKENTRY_TOOL" 1>&2
|
|
echo "$0: Notice: if needed: $GIT_TOOL clone $MKIOCCCENTRY_REPO; cd mkiocccentry" 1>&2
|
|
echo "$0: Notice: then if needed: make clobber all install" 1>&2
|
|
exit 5
|
|
fi
|
|
|
|
|
|
# verify that YEAR is already in .top
|
|
#
|
|
if ! grep -E -q "^$YEAR_DIR$" "$TOP_FILE"; then
|
|
echo "$0: ERROR: YEAR_DIR: $YEAR_DIR not found in: $TOP_FILE" 1>&2
|
|
echo "$0: notice: consider running: bin/new-year.sh $YEAR_DIR -v 1" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
|
|
# verify .info.json and .auth.json are readable non-empty files
|
|
#
|
|
if [[ ! -e $INFO_JSON ]]; then
|
|
echo "$0: ERROR: .info.json does not exist: $INFO_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $INFO_JSON ]]; then
|
|
echo "$0: ERROR: .info.json is not a regular file: $INFO_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -r $INFO_JSON ]]; then
|
|
echo "$0: ERROR: .info.json is not a readable file: $INFO_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -s $INFO_JSON ]]; then
|
|
echo "$0: ERROR: .info.json is not a non-empty readable file: $INFO_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -e $AUTH_JSON ]]; then
|
|
echo "$0: ERROR: .auth.json does not exist: $AUTH_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -f $AUTH_JSON ]]; then
|
|
echo "$0: ERROR: .auth.json is not a regular file: $AUTH_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -r $AUTH_JSON ]]; then
|
|
echo "$0: ERROR: .auth.json is not a readable file: $AUTH_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
if [[ ! -s $AUTH_JSON ]]; then
|
|
echo "$0: ERROR: .auth.json is not a non-empty readable file: $AUTH_JSON" 1>&2
|
|
exit 6
|
|
fi
|
|
|
|
|
|
# initialize the list of files that we might tar
|
|
#
|
|
unset TAR_FILE_SET
|
|
declare -ag TAR_FILE_SET
|
|
#
|
|
for FILE in "$INFO_JSON" "$AUTH_JSON" "$REMARKS_MD" "$README_MD" "$INDEX_HTML" "$TAR_BZ2"; do
|
|
if [[ -f $FILE ]]; then
|
|
TAR_FILE_SET+=("$FILE")
|
|
fi
|
|
done
|
|
#
|
|
# add each author/author_handle.json file referenced by .auth.json file that exists
|
|
#
|
|
unset AUTHOR_HANDLE_SET
|
|
declare -ag AUTHOR_HANDLE_SET
|
|
#
|
|
export PATTERN
|
|
PATTERN='$..author_handle'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $AUTH_JSON '$PATTERN'" 1>&2
|
|
fi
|
|
export FOUND_AUTHOR_HANDLES
|
|
FOUND_AUTHOR_HANDLES=$("$JVAL_WRAPPER" -b -q -- "$AUTH_JSON" "$PATTERN")
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -b -q -- $AUTH_JSON '$PATTERN' failed," \
|
|
"error code: $status" 1>&2
|
|
exit 10
|
|
fi
|
|
if [[ -z $FOUND_AUTHOR_HANDLES ]]; then
|
|
echo "$0: ERROR: found no author_handle's in: $AUTH_JSON" 1>&2
|
|
exit 11
|
|
fi
|
|
for AUTHOR_HANDLE in $FOUND_AUTHOR_HANDLES; do
|
|
# add referenced by .auth.json if it exists
|
|
AUTHOR_HANDLE_JSON="author/$AUTHOR_HANDLE.json"
|
|
if [[ -f $AUTHOR_HANDLE_JSON ]]; then
|
|
TAR_FILE_SET+=("$AUTHOR_HANDLE_JSON")
|
|
fi
|
|
# remember the author_handle for later even if it doesn't exist
|
|
AUTHOR_HANDLE_SET+=("$AUTHOR_HANDLE")
|
|
done
|
|
#
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
for index in "${!TAR_FILE_SET[@]}"; do
|
|
echo "$0: debug[3]: TAR_FILE_SET[$index]=${TAR_FILE_SET[$index]}" 1>&2
|
|
done
|
|
fi
|
|
|
|
|
|
# perform the semantic check on .info.json and .auth.json
|
|
#
|
|
if [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: about to run: $CHKENTRY_TOOL -v 1 -- $INFO_JSON $AUTH_JSON" 1>&2
|
|
"$CHKENTRY_TOOL" -v 1 -- "$INFO_JSON" "$AUTH_JSON"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $CHKENTRY_TOOL -v 1 -- $INFO_JSON $AUTH_JSON failed," \
|
|
"error code: $status" 1>&2
|
|
exit 7
|
|
fi
|
|
else
|
|
"$CHKENTRY_TOOL" -- "$INFO_JSON" "$AUTH_JSON"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: $CHKENTRY_TOOL -- $INFO_JSON $AUTH_JSON failed," \
|
|
"error code: $status" 1>&2
|
|
exit 7
|
|
fi
|
|
fi
|
|
|
|
|
|
# -N stops early before any processing is performed
|
|
#
|
|
if [[ -n $DO_NOT_PROCESS ]]; then
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: arguments parsed, -N given, exiting 0" 1>&2
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
|
|
# save files that might be added to or removed from the tarball
|
|
#
|
|
if [[ -z $NOOP ]]; then
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: about to execute:" \
|
|
"TZ=UTC LC_ALL=C $GTAR_TOOL --sort=name" \
|
|
"--totals -jcvf $TARBALL ${TAR_FILE_SET[*]}" 1>&2
|
|
TZ=UTC LC_ALL=C "$GTAR_TOOL" --sort=name \
|
|
--totals -jcvf "$TARBALL" "${TAR_FILE_SET[@]}"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR:" \
|
|
"TZ=UTC LC_ALL=C $GTAR_TOOL --sort=name" \
|
|
"--totals -jcvf $TARBALL ${TAR_FILE_SET[*]} failed, error: $status" 1>&2
|
|
exit 12
|
|
fi
|
|
|
|
# case: form the tarball silently
|
|
#
|
|
else
|
|
TZ=UTC LC_ALL=C "$GTAR_TOOL" --sort=name \
|
|
-jcf "$TARBALL" "${TAR_FILE_SET[@]}"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR:" \
|
|
"TZ=UTC LC_ALL=C $GTAR_TOOL --sort=name" \
|
|
"-jcf $TARBALL ${TAR_FILE_SET[*]} failed, error: $status" 1>&2
|
|
exit 13
|
|
fi
|
|
fi
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: because of -n, tarball not formed: $TARBALL" 1>&2
|
|
fi
|
|
|
|
|
|
# create a temporary .entry.json file
|
|
#
|
|
export TMP_ENTRY_JSON=".tmp.$NAME.ENTRY_JSON.$$.tmp"
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: temporary .entry.json file: $TMP_ENTRY_JSON" 1>&2
|
|
fi
|
|
if [[ -z $NOOP ]]; then
|
|
trap 'rm -f $TMP_ENTRY_JSON; exit' 0 1 2 3 15
|
|
rm -f "$TMP_ENTRY_JSON"
|
|
if [[ -e $TMP_ENTRY_JSON ]]; then
|
|
echo "$0: ERROR: cannot remove temporary .entry.json file: $TMP_ENTRY_JSON" 1>&2
|
|
exit 14
|
|
fi
|
|
:> "$TMP_ENTRY_JSON"
|
|
if [[ ! -e $TMP_ENTRY_JSON ]]; then
|
|
echo "$0: ERROR: cannot create temporary .entry.json file: $TMP_ENTRY_JSON" 1>&2
|
|
exit 15
|
|
fi
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: because of -n, temporary .entry.json file is not used: $TMP_ENTRY_JSON" 1>&2
|
|
fi
|
|
|
|
|
|
# create a temporary author_handle JSON file
|
|
#
|
|
export TMP_AUTHOR_HANDLE_JSON=".tmp.$NAME.AUTHOR_HANDLE_JSON.$$.tmp"
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: temporary author_handle file: $TMP_AUTHOR_HANDLE_JSON" 1>&2
|
|
fi
|
|
if [[ -z $NOOP ]]; then
|
|
trap 'rm -f $TMP_ENTRY_JSON $TMP_AUTHOR_HANDLE_JSON; exit' 0 1 2 3 15
|
|
rm -f "$TMP_AUTHOR_HANDLE_JSON"
|
|
if [[ -e $TMP_AUTHOR_HANDLE_JSON ]]; then
|
|
echo "$0: ERROR: cannot remove temporary author_handle file: $TMP_AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 16
|
|
fi
|
|
:> "$TMP_AUTHOR_HANDLE_JSON"
|
|
if [[ ! -e $TMP_AUTHOR_HANDLE_JSON ]]; then
|
|
echo "$0: ERROR: cannot create temporary author_handle file: $TMP_AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 17
|
|
fi
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: because of -n, temporary author_handle file is not used: $TMP_AUTHOR_HANDLE_JSON" 1>&2
|
|
fi
|
|
|
|
|
|
# create a temporary manifest.csv file
|
|
#
|
|
export TMP_MANIFEST_CSV=".tmp.$NAME.MANIFEST_CSV.$$.tmp"
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: temporary manifest csv file: $TMP_MANIFEST_CSV" 1>&2
|
|
fi
|
|
if [[ -z $NOOP ]]; then
|
|
trap 'rm -f $TMP_ENTRY_JSON $TMP_AUTHOR_HANDLE_JSON $TMP_MANIFEST_CSV; exit' 0 1 2 3 15
|
|
rm -f "$TMP_MANIFEST_CSV"
|
|
if [[ -e $TMP_MANIFEST_CSV ]]; then
|
|
echo "$0: ERROR: cannot remove temporary manifest csv file: $TMP_MANIFEST_CSV" 1>&2
|
|
exit 18
|
|
fi
|
|
:> "$TMP_MANIFEST_CSV"
|
|
if [[ ! -e $TMP_MANIFEST_CSV ]]; then
|
|
echo "$0: ERROR: cannot create temporary manifest csv file: $TMP_MANIFEST_CSV" 1>&2
|
|
exit 19
|
|
fi
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: because of -n, temporary manifest csv file is not used: $TMP_MANIFEST_CSV" 1>&2
|
|
fi
|
|
|
|
|
|
# obtain title from .info.json
|
|
#
|
|
export PATTERN='$..title'
|
|
TITLE=$("$JVAL_WRAPPER" -b -q "$INFO_JSON" "$PATTERN")
|
|
export TITLE
|
|
if [[ -z $TITLE ]]; then
|
|
TITLE="${ENTRY_DIR}.${YEAR_DIR}"
|
|
echo "$0: Warning empty title for in $INFO_JSON, use $TITLE" 1>&2
|
|
fi
|
|
|
|
|
|
# obtain title from .info.json
|
|
#
|
|
export ABSTRACT='$..abstract'
|
|
ABSTRACT=$("$JVAL_WRAPPER" -b -q "$INFO_JSON" "$PATTERN")
|
|
export ABSTRACT
|
|
if [[ -z $ABSTRACT ]]; then
|
|
ABSTRACT="default abstract for ${YEAR_DIR}/${ENTRY_DIR}"
|
|
echo "$0: Warning empty abstreact for in $INFO_JSON, will use $ABSTRACT" 1>&2
|
|
fi
|
|
|
|
|
|
# case: without -n
|
|
#
|
|
export VALUE
|
|
if [[ -z $NOOP ]]; then
|
|
|
|
# form the start of the temporary .entry.json file
|
|
#
|
|
{
|
|
echo '{'
|
|
echo ' "no_comment" : "'"$NO_COMMENT"'",'
|
|
echo ' "entry_JSON_format_version" : "'"$ENTRY_JSON_FORMAT_VERSION"'",'
|
|
} > "$TMP_ENTRY_JSON"
|
|
|
|
# write the award to the temporary .entry.json file
|
|
#
|
|
VALUE=
|
|
prompt_string "award"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string award failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
{
|
|
# write award
|
|
#
|
|
echo " \"award\" : \"${VALUE}\","
|
|
|
|
# write IOCCC year to the temporary .entry.json file
|
|
#
|
|
echo " \"year\" : ${YEAR_DIR},"
|
|
|
|
# write entry directory to the temporary .entry.json file
|
|
#
|
|
echo " \"dir\" : \"${ENTRY_DIR}\","
|
|
|
|
# write entry_id to the temporary .entry.json file
|
|
#
|
|
echo " \"entry_id\" : \"${ENTRY_ID}\","
|
|
|
|
# write title to the temporary .entry.json file
|
|
#
|
|
echo " \"title\" : \"${TITLE}\","
|
|
|
|
# write abstract to the temporary .entry.json file
|
|
#
|
|
echo " \"abstract\" : \"${ABSTRACT}\","
|
|
|
|
# start the author_set JSON array
|
|
#
|
|
echo " \"author_set\" : ["
|
|
} >> "$TMP_ENTRY_JSON"
|
|
|
|
# process each author_handle
|
|
#
|
|
export i=0
|
|
# In the for loop below, we prefer to use individual redirects
|
|
#
|
|
# SC2129 (style): Consider using { cmd1; cmd2; } >> file instead of individual redirects
|
|
# https://www.shellcheck.net/wiki/SC2129
|
|
# shellcheck disable=SC2129
|
|
for AUTHOR_HANDLE in "${AUTHOR_HANDLE_SET[@]}"; do
|
|
|
|
# case: not the first author_handle
|
|
#
|
|
if [[ $i -ge 1 ]]; then
|
|
printf ",\n"
|
|
fi
|
|
|
|
# initialize the AUTHOR_INFO
|
|
#
|
|
unset AUTHOR_INFO
|
|
declare -Ag AUTHOR_INFO
|
|
AUTHOR_INFO[no_comment]="$NO_COMMENT"
|
|
AUTHOR_INFO[author_JSON_format_version]="$AUTHOR_JSON_FORMAT_VERSION"
|
|
AUTHOR_INFO[deprecated_twitter_handle]="null"
|
|
AUTHOR_INFO[author_handle]="$AUTHOR_HANDLE"
|
|
|
|
# parse an element value of the this particular author in the authors JSON array
|
|
#
|
|
PATTERN='$.authors['"$i"']'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $AUTH_JSON '$PATTERN'" 1>&2
|
|
fi
|
|
export AUTHOR_DATA
|
|
AUTHOR_DATA=$("$JVAL_WRAPPER" -q -- "$AUTH_JSON" "$PATTERN")
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -q -- $AUTH_JSON '$PATTERN' failed," \
|
|
"error code: $status" 1>&2
|
|
exit 20
|
|
fi
|
|
if [[ -z $AUTHOR_DATA ]]; then
|
|
echo "$0: ERROR: found nothing for author[$i] in: $AUTH_JSON" 1>&2
|
|
exit 21
|
|
fi
|
|
export AUTHOR_PAST_WINNING_AUTHOR=
|
|
export AUTHOR_DEFAULT_HANDLE=
|
|
export AUTHOR_AUTHOR_NUMBER=
|
|
while read -r NAME VALUE; do
|
|
|
|
# parse name value
|
|
#
|
|
case "$NAME" in
|
|
name)
|
|
AUTHOR_INFO[name]="$VALUE"
|
|
;;
|
|
location_code)
|
|
AUTHOR_INFO[location_code]="$VALUE"
|
|
;;
|
|
email)
|
|
AUTHOR_INFO[email]="$VALUE"
|
|
;;
|
|
url)
|
|
AUTHOR_INFO[url]="$VALUE"
|
|
;;
|
|
alt_url)
|
|
AUTHOR_INFO[alt_url]="$VALUE"
|
|
;;
|
|
mastodon)
|
|
AUTHOR_INFO[mastodon]="$VALUE"
|
|
;;
|
|
github)
|
|
AUTHOR_INFO[github]="$VALUE"
|
|
;;
|
|
affiliation)
|
|
AUTHOR_INFO[affiliation]="$VALUE"
|
|
;;
|
|
past_winning_author)
|
|
AUTHOR_PAST_WINNING_AUTHOR="$VALUE"
|
|
;;
|
|
default_handle)
|
|
AUTHOR_DEFAULT_HANDLE="$VALUE"
|
|
;;
|
|
author_handle)
|
|
if [[ $AUTHOR_HANDLE != "$VALUE" ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE: $AUTHOR_HANDLE != author_handle value: $VALUE" 1>&2
|
|
exit 22
|
|
fi
|
|
AUTHOR_INFO[author_handle]="$VALUE"
|
|
;;
|
|
author_number)
|
|
if [[ $i != "$VALUE" ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE: $AUTHOR_HANDLE i: $i != author_number: $VALUE" 1>&2
|
|
exit 23
|
|
fi
|
|
AUTHOR_AUTHOR_NUMBER="$VALUE"
|
|
;;
|
|
*)
|
|
echo "$0: ERROR: AUTHOR_HANDLE: $AUTHOR_HANDLE unknown name: $NAME" 1>&2
|
|
exit 24
|
|
;;
|
|
esac
|
|
done <<< "$AUTHOR_DATA"
|
|
|
|
# verify we have all of the required information for this particular author
|
|
#
|
|
for NAME in name location_code email url alt_url mastodon github affiliation author_handle; do
|
|
if [[ -z ${AUTHOR_INFO[${NAME}]} ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE[$i]: $AUTHOR_HANDLE missing $NAME value from: $AUTH_JSON" 1>&2
|
|
exit 25
|
|
fi
|
|
done
|
|
if [[ -z $AUTHOR_PAST_WINNING_AUTHOR ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE[$i]: $AUTHOR_HANDLE missing past_winning_author value from: $AUTH_JSON" 1>&2
|
|
exit 26
|
|
fi
|
|
if [[ -z $AUTHOR_DEFAULT_HANDLE ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE[$i]: $AUTHOR_HANDLE missing default_handle value from: $AUTH_JSON" 1>&2
|
|
exit 27
|
|
fi
|
|
if [[ -z $AUTHOR_AUTHOR_NUMBER ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE[$i]: $AUTHOR_HANDLE missing author_number value from: $AUTH_JSON" 1>&2
|
|
exit 28
|
|
fi
|
|
|
|
# determine sort_word from the Author's last name
|
|
#
|
|
SORT_WORD=$(echo "${AUTHOR_INFO[name]}" | sed -e 's/^.* //' | tr '[:upper:]' '[:lower:]' | tr -d -c 'a-z0-9')
|
|
export SORT_WORD
|
|
if [[ -z $SORT_WORD ]]; then
|
|
echo "$0: ERROR: AUTHOR_HANDLE: $AUTHOR_HANDLE unable to determine the sort_word for: ${AUTHOR_INFO[name]}" 1>&2
|
|
exit 29
|
|
fi
|
|
case "$SORT_WORD" in
|
|
[a-z]*) ;;
|
|
*) SORT_WORD="z$SORT_WORD" ;; # prepend if the last name does not begin with a letter
|
|
esac
|
|
AUTHOR_INFO[sort_word]="$SORT_WORD"
|
|
|
|
# determine the mastodon_url for non-null mastodon
|
|
#
|
|
case "${AUTHOR_INFO[mastodon]}" in
|
|
\"@*@*\")
|
|
# We have a 2 phase swap and substitution. As such it is simpler to use sed.
|
|
#
|
|
# SC2001 (style): See if you can use ${variable//search/replace} instead.
|
|
# https://www.shellcheck.net/wiki/SC2001
|
|
# shellcheck disable=SC2001
|
|
AUTHOR_INFO[mastodon_url]=$(echo "${AUTHOR_INFO[mastodon]}" |
|
|
sed -e 's;^"@\([^@]*\)@\(.*\)"$;https://\2/\1;') ;;
|
|
*) AUTHOR_INFO[mastodon_url]="null" ;;
|
|
esac
|
|
|
|
# form author/author_handle.json
|
|
#
|
|
AUTHOR_HANDLE_JSON="author/$AUTHOR_HANDLE.json"
|
|
|
|
# clear the entry_id set
|
|
#
|
|
unset ENTRY_ID_SET
|
|
declare -ag ENTRY_ID_SET
|
|
|
|
# case: author/author_handle.json exists
|
|
#
|
|
if [[ -e $AUTHOR_HANDLE_JSON ]]; then
|
|
|
|
# firewall
|
|
#
|
|
if [[ ! -f $AUTHOR_HANDLE_JSON ]]; then
|
|
echo "$0: ERROR: author_handle JSON is not a file: $AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 30
|
|
fi
|
|
if [[ ! -r $AUTHOR_HANDLE_JSON ]]; then
|
|
echo "$0: ERROR: author_handle JSON is not a readable file: $AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 31
|
|
fi
|
|
if [[ ! -s $AUTHOR_HANDLE_JSON ]]; then
|
|
echo "$0: ERROR: author_handle JSON is not a non-empty readable file: $AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 32
|
|
fi
|
|
|
|
# parse author/author_handle.json file other than the winning_entry_set
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -q -- $AUTHOR_HANDLE_JSON | sed -E -e ..." 1>&2
|
|
fi
|
|
export AUTHOR_DATA
|
|
AUTHOR_DATA=$("$JVAL_WRAPPER" -q -- "$AUTHOR_HANDLE_JSON" |
|
|
sed -E -e '/^entry_id\t/d')
|
|
status_codes=("${PIPESTATUS[@]}")
|
|
if [[ ${status_codes[*]} =~ [1-9] ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -q -- $AUTHOR_HANDLE_JSON | sed -E -e ... failed," \
|
|
"error codes: ${status_codes[*]}" 1>&2
|
|
exit 33
|
|
fi
|
|
if [[ -z $AUTHOR_DATA ]]; then
|
|
echo "$0: ERROR: found entry_id's in: $AUTH_JSON" 1>&2
|
|
exit 34
|
|
fi
|
|
while read -r NAME VALUE; do
|
|
|
|
# parse name value got non
|
|
#
|
|
case "$NAME" in
|
|
no_comment)
|
|
if [[ $VALUE != "$NO_COMMENT" ]]; then
|
|
echo "$0: ERROR: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"invalid no_comment: $VALUE != \"$NO_COMMENT\"" 1>&2
|
|
exit 35
|
|
fi
|
|
;;
|
|
author_JSON_format_version)
|
|
if [[ $VALUE != "$AUTHOR_JSON_FORMAT_VERSION" ]]; then
|
|
echo "$0: ERROR: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"invalid author_JSON_format_version: $VALUE != \"$AUTHOR_JSON_FORMAT_VERSION\"" 1>&2
|
|
exit 36
|
|
fi
|
|
;;
|
|
author_handle)
|
|
if [[ $VALUE != "${AUTHOR_INFO[author_handle]}" ]]; then
|
|
echo "$0: ERROR: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"invalid author_handle: $VALUE != ${AUTHOR_INFO[author_handle]}" 1>&2
|
|
exit 37
|
|
fi
|
|
;;
|
|
full_name)
|
|
if [[ $VALUE != "${AUTHOR_INFO[name]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of full_name from: $VALUE to: ${AUTHOR_INFO[name]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
sort_word)
|
|
if [[ $VALUE != "${AUTHOR_INFO[sort_word]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of sort_word from: $VALUE to: ${AUTHOR_INFO[sort_word]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
location_code)
|
|
if [[ $VALUE != "${AUTHOR_INFO[location_code]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of location_code from: $VALUE to: ${AUTHOR_INFO[location_code]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
email)
|
|
if [[ $VALUE != "${AUTHOR_INFO[email]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of email from: $VALUE to: ${AUTHOR_INFO[email]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
url)
|
|
if [[ $VALUE != "${AUTHOR_INFO[url]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of url from: $VALUE to: ${AUTHOR_INFO[url]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
alt_url)
|
|
if [[ $VALUE != "${AUTHOR_INFO[alt_url]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of alt_url from: $VALUE to: ${AUTHOR_INFO[alt_url]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
deprecated_twitter_handle)
|
|
AUTHOR_INFO[deprecated_twitter_handle]="$VALUE"
|
|
;;
|
|
mastodon)
|
|
if [[ $VALUE != "${AUTHOR_INFO[mastodon]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of mastodon from: $VALUE to: ${AUTHOR_INFO[mastodon]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
mastodon_url)
|
|
if [[ $VALUE != "${AUTHOR_INFO[mastodon_url]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of mastodon_url from: $VALUE to: ${AUTHOR_INFO[mastodon_url]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
github)
|
|
if [[ $VALUE != "${AUTHOR_INFO[github]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of github from: $VALUE to: ${AUTHOR_INFO[github]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
affiliation)
|
|
if [[ $VALUE != "${AUTHOR_INFO[affiliation]}" ]]; then
|
|
echo "$0: notice: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"change of affiliation from: $VALUE to: ${AUTHOR_INFO[affiliation]}" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
;;
|
|
*)
|
|
echo "$0: ERROR: author_handle file: $AUTHOR_HANDLE_JSON" \
|
|
"unknown $NAME : $VALUE" 1>&2
|
|
exit 38
|
|
;;
|
|
esac
|
|
done <<< "$AUTHOR_DATA"
|
|
|
|
# collect the entry_ids from the winning_entry_set and add the new entry_id
|
|
#
|
|
PATTERN='$..entry_id'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $AUTHOR_HANDLE_JSON '$PATTERN'" 1>&2
|
|
fi
|
|
export ENTRY_IDS
|
|
ENTRY_IDS=$( { "$JVAL_WRAPPER" -b -q -- "$AUTHOR_HANDLE_JSON" "$PATTERN";
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -b -q -- $AUTHOR_HANDLE_JSON '$PATTERN' failed," \
|
|
"error code: $status" 1>&2
|
|
exit 39
|
|
fi
|
|
echo "$ENTRY_ID"
|
|
} | LC_ALL=C sort -d -u )
|
|
if [[ -z $AUTHOR_DATA ]]; then
|
|
echo "$0: ERROR: found no entry_id's in: $AUTHOR_HANDLE_JSON" 1>&2
|
|
exit 40
|
|
fi
|
|
while read -r ENTRY_ID_SET_VALUE; do
|
|
ENTRY_ID_SET+=("$ENTRY_ID_SET_VALUE")
|
|
done <<< "$ENTRY_IDS"
|
|
|
|
# case: a new author/author_handle.json needs to be formed
|
|
#
|
|
else
|
|
ENTRY_ID_SET+=("$ENTRY_ID")
|
|
fi
|
|
|
|
# create or modify the author/author_handle.json as needed
|
|
#
|
|
write_author_handle_file AUTHOR_INFO ENTRY_ID_SET "$TMP_AUTHOR_HANDLE_JSON" "$AUTHOR_HANDLE_JSON"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: write_author_handle_file AUTHOR_INFO ENTRY_ID_SET" \
|
|
"$TMP_AUTHOR_HANDLE_JSON $AUTHOR_HANDLE_JSON failed," \
|
|
"error code: $status" 1>&2
|
|
exit 41
|
|
fi
|
|
|
|
# output the author_handle information for .entry.json
|
|
#
|
|
printf " {\n"
|
|
printf " \"author_handle\" : \"%s\"\n" "$AUTHOR_HANDLE"
|
|
printf " }"
|
|
|
|
# count this author
|
|
#
|
|
((++i))
|
|
done >> "$TMP_ENTRY_JSON"
|
|
printf "\n ],\n" >> "$TMP_ENTRY_JSON"
|
|
|
|
# begin the manifest array
|
|
#
|
|
echo " \"manifest\" : [" >> "$TMP_ENTRY_JSON"
|
|
((count=0))
|
|
|
|
# write manifest csv line for entry source code
|
|
#
|
|
# This is the 1st manifest element of the array. Moreover, we will
|
|
# leave out the trailing comma.
|
|
#
|
|
((++count))
|
|
PATTERN='$..c_src'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN'" 1>&2
|
|
fi
|
|
export FILE_PATH
|
|
FILE_PATH=$("$JVAL_WRAPPER" -b -q -- "$INFO_JSON" "$PATTERN")
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN' failed," \
|
|
"error code: $status" 1>&2
|
|
exit 42
|
|
fi
|
|
if [[ -z $FILE_PATH ]]; then
|
|
echo "$0: ERROR: cannot determine c_src in manifest from: $INFO_JSON" 1>&2
|
|
exit 7
|
|
fi
|
|
if [[ ! -e $YYYY_DIR/$FILE_PATH ]]; then
|
|
echo "$0: ERROR: manifest file for c_src does not exist: $YYYY_DIR/$FILE_PATH" 1>&2
|
|
exit 43
|
|
fi
|
|
if [[ ! -f $YYYY_DIR/$FILE_PATH ]]; then
|
|
echo "$0: ERROR: manifest file for c_src is not a file: $YYYY_DIR/$FILE_PATH" 1>&2
|
|
exit 44
|
|
fi
|
|
manifest_csv "$FILE_PATH" 20 true c true "entry source code" >> "$TMP_MANIFEST_CSV"
|
|
export PROG_C="$FILE_PATH"
|
|
|
|
# write manifest csv line for entry Makefile
|
|
#
|
|
((++count))
|
|
PATTERN='$..Makefile'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN'" 1>&2
|
|
fi
|
|
export FILE_PATH
|
|
FILE_PATH=$("$JVAL_WRAPPER" -b -q -- "$INFO_JSON" "$PATTERN")
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN' failed," \
|
|
"error code: $status" 1>&2
|
|
exit 45
|
|
fi
|
|
if [[ -z $FILE_PATH ]]; then
|
|
echo "$0: ERROR: cannot determine Makefile in manifest from: $INFO_JSON" 1>&2
|
|
exit 46
|
|
fi
|
|
if [[ ! -e $YYYY_DIR/$FILE_PATH ]]; then
|
|
echo "$0: ERROR: manifest file for Makefile does not exist: $YYYY_DIR/$FILE_PATH" 1>&2
|
|
exit 47
|
|
fi
|
|
if [[ ! -f $YYYY_DIR/$FILE_PATH ]]; then
|
|
echo "$0: ERROR: manifest file for Makefile is not a file: $YYYY_DIR/$FILE_PATH" 1>&2
|
|
exit 48
|
|
fi
|
|
manifest_csv "$FILE_PATH" 30 true makefile true "entry Makefile" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# write manifest csv line for alt source file if found
|
|
#
|
|
export ALT_C
|
|
ALT_C=$(basename "$PROG_C" .c)".alt.c"
|
|
if [[ -f $YYYY_DIR/$ALT_C ]]; then
|
|
|
|
# manifest for entry alt source code
|
|
#
|
|
((++count))
|
|
manifest_csv "$ALT_C" 40 true c true "alternate source code" >> "$TMP_MANIFEST_CSV"
|
|
fi
|
|
|
|
|
|
# form original source code if needed
|
|
#
|
|
export ORIG_C
|
|
ORIG_C=$(basename "$PROG_C" .c)".orig.c"
|
|
if [[ ! -f $YYYY_DIR/$ORIG_C ]]; then
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: about to run: cp -f -p -v $YYYY_DIR/$PROG_C $YYYY_DIR/$ORIG_C" 1>&2
|
|
cp -f -p -v "$YYYY_DIR/$PROG_C" "$YYYY_DIR/$ORIG_C"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: cp -f -p -v $YYYY_DIR/$PROG_C $YYYY_DIR/$ORIG_C failed," \
|
|
"error code: $status" 1>&2
|
|
exit 49
|
|
fi
|
|
else
|
|
cp -f -p "$YYYY_DIR/$PROG_C" "$YYYY_DIR/$ORIG_C"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: cp -f -p $YYYY_DIR/$PROG_C $YYYY_DIR/$ORIG_C failed," \
|
|
"error code: $status" 1>&2
|
|
exit 50
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# write manifest csv line for original source code
|
|
#
|
|
((++count))
|
|
manifest_csv "$ORIG_C" 50 false c true "original source code" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# collect manifest for extra_file(s)
|
|
#
|
|
export PATTERN
|
|
PATTERN='$..extra_file'
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to run: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN' | ,,, sort ..." 1>&2
|
|
fi
|
|
export EXTRA_FILE_SET
|
|
EXTRA_FILE_SET=$("$JVAL_WRAPPER" -b -q -- "$INFO_JSON" "$PATTERN" | LC_ALL=C sort -d -u)
|
|
status_codes=("${PIPESTATUS[@]}")
|
|
if [[ ${status_codes[*]} =~ [1-9] ]]; then
|
|
echo "$0: ERROR: $JVAL_WRAPPER -b -q -- $INFO_JSON '$PATTERN' | ... sort ... failed," \
|
|
"error code: ${status_codes[*]}" 1>&2
|
|
exit 51
|
|
fi
|
|
|
|
# perform some validation checks on the extra_file set
|
|
#
|
|
for EXTRA_FILE in $EXTRA_FILE_SET; do
|
|
|
|
# test if extra_file is an invalid filename
|
|
#
|
|
case "$EXTRA_FILE" in
|
|
prog.c|Makefile|prog.orig.c|index.html|README.md|remarks.md|\.*)
|
|
echo "$0: ERROR: invalid extra_file filename: $EXTRA_FILE" 1>&2
|
|
exit 52
|
|
;;
|
|
*) ;;
|
|
esac
|
|
|
|
# test if extra_file is not a file
|
|
#
|
|
if [[ ! -e $YYYY_DIR/$EXTRA_FILE ]]; then
|
|
echo "$0: ERROR: manifest file for extra_file does not exist: $YYYY_DIR/$EXTRA_FILE" 1>&2
|
|
exit 53
|
|
fi
|
|
if [[ ! -f $YYYY_DIR/$EXTRA_FILE ]]; then
|
|
echo "$0: ERROR: manifest file for extra_file is not a file: $YYYY_DIR/$EXTRA_FILE" 1>&2
|
|
exit 54
|
|
fi
|
|
done
|
|
|
|
# process HTML files that do not yet exist but are associated with markdown extra_files
|
|
#
|
|
for EXTRA_FILE in $EXTRA_FILE_SET; do
|
|
|
|
# case: extra_file is a markdown file
|
|
#
|
|
if [[ $EXTRA_FILE =~ (.*)\.md$ ]]; then
|
|
|
|
# warn if there is a HTML file associated with the markdown file
|
|
#
|
|
export HTML_FILE="${BASH_REMATCH[1]}.html"
|
|
if [[ -e $YYYY_DIR/$HTML_FILE ]]; then
|
|
echo 1>&2
|
|
echo "$0: Warning: markdown file: $EXTRA_FILE and HTML file: $HTML_FILE both exist" 1>&2
|
|
echo "$0: Warning: verify HTML file is an HTML version of markdown," \
|
|
"or exclude $YYYY_DIR/$EXTRA_FILE from bin/md2html.cfg processing" 1>&2
|
|
echo 1>&2
|
|
fi
|
|
HTML_FILE_BASENAME=$(basename "$HTML_FILE")
|
|
export HTML_FILE_BASENAME
|
|
|
|
# write manifest csv line for the markdown file
|
|
#
|
|
((++count))
|
|
manifest_csv "$EXTRA_FILE" 4000000000 true markdown true \
|
|
"markdown source for $HTML_FILE_BASENAME" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# prompt for entry_text of HTML file
|
|
#
|
|
VALUE=
|
|
prompt_string "entry_text for $HTML_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string entry_text for $HTML_FILE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
export ENTRY_TEXT="$VALUE"
|
|
|
|
# write manifest csv line for the HTML file associated with the markdown file
|
|
#
|
|
((++count))
|
|
manifest_csv "$HTML_FILE" 100 false markdown true "$ENTRY_TEXT" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# case: extra_file is an HTML file
|
|
#
|
|
elif [[ $EXTRA_FILE =~ (.*)\.html$ ]]; then
|
|
|
|
# case: there is a markdown file associated with this HTML file
|
|
#
|
|
export MD_FILE="${BASH_REMATCH[1]}.md"
|
|
if [[ -e $YYYY_DIR/$HTML_FILE ]]; then
|
|
|
|
# NOTE: We have or will process the HTML file in this loop, nothing to do here
|
|
#
|
|
continue
|
|
fi
|
|
|
|
# prompt for entry_text of HTML file
|
|
#
|
|
VALUE=
|
|
prompt_string "entry_text for $EXTRA_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string inventory_order for $EXTRA_FILE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
export ENTRY_TEXT="$VALUE"
|
|
|
|
# write manifest csv line for the HTML file associated with the markdown file
|
|
#
|
|
((++count))
|
|
manifest_csv "$EXTRA_FILE" 100 false html true "$ENTRY_TEXT" >> "$TMP_MANIFEST_CSV"
|
|
fi
|
|
done
|
|
|
|
# process extra_files that are neither markdown nor HTML
|
|
#
|
|
for EXTRA_FILE in $EXTRA_FILE_SET; do
|
|
|
|
# ignore HTML files because we processed them above
|
|
#
|
|
if [[ $EXTRA_FILE =~ \.html$ || $EXTRA_FILE =~ \.md$ ]]; then
|
|
continue
|
|
fi
|
|
|
|
# prompt for inventory_order
|
|
#
|
|
VALUE=
|
|
prompt_integer "inventory_order for $EXTRA_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string inventory_order for $EXTRA_FILE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
export INVENTORY_ORDER="$VALUE"
|
|
|
|
# prompt for display_as
|
|
#
|
|
VALUE=
|
|
prompt_string "display_as for $EXTRA_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string inventory_order for $EXTRA_FILE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
export DISPLAY_AS="$VALUE"
|
|
|
|
# prompt for entry_text
|
|
#
|
|
VALUE=
|
|
prompt_string "entry_text for $EXTRA_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 || -z $VALUE ]]; then
|
|
echo "$0: ERROR: prompt_string inventory_order for $EXTRA_FILE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 1
|
|
fi
|
|
export ENTRY_TEXT="$VALUE"
|
|
|
|
# write manifest csv line for original source code
|
|
#
|
|
((++count))
|
|
manifest_csv "$EXTRA_FILE" "$INVENTORY_ORDER" true "$DISPLAY_AS" true "$ENTRY_TEXT" >> "$TMP_MANIFEST_CSV"
|
|
done
|
|
|
|
# write manifest csv line for compressed tarball
|
|
#
|
|
((++count))
|
|
manifest_csv "$ENTRY_ID.tar.bz2" 1415926535 false tbz2 false "download entry tarball" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# write manifest csv line for .entry.json
|
|
#
|
|
((++count))
|
|
manifest_csv .entry.json 4000000000 true json true "entry summary and manifest in JSON" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# form .gitignore if needed
|
|
#
|
|
if [[ ! -f $DOT_GITIGNORE ]]; then
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: about to run: cp -f -p -v $TEMPLATE_GITIGNORE $DOT_GITIGNORE" 1>&2
|
|
cp -f -p -v "$YYYY_DIR/$PROG_C" "$DOT_GITIGNORE"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: cp -f -p -v $TEMPLATE_GITIGNORE $DOT_GITIGNORE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 55
|
|
fi
|
|
else
|
|
cp -f -p "$TEMPLATE_GITIGNORE" "$DOT_GITIGNORE"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: cp -f -p $TEMPLATE_GITIGNORE $DOT_GITIGNORE failed," \
|
|
"error code: $status" 1>&2
|
|
exit 56
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# write manifest csv line for .gitignore
|
|
#
|
|
((++count))
|
|
manifest_csv .gitignore 4000000000 true gitignore true "list of files that should not be committed under git" \
|
|
>> "$TMP_MANIFEST_CSV"
|
|
|
|
# form .path if needed
|
|
#
|
|
if [[ ! -f $DOT_PATH ]]; then
|
|
echo "$YYYY_DIR" > "$DOT_PATH"
|
|
fi
|
|
|
|
# write manifest csv line for .path
|
|
#
|
|
((++count))
|
|
manifest_csv .path 4000000000 false path false "directory path from top level directory" \
|
|
>> "$TMP_MANIFEST_CSV"
|
|
|
|
# form README.md if needed
|
|
#
|
|
if [[ ! -f $README_MD ]]; then
|
|
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: forming README.md: $README_MD"
|
|
fi
|
|
cat "$TEMPLATE_README_MD_HEAD" > "$README_MD"
|
|
if [[ -f $YYYY_DIR/remarks.md ]]; then
|
|
cat "$YYYY_DIR/remarks.md" >> "$README_MD"
|
|
else
|
|
echo "$X_3 - mo remarks.md file was found" >> "$README_MD"
|
|
fi
|
|
sed -e "s/$X_3-YEAR-$X_3/$YEAR_DIR/" "$TEMPLATE_README_MD_TAIL" >> "$README_MD"
|
|
fi
|
|
|
|
# write manifest csv line for README.md
|
|
#
|
|
((++count))
|
|
manifest_csv README.md 4000000000 true markdown true "markdown source for this web page" \
|
|
>> "$TMP_MANIFEST_CSV"
|
|
|
|
# write manifest csv line for index.html
|
|
#
|
|
((++count))
|
|
manifest_csv index.html 4294967295 false html false "this web page" >> "$TMP_MANIFEST_CSV"
|
|
|
|
# sort the manifest csv file
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to: LC_ALL=C sort -t, -k2n -k1,1 -k3,6 $TMP_MANIFEST_CSV -o $TMP_MANIFEST_CSV" 1>&2
|
|
fi
|
|
LC_ALL=C sort -t, -k2n -k1,1 -k3,6 "$TMP_MANIFEST_CSV" -o "$TMP_MANIFEST_CSV"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: LC_ALL=C sort -t, -k2n -k1,1 -k3,6 $TMP_MANIFEST_CSV -o $TMP_MANIFEST_CSV failed," \
|
|
"error code: $status" 1>&2
|
|
exit 57
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: sorted temporary manifest csv file: $TMP_MANIFEST_CSV" 1>&2
|
|
fi
|
|
|
|
# convert manifest csv lines in the manifest csv file into manifest JSON entries
|
|
#
|
|
MANIFEST_CSV_LINES=$(wc -l < "$TMP_MANIFEST_CSV")
|
|
export MANIFEST_CSV_LINES
|
|
export line=0
|
|
sed -e 's/,/ /g' "$TMP_MANIFEST_CSV" |
|
|
while read -r FILE_PATH INVENTORY_ORDER OK_TO_EDIT DISPLAY_AS DISPLAY_VIA_GITHUB ENTRY_TEXT; do
|
|
|
|
# determine if manifest needs a comma
|
|
#
|
|
((++line))
|
|
export COMMA="comma"
|
|
if [[ $line -ge $MANIFEST_CSV_LINES ]]; then
|
|
COMMA=""
|
|
fi
|
|
|
|
# write inventory item into temporary .entry.json file
|
|
#
|
|
manifest_entry "$FILE_PATH" "$INVENTORY_ORDER" "$OK_TO_EDIT" "$DISPLAY_AS" "$DISPLAY_VIA_GITHUB" \
|
|
"$ENTRY_TEXT" "$COMMA" >> "$TMP_ENTRY_JSON"
|
|
done
|
|
|
|
# end the manifest array and end of temporary .entry.json file
|
|
#
|
|
# We complete the last manifest_entry that was written.
|
|
#
|
|
printf " ]\n}\n" >> "$TMP_ENTRY_JSON"
|
|
|
|
# validate the JSON in the temporary .entry.json file
|
|
#
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: about to: $JPARSE_TOOL -q -- $TMP_ENTRY_JSON" 1>&2
|
|
fi
|
|
"$JPARSE_TOOL" -q -- "$TMP_ENTRY_JSON" 1>&2
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $JPARSE_TOOL -q -- $TMP_ENTRY_JSON filed," \
|
|
"error code: $status" 1>&2
|
|
exit 58
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: valid JSON: $TMP_ENTRY_JSON" 1>&2
|
|
fi
|
|
|
|
# update .entry.json if needed
|
|
#
|
|
if cmp -s "$TMP_ENTRY_JSON" "$ENTRY_JSON"; then
|
|
|
|
# case: .entry.json did not change
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: .entry.json file did not change: $ENTRY_JSON" 1>&2
|
|
fi
|
|
|
|
else
|
|
|
|
# case: .entry.json file changed, update the file
|
|
#
|
|
if [[ $V_FLAG -ge 5 ]]; then
|
|
echo "$0: debug[5]: about to: mv -f -- $TMP_ENTRY_JSON $ENTRY_JSON" 1>&2
|
|
fi
|
|
if [[ $V_FLAG -ge 3 ]]; then
|
|
mv -f -v -- "$TMP_ENTRY_JSON" "$ENTRY_JSON" 1>&2
|
|
status="$?"
|
|
else
|
|
mv -f -- "$TMP_ENTRY_JSON" "$ENTRY_JSON" 1>&2
|
|
status="$?"
|
|
fi
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: mv -f -- $TMP_ENTRY_JSON $ENTRY_JSON filed," \
|
|
"error code: $status" 1>&2
|
|
exit 59
|
|
elif [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: updated .entry.json: $ENTRY_JSON" 1>&2
|
|
fi
|
|
if [[ ! -s $ENTRY_JSON ]]; then
|
|
echo "$0: ERROR: not a non-empty .entry.json: $ENTRY_JSON" 1>&2
|
|
exit 60
|
|
fi
|
|
fi
|
|
|
|
# case: with -n
|
|
#
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: -n disabled adding YYYY_DIR: $YYYY_DIR to $DOT_YEAR" 1>&2
|
|
fi
|
|
|
|
|
|
|
|
# build HTML files based on extra_file markdown files
|
|
#
|
|
for EXTRA_FILE in $EXTRA_FILE_SET; do
|
|
|
|
# case: extra_file is a markdown file
|
|
#
|
|
if [[ $EXTRA_FILE =~ (.*)\.md$ ]]; then
|
|
|
|
# form HTML file if it does not exist
|
|
#
|
|
export HTML_FILE="${BASH_REMATCH[1]}.html"
|
|
if [[ ! -e $HTML_FILE ]]; then
|
|
|
|
if [[ -z $NOOP ]]; then
|
|
|
|
if [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: about to run: $OTHERMD2HTML_SH -v $V_FLAG -- $YYYY_DIR/$EXTRA_FILE" 1>&2
|
|
fi
|
|
"$OTHERMD2HTML_SH" -v "$V_FLAG" -- "$YYYY_DIR/$EXTRA_FILE"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $OTHERMD2HTML_SH -v $V_FLAG -- $YYYY_DIR/$EXTRA_FILE filed," \
|
|
"error code: $status" 1>&2
|
|
exit 61
|
|
fi
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: -n disabled forming HTML: $YYYY_DIR/$HTML_FILE" 1>&2
|
|
fi
|
|
|
|
# HTML file already exists
|
|
#
|
|
elif [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: notice: markdown: $YYYY_DIR/$EXTRA_FILE HTML file exists: $YYYY_DIR/$HTML_FILE" 1>&2
|
|
fi
|
|
fi
|
|
done
|
|
|
|
|
|
# form index.html if needed
|
|
#
|
|
if [[ -z $NOOP ]]; then
|
|
if [[ ! -f $INDEX_HTML ]]; then
|
|
|
|
if [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: about to run: $MD2HTML_SH -v $V_FLAG -- $README_MD $INDEX_HTML" 1>&2
|
|
fi
|
|
"$MD2HTML_SH" -v "$V_FLAG" -- "$README_MD" "$INDEX_HTML"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: $MD2HTML_SH -v $V_FLAG -- $README_MD $INDEX_HTML filed," \
|
|
"error code: $status" 1>&2
|
|
exit 62
|
|
fi
|
|
fi
|
|
|
|
# case: with -n
|
|
#
|
|
elif [[ $V_FLAG -ge 3 ]]; then
|
|
echo "$0: debug[3]: -n disabled forming index.html: $INDEX_HTML" 1>&2
|
|
fi
|
|
|
|
|
|
# remove submission files that are no longer needed for a winning IOCCC entry
|
|
#
|
|
if [[ $V_FLAG -ge 1 ]]; then
|
|
echo "$0: debug[1]: about to run: rm -f -v -- $INFO_JSON $AUTH_JSON $REMARKS_MD" 1>&2
|
|
fi
|
|
rm -f -v -- "$INFO_JSON" "$AUTH_JSON" "$REMARKS_MD"
|
|
status="$?"
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "$0: ERROR: rm -f -v -- $INFO_JSON $AUTH_JSON $REMARKS_MD filed," \
|
|
"error code: $status" 1>&2
|
|
exit 63
|
|
fi
|
|
|
|
|
|
# All Done!!! All Done!!! -- Jessica Noll, Age 2
|
|
#
|
|
exit 0
|