release readme2index.sh version 1.0 2024-01-14
The initial release of `bin/readme2index.sh` tool that converts `READMD.md` and various JSON files such as `.winner.json` as well as "author/author_handle.json" files. Applied the `readme2index.sh` tool to generate `2020/ferguson1/index.html`. We generated the `2020/ferguson1/index.html` by executing: ```sh ./bin/readme2index.sh -v 3 2020/ferguson1 ``` NOTE: This above tool requires **pandoc to be installed**. See the [pandoc web site](https://pandoc.org) for how to install. We used _HomeBrew_ to install it, but there is also a _macports_ process as well. NOTE: While the above web page does have formatting issues, it is a first attempt data driven programmatic web page generation. Some adjustments can be made by mostly improving `ioccc.css`, and some perhaps by modifying how `bin/pandoc_wrapper.sh` invokes pandoc. But probably most of the improvements can be made by fixing and improving `ioccc.css`. TODO: Fix and improve the `2020/ferguson1/index.html` web page by fixing and improving `ioccc.css`. Moved scripts and tools needed to generate HTML pages into a new `/bin` subdirectory. TODO: Consider getting rid of the [build-ioccc repo](https://github.com/ioccc-src/build-ioccc) and just use the `/bin` subdirectory. NOTE: Some links in the `2020/ferguson1/index.html` web page do not (yet) exist. TODO: Once the basic format of the `2020/ferguson1/index.html` web page is somewhat reasonable, generate `index.html` pages for other winners. Generate the year level `index.html' files. Generate the top level HTML files, including the missing `location.html` file. Greatly simplified the `.winner.json` file format, removing a number of fields that were not strictly needed for generating an inventory on a `index.html` page. Updated various versions: * `bin/gen-author.sh` VERSION="1.3 2024-01-14" * `bin/gen-inventory.sh` VERSION="1.0 2024-01-14" * `bin/manifest.winner.json.awk` VERSION="1.0 2024-01-14" * `bin/pandoc_wrapper.sh` VERSION="1.3 2024-01-14" * `bin/readme2index.sh` VERSION="1.0 2024-01-14" * `bin/subst.default.sh` VERSION="1.1 2024-01-14" * `bin/subst.winner-index.sh` VERSION="1.1 2024-01-14" * `tmp/gen_path_list.found.sh` VERSION="1.1 2024-01-14" * `tmp/gen_winner_json.sh` VERSION="1.1 2024-01-14" The `.winner.json` file format from winner_JSON_format_version "0.5 2023-11-04" to "1.0 2024-01-14". All `.winner.json` files have been updated to use the new `.winner.json` file format. The manifest (`tmp/manifest.numbers` and `tmp/manifest.csv`) has updated to use the new `.winner.json` file format. The following procedure was used to generate the `tmp/manifest.csv` manifest file: 0. open [manifest.numbers](manifest.numbers) in numbers: modify if/as needed NOTE: Please try to keep the [manifest.numbers](manifest.numbers) spreadsheet in order order. Use Organize -> Sort -> ((Sort Now)) to sort. NOTE: Empty fields in the [manifest.numbers](manifest.numbers) spreadsheet are not allowed. By default, a cell that is empty is colored as a warning. 1. File -> Export To -> CSV... * 1a. `[ ]` Include table names (unset) * 1b. Text Encoding: Unicode (UTF-8) * 1c. Click ((Save..)) 2. Save As: manifest.csv * 2a. Select the `tmp` directory 3. Click ((Export)) * 3a. If needed click ((Replace)) 4. Execute ./tmp/[fix_csv.sh](fix_csv.sh) NOTE: You must run the [fix_csv.sh](fix_csv.sh) in the above step in order to make the CSV file usable by other tools. NOTE: If no changes are needed in the above step, the original file content will be restored. 5. Execute ./tmp/[gen_path_list.found.sh](gen_path_list.found.sh) NOTE: The above step silently performs a `make clobber` at the top level, and so it takes a bit of time. NOTE: If no changes are needed in the above step, the original file content will be restored. 6. Execute ./tmp/[check_path_list.sh](check_path_list.sh) NOTE: The above step prints nothing and for an exit 0, then all is well. If there is a problem, such as files found that are not part of the manifest, or files in the manifest that are not found, then an error message will be printed and the tool will exit non-zero. If errors are reported, go back to step 0 and correct the errors. 7. Execute ./tmp/[run_all.sh](run_all.sh) ./gen_winner_json.sh NOTE: The above step will take a few seconds to run. It will rebuild all `.winner.json` files for all winners. NOTE: If no changes are needed in the above step, the original file content will be restored. 8. Execute `git status` and inspect changes NOTE: Check in changes if and as needed. NOTE: In a number of shell scripts under `bin/*.sh`, and in the `bin/manifest.winner.json.awk` script you will find comments of the form: ``` ``` This is a note that when tools such as `jnamval` (and `jval` and `jfmt`) are ready, these gross hacks should be replaced with calls to those tools. Until they are ready, some must be careful with the layout of JSON files. A number of bugs and typos have been fixed. NOTE: Fixing typos in the files touched by this comment is welcome. This includes scripts, data files, text files, etc. The _inventory_order_, _display_as_, _display_via_github_. and _winners_text_ fields of the [manifest.numbers](manifest.numbers) spreadsheet were just set to have some initial values. As they impact the inventory displayed on `index.html` pages, their content needs to be improved. NOTE: Improving the above mentioned fields of the [manifest.numbers](manifest.numbers) spreadsheet is welcome.
This commit is contained in:
1 parent
f5a259d3b3
commit
c6e6201209
366 files changed
+29369
-31783
No files matched your search
+247
@@ -0,0 +1,247 @@
|
||||
# bin
|
||||
|
||||
The directory holds [bin](README.md) directory
|
||||
holds tools that builds files, such as HTML content, for the
|
||||
[official IOCCC web site](https://www.ioccc.org).
|
||||
|
||||
For HTML content, the [bin](README.md) directory tools
|
||||
makes use of HTML fragments from the [inc](../inc/README.md) directory
|
||||
as well as various JSON files and other content from the
|
||||
[IOCCC GitHub repo](https://github.com/ioccc-src/temp-test-ioccc).
|
||||
|
||||
|
||||
## bin tools
|
||||
|
||||
|
||||
### [gen-author.sh](gen-author.sh)
|
||||
|
||||
Output winning author(s) Related HTML.
|
||||
|
||||
|
||||
### [gen-inventory.sh](gen-inventory.sh)
|
||||
|
||||
Output the inventory in HTML form for a winner index.html page.
|
||||
|
||||
|
||||
### [manifest.winner.json.awk](manifest.winner.json.awk)
|
||||
|
||||
Output manifest table from a winner .winner.json file.
|
||||
|
||||
|
||||
### [pandoc_wrapper.sh](pandoc_wrapper.sh)
|
||||
|
||||
Wrapper tool to run pandoc.
|
||||
|
||||
|
||||
### [readme2index.sh](readme2index.sh)
|
||||
|
||||
Convert README.md into index.html.
|
||||
|
||||
|
||||
### [subst.default.sh](subst.default.sh)
|
||||
|
||||
Print default substitutions.
|
||||
|
||||
|
||||
### [subst.winner-index.sh](subst.winner-index.sh)
|
||||
|
||||
Print substitutions for a winner index.html.
|
||||
|
||||
|
||||
### [subst.winner-navbar.awk](subst.winner-navbar.awk)
|
||||
|
||||
Output substitutions for navbar on behalf of a winner.
|
||||
|
||||
|
||||
## How HTML content is built
|
||||
|
||||
Files under the [inc](../inc/README.md) directory contain HTML fragments that the
|
||||
tools in the [bin](README.md) directory
|
||||
tools use to form HTML content for the [official IOCCC web site](https://www.ioccc.org).
|
||||
|
||||
The canonical way that HTML content is built uses, by default, files of the form:
|
||||
|
||||
```
|
||||
*.default.html
|
||||
```
|
||||
|
||||
|
||||
### HTML phases
|
||||
|
||||
The following HTML phase files are used to build HTML content:
|
||||
|
||||
0. inc/top.default.html
|
||||
1. inc/head.default.html
|
||||
2. inc/body.default.html
|
||||
3. inc/header.default.html
|
||||
4. inc/topnav.default.html
|
||||
5. inc/begin-row.default.html
|
||||
6. inc/begin-leftcolumn.default.html
|
||||
7. inc/sidenav.default.html
|
||||
8. inc/end-leftcolumn.default.html
|
||||
9. inc/begin-rightcolumn.default.html
|
||||
10. inc/before-content.default.html
|
||||
|
||||
Phases 11-19 are reserved for future use.
|
||||
|
||||
20. ((insert 'before tool' output))
|
||||
21. ((insert 'pandoc wrapper tool' output))
|
||||
22. ((insert 'after tool' output))
|
||||
|
||||
Phases 23-29 are reserved for future use.
|
||||
|
||||
30. inc/after-content.default.html
|
||||
31. inc/end-rightcolumn.default.html
|
||||
32. inc/end-row.default.html
|
||||
33. inc/footer.default.html
|
||||
34. inc/bottom.default.html
|
||||
|
||||
Phases 35-39 are reserved for future use.
|
||||
|
||||
In the above HTML phase numbers, except during HTML phase numbers 20-29, symbols of the form %%TOKEN%% are substituted.
|
||||
Any %%TOKEN%% printed by the 'before tool' (-b tool), the 'pandoc wrapper tool' (-p tool), and the 'after tool' (-a tool)
|
||||
are ignored (i.e., not substituted).
|
||||
|
||||
See the tool [readme2index.sh](readme2index.sh) for an example of
|
||||
how HTML phases are implemented.
|
||||
|
||||
|
||||
### Tool command line
|
||||
|
||||
The command line of tools in the [bin](README.md) directory,
|
||||
and perhaps modified via [md2html config file](../inc/md2html.cfg) file may change
|
||||
to using a different filename for a given phase.
|
||||
|
||||
For example when forming the HTML from `2020/ferguson2/chocolate-cake.md`,
|
||||
a different "topnav" navigation bar is needed. So instead of the
|
||||
usual top navigation bar that normally directs people to the previous
|
||||
entry for the year, or go up to the year page, or to the next entry
|
||||
for the year, a top navigation bar to just go up to the entry's
|
||||
main page is needed. A line the [md2html config file](../inc/md2html.cfg) file
|
||||
that refers to `2020/ferguson1/chocolate-cake.md` may specify use
|
||||
of `topnav.up2index.html` instead of using the `topnav.default.html` default.
|
||||
|
||||
The HTML phase may be skipped resulting in no HTML output during a given phase.
|
||||
Furthermore, forming HTML content from a given markdown file altogether.
|
||||
|
||||
See comments in the [md2html config file](../inc/md2html.cfg) file for details.
|
||||
See also, the tool [readme2index.sh](readme2index.sh) for an example of
|
||||
how such command lines are used.
|
||||
|
||||
|
||||
## Use CAUTION when modifying inc files
|
||||
|
||||
Some of the files under this directory are used to form **MOST** of the HTML content
|
||||
on the [official IOCCC web site](https://www.ioccc.org).
|
||||
|
||||
These files are used to form **MOST** of the HTML content
|
||||
on the [experimental web site](https://ioccc-src.github.io/temp-test-ioccc/).
|
||||
|
||||
... and in particular files under [inc](../inc/README.md) that are of the form (called default HTML files) ...:
|
||||
|
||||
```
|
||||
*.default.html
|
||||
```
|
||||
|
||||
... contain default content used to form IOCCC HTML / IOCCC web pages.
|
||||
|
||||
Instead of editing the default HTML files in order to fix a special web page,
|
||||
consider making a copy of the default file and modifying the [md2html config file](md2html.cfg) to refer to the copy instead. That way your special case situation will
|
||||
not impact **MOST** of the HTML content.
|
||||
|
||||
|
||||
## Why do we do not use certain well know HTML technology
|
||||
|
||||
You may wonder why we need these files in the first place.
|
||||
You may wonder why we even need the tools in the [bin](README.md) directory
|
||||
when there other solutions available to form web pages.
|
||||
|
||||
|
||||
### <a name="static-only"></a>Static web pages only
|
||||
|
||||
Here are some reasons why we are using these files and
|
||||
special tools to create HTML content / IOCCC web pages:
|
||||
|
||||
We host [official IOCCC web site](https://www.ioccc.org) via [GitHub pages](https://pages.github.com).
|
||||
As of the time this file written, **only static web pages are supported**.
|
||||
|
||||
|
||||
### Cannot use server side include
|
||||
|
||||
We use [static web pages](#static-only), so use of "server side include" is not available to the IOCCC.
|
||||
|
||||
For example, Apache SSI "#include" does not work on [GitHub pages](https://pages.github.com).
|
||||
|
||||
|
||||
### Cannot use a back-end database
|
||||
|
||||
We use [static web pages](#static-only), so use of "back-end database" is not available to the IOCCC.
|
||||
|
||||
|
||||
### <a name="why-github"></a>Cannot use non-GitHub web servers
|
||||
|
||||
The [GitHub pages](https://pages.github.com) have the distributed server capacity needed to handle
|
||||
the **huge download volume** or [Slashdot effect](https://en.wikipedia.org/wiki/Slashdot_effect)
|
||||
that happens when a IOCCC winners are published.
|
||||
|
||||
Most so-called low cost web hosting sites have a somewhat hidden excessive bandwidth charge
|
||||
and/or cap bandwidth when the volume gets too high, and/or do not have the infrastructure
|
||||
that can handle the [Slashdot effect](https://en.wikipedia.org/wiki/Slashdot_effect).
|
||||
|
||||
The IOCCC had experience with people offering web mirrors and even free hosting
|
||||
only to find that the generous benefactor moves on, or their service is purchased
|
||||
by someone else who is not so generous. While it is possible that GitHub might someday
|
||||
suffer a similar fate, for the time being we are betting that GitHub will remain
|
||||
willing to host the IOCCC.
|
||||
|
||||
The [official IOCCC web site](https://www.ioccc.org) is, after all, primarily C source code
|
||||
with some supporting documentation. As such it is a natural fit for GitHub and
|
||||
[GitHub pages](https://pages.github.com).
|
||||
|
||||
|
||||
### cannot use the HTML object tag
|
||||
|
||||
The _<_ object _>_ HTML tag does not work for our needs.
|
||||
|
||||
The browser context relationship between the HTML content holds the
|
||||
HTML tag does not extend into the content that the tag includes.
|
||||
For example, menu bars will not operate as specified by the [ioccc CSS](../ioccc.css).
|
||||
|
||||
|
||||
### cannot use the HTML embed tag
|
||||
|
||||
The _<_ embed _>_ HTML tag does not work for our needs.
|
||||
|
||||
This tag wants one to specify the _width_ and _height_ in pixels.
|
||||
Use of a percentage is not officially supported even if some browsers
|
||||
might do so. Our Responsive Web Design on the [ioccc CSS](../ioccc.css)
|
||||
needs to be responsive to small-sized cell phone-like screens,
|
||||
mid-sized table-like screens, as well as large-sized desktop-like screens.
|
||||
Specifying a _width_ and _height_ in pixels will not work well in
|
||||
all of those screen size contexts.
|
||||
|
||||
|
||||
### cannot use the HTML iframe tag
|
||||
|
||||
The _<_ iframe _>_ HTML tag does not work for our needs.
|
||||
|
||||
This tag wants one to specify the _width_ and _height_ in pixels.
|
||||
Use of a percentage is not officially supported even if some browsers
|
||||
might do so. Our Responsive Web Design on the [ioccc CSS](../ioccc.css)
|
||||
needs to be responsive to small-sized cell phone-like screens,
|
||||
mid-sized table-like screens, as well as large-sized desktop-like screens.
|
||||
Specifying a _width_ and _height_ in pixels will not work well in
|
||||
all of those screen size contexts.
|
||||
|
||||
|
||||
### cannot use JavaScript to include content
|
||||
|
||||
We do not use JavaScript to include HTML content.
|
||||
|
||||
While the IOCCC may use JavaScript in the future to directly render things like C source code,
|
||||
we will do so in such a way that someone will be able to view [official IOCCC web site](https://www.ioccc.org)
|
||||
content with JavaScript disabled.
|
||||
|
||||
The IOCCC will **NOT MANDATE USE OF JavaScript** to view [official IOCCC web site](https://www.ioccc.org).
|
||||
|
||||
For this reason, we cannot use JavaScript include HTML content.
|
||||
Executable
+783
@@ -0,0 +1,783 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# gen-author.sh - output winning author(s) related HTML
|
||||
#
|
||||
# This tool is intended to be used as a "before tool" during HTML phase number 20.
|
||||
#
|
||||
# This tool is intended to be invoked by a tool such as "readme2index.sh".
|
||||
# The final arg will be in yyyy/dir form, and will be called from
|
||||
# the topdir directory under which the yyyy/dir winner directory must be found.
|
||||
#
|
||||
# Copyright (c) 2023,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
|
||||
#
|
||||
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 . nor ..
|
||||
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 2024-01-14"
|
||||
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 200
|
||||
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 PANDOC_WRAPPER="bin/pandoc_wrapper.sh"
|
||||
export PANDOC_WRAPPER_OPTSTR="-f markdown -t html --fail-if-warnings=true"
|
||||
export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
||||
export TOP_URL="https://ioccc-src.github.io/temp-test-ioccc"
|
||||
export DOCROOT_URL_SLASH="../../"
|
||||
|
||||
# set usage message
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N]
|
||||
[-d topdir] [-p tool] [-P optstr]
|
||||
[-u repo_url] [-U top_url] [-e string ..] [-E exitcode]
|
||||
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)
|
||||
|
||||
-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 run 'pandoc wrapper tool' (not pandoc path) during HTML phase number 21 (def: use $PANDOC_WRAPPER)
|
||||
-P pandoc_opts run 'pandoc wrapper tool' with options found in 'optstr' (def: $PANDOC_WRAPPER_OPTSTR)
|
||||
NOTE: The 'optstr' may not contain a single-quote, nor a double-quote.
|
||||
|
||||
-u repo_url Base level URL of target git repo (def: $REPO_URL)
|
||||
-U top_url Top level URL of web site where HTML files will be viewed (def: $TOP_URL)
|
||||
|
||||
-e string output string, followed by newline, to stderr (def: do not)
|
||||
-E exitcode force exit with exitcode (def: exit based on success or failure of the action)
|
||||
|
||||
yyyy/dir path from topdir to winner directory: must contain the files: README.md, .path and .winner.json
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 pandoc exited non-zero
|
||||
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 winner directory
|
||||
6 pandoc tool not found or not executable
|
||||
>= 10 < 200 ((not used))
|
||||
>= 200 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
# setup
|
||||
#
|
||||
export NOOP=
|
||||
export DO_NOT_PROCESS=
|
||||
|
||||
# output_author_handles
|
||||
#
|
||||
# Write the author handle(s) for the yyyy/dir winner to standard output (stdout)
|
||||
#
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - until we have the jnamval command, we must FAKE PARSE the .winner.json file - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
#
|
||||
# usage:
|
||||
# output_author_handles yyyy/dir/.winner.json
|
||||
#
|
||||
# returns:
|
||||
# 0 ==> no errors detected, but output may be empty
|
||||
# > 0 ==> function error number
|
||||
#
|
||||
function output_author_handles
|
||||
{
|
||||
local WINNER_JSON_PATH; # the .winner.json path
|
||||
local author_handle; # a found author handle
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in output_author_handles: expected 1 arg, found $#" 1>&2
|
||||
return 1
|
||||
fi
|
||||
WINNER_JSON_PATH="$1"
|
||||
if [[ ! -e $WINNER_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_author_handles: .winner.json does not exist: $WINNER_JSON_PATH" 1>&2
|
||||
return 2
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_author_handles: .winner.json is not a file: $WINNER_JSON_PATH" 1>&2
|
||||
return 3
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_author_handles: .winner.json is not a readable file: $WINNER_JSON_PATH" 1>&2
|
||||
return 4
|
||||
fi
|
||||
|
||||
# extract author handles from .winner.json
|
||||
#
|
||||
grep -F author_handle "$WINNER_JSON_PATH" |
|
||||
awk 'NF == 5 { print $4; }' |
|
||||
tr -d '"' |
|
||||
while read -r author_handle; do
|
||||
echo "$author_handle"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# output_winner_ids
|
||||
#
|
||||
# Write the winner ids from an author/author_handle.json file to standard output (stdout)
|
||||
#
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - until we have the jnamval command, we must FAKE PARSE the author/author_handle.json file - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
#
|
||||
# usage:
|
||||
# output_winner_ids author/author_handle.json
|
||||
#
|
||||
# returns:
|
||||
# 0 ==> no errors detected, but output may be empty
|
||||
# > 0 ==> function error number
|
||||
#
|
||||
function output_winner_ids
|
||||
{
|
||||
local AUTHOR_HANDLE_JSON_PATH; # the .winner.json path
|
||||
local winner_id; # a found winner id
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in output_winner_ids: expected 1 arg, found $#" 1>&2
|
||||
return 1
|
||||
fi
|
||||
AUTHOR_HANDLE_JSON_PATH="$1"
|
||||
if [[ ! -e $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_winner_ids: author_handle.json does not exist: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 2
|
||||
fi
|
||||
if [[ ! -f $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_winner_ids: author_handle.json is not a file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 3
|
||||
fi
|
||||
if [[ ! -r $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_winner_ids: author_handle.json is not a readable file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 4
|
||||
fi
|
||||
|
||||
# extract winner ids from the author/author_handle.json file
|
||||
#
|
||||
grep -F winner_id "$AUTHOR_HANDLE_JSON_PATH" |
|
||||
awk 'NF == 5 { print $4; }' |
|
||||
tr -d '"' |
|
||||
while read -r winner_id; do
|
||||
echo "$winner_id"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# output_full_name
|
||||
#
|
||||
# Write the Full Name from an author/author_handle.json file to standard output (stdout)
|
||||
#
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - until we have the jnamval command, we must FAKE PARSE the author/author_handle.json file - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
#
|
||||
# usage:
|
||||
# output_full_name author/author_handle.json
|
||||
#
|
||||
# returns:
|
||||
# 0 ==> no errors detected, but output may be empty
|
||||
# > 0 ==> function error number
|
||||
#
|
||||
function output_full_name
|
||||
{
|
||||
local AUTHOR_HANDLE_JSON_PATH; # the .winner.json path
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in output_full_name: expected 1 arg, found $#" 1>&2
|
||||
return 1
|
||||
fi
|
||||
AUTHOR_HANDLE_JSON_PATH="$1"
|
||||
if [[ ! -e $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_full_name: author_handle.json does not exist: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 2
|
||||
fi
|
||||
if [[ ! -f $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_full_name: author_handle.json is not a file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 3
|
||||
fi
|
||||
if [[ ! -r $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_full_name: author_handle.json is not a readable file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 4
|
||||
fi
|
||||
|
||||
# extract Full Name from the author/author_handle.json file
|
||||
#
|
||||
grep -F full_name "$AUTHOR_HANDLE_JSON_PATH" | sed -e 's/.*"full_name" : "//' -e 's/",.*//'
|
||||
return 0
|
||||
}
|
||||
|
||||
# output_location_code
|
||||
#
|
||||
# Write the Location Code from an author/author_handle.json file to standard output (stdout)
|
||||
#
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - until we have the jnamval command, we must FAKE PARSE the author/author_handle.json file - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
#
|
||||
# usage:
|
||||
# output_location_code author/author_handle.json
|
||||
#
|
||||
# returns:
|
||||
# 0 ==> no errors detected, but output may be empty
|
||||
# > 0 ==> function error number
|
||||
#
|
||||
function output_location_code
|
||||
{
|
||||
local AUTHOR_HANDLE_JSON_PATH; # the .winner.json path
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in output_location_code: expected 1 arg, found $#" 1>&2
|
||||
return 1
|
||||
fi
|
||||
AUTHOR_HANDLE_JSON_PATH="$1"
|
||||
if [[ ! -e $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_location_code: author_handle.json does not exist: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 2
|
||||
fi
|
||||
if [[ ! -f $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_location_code: author_handle.json is not a file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 3
|
||||
fi
|
||||
if [[ ! -r $AUTHOR_HANDLE_JSON_PATH ]]; then
|
||||
echo "$0: ERROR: in output_location_code: author_handle.json is not a readable file: $AUTHOR_HANDLE_JSON_PATH" 1>&2
|
||||
return 4
|
||||
fi
|
||||
|
||||
# extract Location Code from the author/author_handle.json file
|
||||
#
|
||||
grep -F location_code "$AUTHOR_HANDLE_JSON_PATH" | sed -e 's/.*"location_code" : "*//' -e 's/"*,.*//'
|
||||
return 0
|
||||
}
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nNp:P:u:U:e:E: flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
n) NOOP="-n"
|
||||
;;
|
||||
N) DO_NOT_PROCESS="-N"
|
||||
;;
|
||||
p) PANDOC_WRAPPER="$OPTARG"
|
||||
;;
|
||||
P) # parse -P optstr
|
||||
case "$OPTARG" in
|
||||
*"'"*)
|
||||
echo "$0: ERROR: in -P optstr, the optstr may not contain a single-quote character: $OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*'"'*)
|
||||
echo "$0: ERROR: in -P optstr, the optstr may not contain a double-quote character: $OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
PANDOC_WRAPPER_OPTSTR="$OPTARG"
|
||||
;;
|
||||
u) REPO_URL="$OPTARG"
|
||||
;;
|
||||
U) TOP_URL="$OPTARG"
|
||||
;;
|
||||
e) echo "$OPTARG" 1>&2
|
||||
;;
|
||||
E) exit "$OPTARG"
|
||||
;;
|
||||
\?) 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 1 ]]; then
|
||||
echo "$0: debug[1]: 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 WINNER_PATH="$1"
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: WINNER_PATH=$WINNER_PATH" 1>&2
|
||||
fi
|
||||
|
||||
# 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 201
|
||||
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 202
|
||||
fi
|
||||
|
||||
# verify that we have an author subdirectory
|
||||
#
|
||||
export AUTHOR_PATH="$TOPDIR/author"
|
||||
if [[ ! -d $AUTHOR_PATH ]]; then
|
||||
echo "$0: ERROR: author is not a directory under topdir: $AUTHOR_PATH" 1>&2
|
||||
exit 203
|
||||
fi
|
||||
export AUTHOR_DIR="author"
|
||||
|
||||
# verify that we have an inc subdirectory
|
||||
#
|
||||
export INC_PATH="$TOPDIR/inc"
|
||||
if [[ ! -d $INC_PATH ]]; then
|
||||
echo "$0: ERROR: inc is not a directory under topdir: $INC_PATH" 1>&2
|
||||
exit 204
|
||||
fi
|
||||
export INC_DIR="inc"
|
||||
|
||||
# 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 205
|
||||
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 206
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 207
|
||||
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 208
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
# verify that WINNER_PATH is a winner directory
|
||||
#
|
||||
# WINNER_PATH must be in yyyy/dir form
|
||||
# yyyy must be a directory
|
||||
# yyyy must be a writable directory
|
||||
# yyyy/.year must be a non-empty file
|
||||
# yyyy/dir must be a directory
|
||||
# yyyy/dir/.path must be a non-empty file
|
||||
# WINNER_PATH must match the contents of yyyy/dir/.path
|
||||
# yyyy/dir/.winner.json must be a non-empty file
|
||||
#
|
||||
if [[ ! -d $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -w $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a writable directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export YEAR_DIR=${WINNER_PATH%%/*}
|
||||
if [[ -z $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: arg not in yyyy/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_DIR=${WINNER_PATH#*/}
|
||||
if [[ -z $WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH not in $YEAR_DIR/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ $WINNER_DIR = */* ]]; then
|
||||
echo "$0: ERROR: dir from arg: $WINNER_PATH contains a /: $WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy from arg: $WINNER_PATH is not a directory: $YEAR_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_ID="${YEAR_DIR}_${WINNER_DIR}"
|
||||
export DOT_YEAR="$YEAR_DIR/.year"
|
||||
if [[ ! -s $DOT_YEAR ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_YEAR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR/$WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy/dir from arg: $WINNER_PATH is not a directory: $YEAR_DIR/$WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export DOT_PATH="$YEAR_DIR/$WINNER_DIR/.path"
|
||||
if [[ ! -s $DOT_PATH ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
DOT_PATH_CONTENT=$(< "$DOT_PATH")
|
||||
if [[ $WINNER_PATH != "$DOT_PATH_CONTENT" ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH does not match $DOT_PATH contents: $DOT_PATH_CONTENT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_JSON="$YEAR_DIR/$WINNER_DIR/.winner.json"
|
||||
if [[ ! -e $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json does not exist: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a readable file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -e $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool does not exist: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -f $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool is not a file: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -x $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool is not an executable file: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
|
||||
# parameter debugging
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_DIR=$WINNER_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_ID=$WINNER_ID" 1>&2
|
||||
echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
|
||||
echo "$0: debug[3]: DOT_PATH=$DOT_PATH" 1>&2
|
||||
echo "$0: debug[3]: WINNER_JSON=$WINNER_JSON" 1>&2
|
||||
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
||||
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
||||
echo "$0: debug[3]: TOP_URL=$TOP_URL" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_PATH=$AUTHOR_PATH" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_DIR=$AUTHOR_DIR" 1>&2
|
||||
echo "$0: debug[3]: INC_PATH=$INC_PATH" 1>&2
|
||||
echo "$0: debug[3]: INC_DIR=$INC_DIR" 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]: PANDOC_WRAPPER=$PANDOC_WRAPPER" 1>&2
|
||||
echo "$0: debug[3]: PANDOC_WRAPPER_OPTSTR=$PANDOC_WRAPPER_OPTSTR" 1>&2
|
||||
echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
|
||||
echo "$0: debug[3]: NOOP=$NOOP" 1>&2
|
||||
fi
|
||||
|
||||
# Set AUTHOR_HANDLE_SET with author handles from .winner.json
|
||||
#
|
||||
export AUTHOR_HANDLE_SET
|
||||
AUTHOR_HANDLE_SET=$(output_author_handles "$WINNER_JSON")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $AUTHOR_HANDLE_SET ]]; then
|
||||
echo "$0: ERROR: unable to obtain any author handles from: $WINNER_JSON" 1>&2
|
||||
exit 209
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: author handles found in $WINNER_JSON start below" 1>&2
|
||||
echo "$AUTHOR_HANDLE_SET" 1>&2
|
||||
echo "$0: debug[3]: author handles found in $WINNER_JSON end above" 1>&2
|
||||
fi
|
||||
|
||||
# verify each author handle has a readable /author/author_handle.json file
|
||||
#
|
||||
for author_handle in $AUTHOR_HANDLE_SET; do
|
||||
|
||||
# determine the author handle JSON path
|
||||
#
|
||||
AUTHOR_HANDLE_JSON="$AUTHOR_DIR/$author_handle.json"
|
||||
|
||||
# verify that /author/author_handle.json exists as a readable file
|
||||
#
|
||||
if [[ ! -e $AUTHOR_HANDLE_JSON ]]; then
|
||||
echo "$0: ERROR: for author handle: $author_handle author JSON file not found: $AUTHOR_HANDLE_JSON" 1>&2
|
||||
exit 210
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: for author handle: $author_handle author JSON is not a file: $AUTHOR_HANDLE_JSON" 1>&2
|
||||
exit 211
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: for author handle: $author_handle author JSON is not a readable file: $AUTHOR_HANDLE_JSON" 1>&2
|
||||
exit 212
|
||||
fi
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: for author handle: $author_handle found a readable author JSON file: $AUTHOR_HANDLE_JSON" 1>&2
|
||||
fi
|
||||
|
||||
# verify that the /author/author_handle.json file lists the WINNER_ID as one of their wins
|
||||
#
|
||||
WINNER_ID_FOUND=$(output_winner_ids "$AUTHOR_HANDLE_JSON" | grep -F -- "$WINNER_ID")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $WINNER_ID_FOUND ]]; then
|
||||
echo "$0: ERROR: winner id: $WINNER_ID not found in author JSON file: $AUTHOR_HANDLE_JSON, status: $status" 1>&2
|
||||
exit 213
|
||||
fi
|
||||
if [[ $V_FLAG -ge 7 ]]; then
|
||||
echo "$0: debug[7]: readable author JSON file: $AUTHOR_HANDLE_JSON mentions winner id: $WINNER_ID" 1>&2
|
||||
fi
|
||||
|
||||
# verify that we have a Full Name in the /author/author_handle.json file
|
||||
#
|
||||
FULL_NAME=$(output_full_name "$AUTHOR_HANDLE_JSON")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $FULL_NAME ]]; then
|
||||
echo "$0: ERROR: author JSON file: $AUTHOR_HANDLE_JSON as no FULL NAME, status: $status" 1>&2
|
||||
exit 214
|
||||
fi
|
||||
if [[ $V_FLAG -ge 7 ]]; then
|
||||
echo "$0: debug[7]: author JSON file: $AUTHOR_HANDLE_JSON Full Name: $FULL_NAME" 1>&2
|
||||
fi
|
||||
|
||||
# verify that we have a Location Code in the /author/author_handle.json file
|
||||
#
|
||||
LOCATION_CODE=$(output_location_code "$AUTHOR_HANDLE_JSON")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $LOCATION_CODE ]]; then
|
||||
echo "$0: ERROR: author JSON file: $AUTHOR_HANDLE_JSON as no Location Code, status: $status" 1>&2
|
||||
exit 215
|
||||
fi
|
||||
if [[ $V_FLAG -ge 7 ]]; then
|
||||
echo "$0: debug[7]: author JSON file: $AUTHOR_HANDLE_JSON Location Code: $LOCATION_CODE" 1>&2
|
||||
fi
|
||||
done
|
||||
|
||||
# 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 markdown for pandoc to process
|
||||
#
|
||||
TMP_FILE=".$NAME.$$.md"
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: temporary markdown file: $TMP_FILE" 1>&2
|
||||
fi
|
||||
if [[ -z $NOOP ]]; then
|
||||
trap 'rm -f $TMP_FILE; exit' 0 1 2 3 15
|
||||
rm -f "$TMP_FILE"
|
||||
if [[ -e $TMP_FILE ]]; then
|
||||
echo "$0: ERROR: cannot remove temporary markdown file: $TMP_FILE" 1>&2
|
||||
exit 216
|
||||
fi
|
||||
:> "$TMP_FILE"
|
||||
if [[ ! -e $TMP_FILE ]]; then
|
||||
echo "$0: ERROR: cannot create temporary markdown file: $TMP_FILE" 1>&2
|
||||
exit 217
|
||||
fi
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: because of -n, temporary markdown file is not used: $TMP_FILE" 1>&2
|
||||
fi
|
||||
|
||||
# write author header to temporary markdown file
|
||||
#
|
||||
{
|
||||
AUTHOR_COUNT=$(echo "$AUTHOR_HANDLE_SET" | wc -l)
|
||||
if [[ $AUTHOR_COUNT -gt 1 ]]; then
|
||||
echo '<a name="author">**Authors:**</a>'
|
||||
else
|
||||
echo '<a name="author">**Author:**</a>'
|
||||
fi
|
||||
echo
|
||||
} | if [[ -z $NOOP ]]; then
|
||||
cat >> "$TMP_FILE"
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
sed -e "s;^;$0: debug[3]: -n disabled write: ;" 1>&2
|
||||
else
|
||||
cat >> /dev/null
|
||||
fi
|
||||
|
||||
# write each author's information to temporary markdown file
|
||||
#
|
||||
for author_handle in $AUTHOR_HANDLE_SET; do
|
||||
|
||||
# determine the author handle JSON path
|
||||
#
|
||||
AUTHOR_HANDLE_JSON="$AUTHOR_DIR/$author_handle.json"
|
||||
|
||||
# obtain the Full Name from the author handle JSON file
|
||||
#
|
||||
FULL_NAME=$(output_full_name "$AUTHOR_HANDLE_JSON")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $FULL_NAME ]]; then
|
||||
echo "$0: ERROR: author JSON file: $AUTHOR_HANDLE_JSON as no FULL NAME, status: $status" 1>&2
|
||||
exit 218
|
||||
fi
|
||||
|
||||
# obtain the Location Code from the author handle JSON file
|
||||
#
|
||||
LOCATION_CODE=$(output_location_code "$AUTHOR_HANDLE_JSON")
|
||||
status="$?"
|
||||
if [[ $status -ne 0 || -z $LOCATION_CODE ]]; then
|
||||
echo "$0: ERROR: author JSON file: $AUTHOR_HANDLE_JSON as no Location Code, status: $status" 1>&2
|
||||
exit 219
|
||||
fi
|
||||
|
||||
# write this author's information
|
||||
#
|
||||
{
|
||||
echo "Name: [$FULL_NAME](${DOCROOT_URL_SLASH}winners.html#$author_handle)<br>"
|
||||
if [[ $LOCATION_CODE == null ]]; then
|
||||
echo "Location: [unknown](${DOCROOT_URL_SLASH}location.html#$LOCATION_CODE)"
|
||||
else
|
||||
|
||||
echo "Location: [$LOCATION_CODE](${DOCROOT_URL_SLASH}location.html#$LOCATION_CODE)"
|
||||
fi
|
||||
echo
|
||||
} | if [[ -z $NOOP ]]; then
|
||||
cat >> "$TMP_FILE"
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
sed -e "s;^;$0: debug[3]: -n disabled write: ;" 1>&2
|
||||
else
|
||||
cat >> /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
# convert temporary markdown file into HTML
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
echo "<!-- START: this line starts content generated by: bin/$NAME -->"
|
||||
echo
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: about to execute: $PANDOC_WRAPPER -P \"$PANDOC_WRAPPER_OPTSTR\" $TMP_FILE -" 1>&2
|
||||
fi
|
||||
"$PANDOC_WRAPPER" -P "$PANDOC_WRAPPER_OPTSTR" "$TMP_FILE" -
|
||||
status="$?"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$0: ERROR: pandoc failed, error: $status" 1>&2
|
||||
exit 220
|
||||
fi
|
||||
echo
|
||||
echo "<!-- END: next line ends content generated by: bin/$NAME -->"
|
||||
elif [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: -n disabled execution of: $PANDOC_WRAPPER -P \"$PANDOC_WRAPPER_OPTSTR\" $TMP_FILE -" 1>&2
|
||||
fi
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
rm -f "$TMP_FILE"
|
||||
elif [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: -n disabled execution of: rm -f $TMP_FILE" 1>&2
|
||||
fi
|
||||
exit 0
|
||||
Executable
+510
@@ -0,0 +1,510 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# gen-inventory.sh - output the inventory in HTML form for a winner index.html page
|
||||
#
|
||||
# This tool is intended to be used as a "before tool" during HTML phase number 22.
|
||||
#
|
||||
# This tool is intended to be invoked by a tool such as "readme2index.sh".
|
||||
# The final arg will be in yyyy/dir form, and will be called from
|
||||
# the topdir directory under which the yyyy/dir winner directory must be found.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
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 . nor ..
|
||||
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-01-14"
|
||||
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 200
|
||||
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 PANDOC_WRAPPER="bin/pandoc_wrapper.sh"
|
||||
export PANDOC_WRAPPER_OPTSTR="-f markdown -t html --fail-if-warnings=true"
|
||||
export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
||||
export TOP_URL="https://ioccc-src.github.io/temp-test-ioccc"
|
||||
|
||||
# set usage message
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N]
|
||||
[-d topdir] [-p tool] [-P optstr]
|
||||
[-u repo_url] [-U top_url] [-e string ..] [-E exitcode]
|
||||
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)
|
||||
|
||||
-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 run 'pandoc wrapper tool' (not pandoc path) during HTML phase number 21 (def: use $PANDOC_WRAPPER)
|
||||
-P pandoc_opts run 'pandoc wrapper tool' with options found in 'optstr' (def: $PANDOC_WRAPPER_OPTSTR)
|
||||
NOTE: The 'optstr' may not contain a single-quote, nor a double-quote.
|
||||
|
||||
-u repo_url Base level URL of target git repo (def: $REPO_URL)
|
||||
-U top_url Top level URL of web site where HTML files will be viewed (def: $TOP_URL)
|
||||
|
||||
-e string output string, followed by newline, to stderr (def: do not)
|
||||
-E exitcode force exit with exitcode (def: exit based on success or failure of the action)
|
||||
|
||||
yyyy/dir path from topdir to winner directory: must contain the files: README.md, .path and .winner.json
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 pandoc exited non-zero
|
||||
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 winner directory
|
||||
6 pandoc tool not found or not executable
|
||||
>= 10 < 200 ((not used))
|
||||
>= 200 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
# setup
|
||||
#
|
||||
export NOOP=
|
||||
export DO_NOT_PROCESS=
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nNp:P:u:U:e:E: flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
n) NOOP="-n"
|
||||
;;
|
||||
N) DO_NOT_PROCESS="-N"
|
||||
;;
|
||||
p) PANDOC_WRAPPER="$OPTARG"
|
||||
;;
|
||||
P) # parse -P optstr
|
||||
case "$OPTARG" in
|
||||
*"'"*)
|
||||
echo "$0: ERROR: in -P optstr, the optstr may not contain a single-quote character: $OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*'"'*)
|
||||
echo "$0: ERROR: in -P optstr, the optstr may not contain a double-quote character: $OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
PANDOC_WRAPPER_OPTSTR="$OPTARG"
|
||||
;;
|
||||
u) REPO_URL="$OPTARG"
|
||||
;;
|
||||
U) TOP_URL="$OPTARG"
|
||||
;;
|
||||
e) echo "$OPTARG" 1>&2
|
||||
;;
|
||||
E) exit "$OPTARG"
|
||||
;;
|
||||
\?) 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 1 ]]; then
|
||||
echo "$0: debug[1]: 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 WINNER_PATH="$1"
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: WINNER_PATH=$WINNER_PATH" 1>&2
|
||||
fi
|
||||
|
||||
# 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 201
|
||||
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 202
|
||||
fi
|
||||
|
||||
# verify that we have an author subdirectory
|
||||
#
|
||||
export AUTHOR_PATH="$TOPDIR/author"
|
||||
if [[ ! -d $AUTHOR_PATH ]]; then
|
||||
echo "$0: ERROR: author is not a directory under topdir: $AUTHOR_PATH" 1>&2
|
||||
exit 203
|
||||
fi
|
||||
export AUTHOR_DIR="author"
|
||||
|
||||
# verify that we have an inc subdirectory
|
||||
#
|
||||
export INC_PATH="$TOPDIR/inc"
|
||||
if [[ ! -d $INC_PATH ]]; then
|
||||
echo "$0: ERROR: inc is not a directory under topdir: $INC_PATH" 1>&2
|
||||
exit 204
|
||||
fi
|
||||
export INC_DIR="inc"
|
||||
|
||||
# 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 205
|
||||
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 206
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 207
|
||||
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 208
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
# verify that WINNER_PATH is a winner directory
|
||||
#
|
||||
# WINNER_PATH must be in yyyy/dir form
|
||||
# yyyy must be a directory
|
||||
# yyyy must be a writable directory
|
||||
# yyyy/.year must be a non-empty file
|
||||
# yyyy/dir must be a directory
|
||||
# yyyy/dir/.path must be a non-empty file
|
||||
# WINNER_PATH must match the contents of yyyy/dir/.path
|
||||
# yyyy/dir/.winner.json must be a non-empty file
|
||||
#
|
||||
if [[ ! -d $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -w $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a writable directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export YEAR_DIR=${WINNER_PATH%%/*}
|
||||
if [[ -z $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: arg not in yyyy/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_DIR=${WINNER_PATH#*/}
|
||||
if [[ -z $WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH not in $YEAR_DIR/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ $WINNER_DIR = */* ]]; then
|
||||
echo "$0: ERROR: dir from arg: $WINNER_PATH contains a /: $WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy from arg: $WINNER_PATH is not a directory: $YEAR_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_ID="${YEAR_DIR}_${WINNER_DIR}"
|
||||
export DOT_YEAR="$YEAR_DIR/.year"
|
||||
if [[ ! -s $DOT_YEAR ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_YEAR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR/$WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy/dir from arg: $WINNER_PATH is not a directory: $YEAR_DIR/$WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export DOT_PATH="$YEAR_DIR/$WINNER_DIR/.path"
|
||||
if [[ ! -s $DOT_PATH ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
DOT_PATH_CONTENT=$(< "$DOT_PATH")
|
||||
if [[ $WINNER_PATH != "$DOT_PATH_CONTENT" ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH does not match $DOT_PATH contents: $DOT_PATH_CONTENT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_JSON="$YEAR_DIR/$WINNER_DIR/.winner.json"
|
||||
if [[ ! -e $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json does not exist: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a readable file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -e $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool does not exist: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -f $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool is not a file: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -x $PANDOC_WRAPPER ]]; then
|
||||
echo "$0: ERROR: pandoc wrapper tool is not an executable file: $PANDOC_WRAPPER" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
|
||||
# verify we have our awk script
|
||||
#
|
||||
export MANIFEST_WINNER_JSON_AWK="$BIN_DIR/manifest.winner.json.awk"
|
||||
if [[ ! -e $MANIFEST_WINNER_JSON_AWK ]]; then
|
||||
echo "$0: ERROR: bin/manifest.winner.json.awk does not exist: $MANIFEST_WINNER_JSON_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -f $MANIFEST_WINNER_JSON_AWK ]]; then
|
||||
echo "$0: ERROR: bin/manifest.winner.json.awk is not a file: $MANIFEST_WINNER_JSON_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -r $MANIFEST_WINNER_JSON_AWK ]]; then
|
||||
echo "$0: ERROR: bin/manifest.winner.json.awk is not a readable file: $MANIFEST_WINNER_JSON_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
|
||||
# parameter debugging
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_DIR=$WINNER_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_ID=$WINNER_ID" 1>&2
|
||||
echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
|
||||
echo "$0: debug[3]: DOT_PATH=$DOT_PATH" 1>&2
|
||||
echo "$0: debug[3]: WINNER_JSON=$WINNER_JSON" 1>&2
|
||||
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
||||
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
||||
echo "$0: debug[3]: TOP_URL=$TOP_URL" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_PATH=$AUTHOR_PATH" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_DIR=$AUTHOR_DIR" 1>&2
|
||||
echo "$0: debug[3]: INC_PATH=$INC_PATH" 1>&2
|
||||
echo "$0: debug[3]: INC_DIR=$INC_DIR" 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]: PANDOC_WRAPPER=$PANDOC_WRAPPER" 1>&2
|
||||
echo "$0: debug[3]: PANDOC_WRAPPER_OPTSTR=$PANDOC_WRAPPER_OPTSTR" 1>&2
|
||||
echo "$0: debug[3]: MANIFEST_WINNER_JSON_AWK=$MANIFEST_WINNER_JSON_AWK" 1>&2
|
||||
echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
|
||||
echo "$0: debug[3]: NOOP=$NOOP" 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 markdown for pandoc to process
|
||||
#
|
||||
TMP_FILE=".$NAME.$$.md"
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: temporary markdown file: $TMP_FILE" 1>&2
|
||||
fi
|
||||
if [[ -z $NOOP ]]; then
|
||||
trap 'rm -f $TMP_FILE; exit' 0 1 2 3 15
|
||||
rm -f "$TMP_FILE"
|
||||
if [[ -e $TMP_FILE ]]; then
|
||||
echo "$0: ERROR: cannot remove temporary markdown file: $TMP_FILE" 1>&2
|
||||
exit 209
|
||||
fi
|
||||
:> "$TMP_FILE"
|
||||
if [[ ! -e $TMP_FILE ]]; then
|
||||
echo "$0: ERROR: cannot create temporary markdown file: $TMP_FILE" 1>&2
|
||||
exit 210
|
||||
fi
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: because of -n, temporary markdown file is not used: $TMP_FILE" 1>&2
|
||||
fi
|
||||
|
||||
# create a temporary manifest file
|
||||
#
|
||||
TMP_MANIFEST=".$NAME.$$.manifest"
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: temporary manifest file: $TMP_MANIFEST" 1>&2
|
||||
fi
|
||||
if [[ -z $NOOP ]]; then
|
||||
trap 'rm -f $TMP_FILE $TMP_MANIFEST; exit' 0 1 2 3 15
|
||||
rm -f "$TMP_MANIFEST"
|
||||
if [[ -e $TMP_MANIFEST ]]; then
|
||||
echo "$0: ERROR: cannot remove temporary manifest file: $TMP_MANIFEST" 1>&2
|
||||
exit 211
|
||||
fi
|
||||
:> "$TMP_MANIFEST"
|
||||
if [[ ! -e $TMP_MANIFEST ]]; then
|
||||
echo "$0: ERROR: cannot create temporary manifest file: $TMP_MANIFEST" 1>&2
|
||||
exit 212
|
||||
fi
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: because of -n, temporary manifest file is not used: $TMP_MANIFEST" 1>&2
|
||||
fi
|
||||
|
||||
# generate the temporary manifest file
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
awk -v github="$REPO_URL" -f "$MANIFEST_WINNER_JSON_AWK" "$WINNER_JSON" > "$TMP_MANIFEST"
|
||||
status="$?"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$0: ERROR: manifest.winner.json.awk failed, error: $status" 1>&2
|
||||
exit 213
|
||||
fi
|
||||
|
||||
# load numerically sorted winners_rank lines into the temporary markdown file
|
||||
#
|
||||
# Any winners_rank that is 1 to 9 decimal digits is considered a primary file.
|
||||
# Any winners_rank that is 10 or more decimal digits is considered a secondary file.
|
||||
#
|
||||
{
|
||||
echo '# <a name="inventory"></a>Inventory for' "$YEAR_DIR/$WINNER_DIR"
|
||||
echo
|
||||
echo '## Primary files'
|
||||
echo
|
||||
grep -E '^[0-9][0-9]{0,8} ' "$TMP_MANIFEST" | sort -n | sed -e 's/^[0-9][0-9]* //'
|
||||
echo
|
||||
echo '## Secondary files'
|
||||
echo
|
||||
grep -E '^[1-9][0-9]{9,} ' "$TMP_MANIFEST" | sort -n | sed -e 's/^[0-9][0-9]* //'
|
||||
} > "$TMP_FILE"
|
||||
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: because of -n, temporary manifest file is NOT written into: $TMP_MANIFEST" 1>&2
|
||||
fi
|
||||
|
||||
# convert temporary markdown file into HTML
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
echo "<!-- START: this line starts content generated by: bin/$NAME -->"
|
||||
echo
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: about to execute: $PANDOC_WRAPPER -P \"$PANDOC_WRAPPER_OPTSTR\" $TMP_FILE -" 1>&2
|
||||
fi
|
||||
"$PANDOC_WRAPPER" -P "$PANDOC_WRAPPER_OPTSTR" "$TMP_FILE" -
|
||||
status="$?"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$0: ERROR: pandoc failed, error: $status" 1>&2
|
||||
exit 213
|
||||
fi
|
||||
echo
|
||||
echo "<!-- END: next line ends content generated by: bin/$NAME -->"
|
||||
elif [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: -n disabled execution of: $PANDOC_WRAPPER -P \"$PANDOC_WRAPPER_OPTSTR\" $TMP_FILE -" 1>&2
|
||||
fi
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
rm -f "$TMP_FILE" "$TMP_MANIFEST"
|
||||
elif [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: -n disabled execution of: rm -f $TMP_FILE $TMP_MANIFEST" 1>&2
|
||||
fi
|
||||
exit 0
|
||||
Executable
+432
@@ -0,0 +1,432 @@
|
||||
#!/usr/bin/env awk
|
||||
#
|
||||
# manifest.winner.json.awk - output manifest table from a winner .winner.json file
|
||||
#
|
||||
# usage:
|
||||
#
|
||||
# awk -v github=REPO_URL -f bin/manifest.winner.json.awk YYYY/dir/.winner.json
|
||||
#
|
||||
# where:
|
||||
#
|
||||
# YYYY IOCCC year or mock
|
||||
# dir name of winner directory under YYYY containing .winner.json
|
||||
# REPO_URL GitHub repo URL, e.g., https://github.com/ioccc-src/winner
|
||||
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - until we have the jnamval command, we must FAKE PARSE the .winner.json file - XXX
|
||||
# XXX - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - GROSS HACK - XXX
|
||||
# XXX - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - XXX
|
||||
|
||||
BEGIN {
|
||||
|
||||
# setup
|
||||
#
|
||||
VERSION="1.0 2024-01-14"
|
||||
found_manifest_array = 0; # 1 ==> we found the manifest ARRAY
|
||||
within_manifest_array = 0; # 1 ==> found start of "manifest" : [ JSON array
|
||||
begin_manifest_element = 0; # 1 ==> we have found the start of the manifest array element
|
||||
|
||||
# error if github is not set via -v github=REPO_URL
|
||||
#
|
||||
if (length(github) == 0) {
|
||||
exit 200; # END section will output ERROR message about github not set
|
||||
}
|
||||
|
||||
# extract YYYY and dir from file argument
|
||||
#
|
||||
yyyy = "";
|
||||
dir = "";
|
||||
tmp = ARGV[1];
|
||||
gsub(/\.winner\.json$/, "", tmp);
|
||||
arg_path_count = split(tmp, part, "/");
|
||||
if (arg_path_count >= 2) {
|
||||
dir=part[arg_path_count-1];
|
||||
yyyy=part[arg_path_count-2];
|
||||
}
|
||||
if (length(dir) == 0) {
|
||||
exit 201; # END section will output ERROR message about cannot find dir
|
||||
}
|
||||
if (length(yyyy) == 0) {
|
||||
exit 202; # END section will output ERROR message about cannot find yyyy
|
||||
}
|
||||
}
|
||||
|
||||
# look for the start of "manifest" JSON array
|
||||
#
|
||||
# We look for a line with 3 tokens:
|
||||
#
|
||||
# "manifest" : [
|
||||
#
|
||||
NF == 3 && $1 ~ /^"manifest"$/ && $2 ~ /^:$/ && $3 ~ /^\[$/ {
|
||||
|
||||
# note we have found the start of "manifest" JSON array
|
||||
#
|
||||
found_manifest_array = 1;
|
||||
within_manifest_array = 1;
|
||||
begin_manifest_element = 0;
|
||||
}
|
||||
|
||||
# after start of "manifest" JSON array, process start of a manifest array element
|
||||
#
|
||||
# We have just seen the start of "manifest" JSON array:
|
||||
#
|
||||
# "manifest" : [
|
||||
#
|
||||
# Now, when we see a line of this form:
|
||||
#
|
||||
# {
|
||||
#
|
||||
# we know that we are about to see the start of one of the manifest array elements.
|
||||
#
|
||||
within_manifest_array == 1 && NF == 1 && $1 ~ /^{$/ {
|
||||
|
||||
# note the start of the manifest array element
|
||||
#
|
||||
begin_manifest_element = 1;
|
||||
|
||||
# clear values for the JSON members of this manifest array elements
|
||||
#
|
||||
file_path = "";
|
||||
inventory_order = "";
|
||||
OK_to_edit = "";
|
||||
display_as = "";
|
||||
display_via_github = "";
|
||||
winners_text = "";
|
||||
|
||||
# clear unquoted values for the JSON members of this manifest array elements
|
||||
#
|
||||
unquote_file_path = "";
|
||||
unquote_inventory_order = "";
|
||||
unquote_OK_to_edit = "";
|
||||
unquote_display_as = "";
|
||||
unquote_display_via_github = "";
|
||||
unquote_winners_text = "";
|
||||
}
|
||||
|
||||
# record file_path from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "file_path" : something,
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"file_path"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
file_path = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (file_path ~ /,$/) {
|
||||
file_path = substr(file_path, 1, length(file_path)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (file_path ~ /^".*"$/) {
|
||||
unquote_file_path = substr(file_path, 2, length(file_path)-2);
|
||||
} else {
|
||||
unquote_file_path = file_path;
|
||||
}
|
||||
}
|
||||
|
||||
# record inventory_order from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "inventory_order" : something,
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"inventory_order"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
inventory_order = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (inventory_order ~ /,$/) {
|
||||
inventory_order = substr(inventory_order, 1, length(inventory_order)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (inventory_order ~ /^".*"$/) {
|
||||
unquote_inventory_order = substr(inventory_order, 2, length(inventory_order)-2);
|
||||
} else {
|
||||
unquote_inventory_order = inventory_order;
|
||||
}
|
||||
}
|
||||
|
||||
# record OK_to_edit from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "OK_to_edit" : something,
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"OK_to_edit"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
OK_to_edit = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (OK_to_edit ~ /,$/) {
|
||||
OK_to_edit = substr(OK_to_edit, 1, length(OK_to_edit)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (OK_to_edit ~ /^".*"$/) {
|
||||
unquote_OK_to_edit = substr(OK_to_edit, 2, length(OK_to_edit)-2);
|
||||
} else {
|
||||
unquote_OK_to_edit = OK_to_edit;
|
||||
}
|
||||
}
|
||||
|
||||
# record display_as from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "display_as" : something,
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"display_as"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
display_as = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (display_as ~ /,$/) {
|
||||
display_as = substr(display_as, 1, length(display_as)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (display_as ~ /^".*"$/) {
|
||||
unquote_display_as = substr(display_as, 2, length(display_as)-2);
|
||||
} else {
|
||||
unquote_display_as = display_as;
|
||||
}
|
||||
}
|
||||
|
||||
# record display_via_github from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "display_via_github" : something,
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"display_via_github"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
display_via_github = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (display_via_github ~ /,$/) {
|
||||
display_via_github = substr(display_via_github, 1, length(display_via_github)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (display_via_github ~ /^".*"$/) {
|
||||
unquote_display_via_github = substr(display_via_github, 2, length(display_via_github)-2);
|
||||
} else {
|
||||
unquote_display_via_github = display_via_github;
|
||||
}
|
||||
}
|
||||
|
||||
# record winners_text from an manifest array element
|
||||
#
|
||||
# We are looking for a JSON member line of the form:
|
||||
#
|
||||
# "winners_text" : something
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF >= 3 && $1 ~ /^"winners_text"$/ && $2 ~ /^:$/ {
|
||||
|
||||
# save JSON member value
|
||||
#
|
||||
# The JSON member value starts after the 1st and 2nd fields.
|
||||
# We remove any leading leading whitespace, such as the FS
|
||||
# between the 1st and 2nd fields, and between the 2nd and 3rd field.
|
||||
#
|
||||
$1 = ""; # remove 1st field
|
||||
$2 = ""; # remove 2nd field
|
||||
gsub(/^[[:space:]]+/, "", $0); # any leading whitespace
|
||||
winners_text = $0;
|
||||
|
||||
# Remove any trailing ,
|
||||
#
|
||||
if (winners_text ~ /,$/) {
|
||||
winners_text = substr(winners_text, 1, length(winners_text)-1);
|
||||
}
|
||||
|
||||
# remove any enclosing double quotes
|
||||
#
|
||||
if (winners_text ~ /^".*"$/) {
|
||||
unquote_winners_text = substr(winners_text, 2, length(winners_text)-2);
|
||||
} else {
|
||||
unquote_winners_text = winners_text;
|
||||
}
|
||||
}
|
||||
|
||||
# process end of manifest array element
|
||||
#
|
||||
within_manifest_array == 1 && begin_manifest_element == 1 && NF == 1 && $1 ~ /^},?$/ {
|
||||
|
||||
# verify we have seen a file_path JSON member
|
||||
#
|
||||
if (length(file_path) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a file_path JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 203;
|
||||
}
|
||||
|
||||
# verify we have seen a inventory_order JSON member
|
||||
#
|
||||
if (length(inventory_order) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a inventory_order JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 204;
|
||||
}
|
||||
|
||||
# verify we have seen a OK_to_edit JSON member
|
||||
#
|
||||
if (length(OK_to_edit) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a OK_to_edit JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 206;
|
||||
}
|
||||
|
||||
# verify we have seen a display_as JSON member
|
||||
#
|
||||
if (length(display_as) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a display_as JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 207;
|
||||
}
|
||||
|
||||
# verify we have seen a display_via_github JSON member
|
||||
#
|
||||
if (length(display_via_github) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a display_via_github JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 209;
|
||||
}
|
||||
|
||||
# verify we have seen a winners_text JSON member
|
||||
#
|
||||
if (length(winners_text) == 0) {
|
||||
print "ERROR: manifest array JSON member did not have a winners_text JSON member in:", ARGV[1] > "/dev/stderr";
|
||||
exit 210;
|
||||
}
|
||||
|
||||
# print manifest information
|
||||
#
|
||||
# print "# debug: file_path:", file_path;
|
||||
# print "# debug: inventory_order:", inventory_order;
|
||||
# print "# debug: OK_to_edit:", OK_to_edit;
|
||||
# print "# debug: display_as:", display_as;
|
||||
# print "# debug: display_via_github:", display_via_github;
|
||||
# print "# debug: winners_text:", winners_text;
|
||||
#
|
||||
# print "# debug: unquote_file_path:", unquote_file_path;
|
||||
# print "# debug: unquote_inventory_order:", unquote_inventory_order;
|
||||
# print "# debug: unquote_OK_to_edit:", unquote_OK_to_edit;
|
||||
# print "# debug: unquote_display_as:", unquote_display_as;
|
||||
# print "# debug: unquote_display_via_github:", unquote_display_via_github;
|
||||
# print "# debug: unquote_winners_text:", unquote_winners_text;
|
||||
#
|
||||
if (unquote_display_via_github == "false") {
|
||||
url = unquote_file_path;
|
||||
} else {
|
||||
url = github "/blob/master/" yyyy "/" dir "/" unquote_file_path;
|
||||
}
|
||||
print inventory_order, "* [" unquote_file_path "](" url ") -", unquote_winners_text;
|
||||
|
||||
# note the end of the manifest array element
|
||||
#
|
||||
begin_manifest_element = 0;
|
||||
|
||||
# note if we found the end of the manifest array
|
||||
#
|
||||
if ($1 ~ /^}$/) {
|
||||
within_manifest_array = 0;
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
|
||||
# case: we quit due to github unset
|
||||
#
|
||||
if (length(github) == 0) {
|
||||
print "ERROR: github variable not set, call with -v github=REPO_URL" > "/dev/stderr";
|
||||
exit 200; # use 200 to match exit code from BEGIN
|
||||
}
|
||||
|
||||
# case: we quit because we could not determine dir from ARGV[1]
|
||||
#
|
||||
if (length(dir) == 0) {
|
||||
print "ERROR: cannot determine dir from:", ARGV[1] > "/dev/stderr";
|
||||
exit 201; # END section will output ERROR message about cannot find dir
|
||||
}
|
||||
|
||||
if (length(yyyy) == 0) {
|
||||
print "ERROR: cannot determine yyyy from:", ARGV[1] > "/dev/stderr";
|
||||
exit 202; # END section will output ERROR message about cannot find yyyy
|
||||
}
|
||||
|
||||
# case: no manifest array was found
|
||||
#
|
||||
if (!found_manifest_array) {
|
||||
print "ERROR: we did not find a manifest JSON array in:", ARGV[1] > "/dev/stderr";
|
||||
exit 211;
|
||||
}
|
||||
|
||||
# case: manifest array was found, but manifest array element did not finish
|
||||
#
|
||||
if (begin_manifest_element) {
|
||||
print "ERROR: manifest JSON array element did not end in:", ARGV[1] > "/dev/stderr";
|
||||
exit 212;
|
||||
}
|
||||
|
||||
# case: manifest array did not end
|
||||
#
|
||||
if (within_manifest_array) {
|
||||
print "ERROR: manifest JSON array did not end in:", ARGV[1] > "/dev/stderr";
|
||||
exit 213;
|
||||
}
|
||||
}
|
||||
Executable
+341
@@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# pandoc_wrapper.sh - wrapper tool to run pandoc
|
||||
#
|
||||
# This tool is intended to be used as a 'pandoc wrapper tool' during HTML phase number 21.
|
||||
#
|
||||
# This tool is intended to be invoked by a tool such as 'readme2index.sh"
|
||||
# and as such, the leading options will include "-p pandoc_wrapper" and -P "optstr",
|
||||
# the final arg will be in yyyy/dir form, and will be called from
|
||||
# the topdir directory under which the yyyy/dir winner directory must be found.
|
||||
#
|
||||
# Copyright (c) 2023,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
|
||||
#
|
||||
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 . nor ..
|
||||
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 2024-01-14"
|
||||
NAME=$(basename "$0")
|
||||
export NAME
|
||||
export V_FLAG=0
|
||||
export PANDOC_TOOL
|
||||
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 200
|
||||
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
|
||||
PANDOC_TOOL=$(type -P pandoc)
|
||||
if [[ -z $PANDOC_TOOL ]]; then
|
||||
PANDOC_TOOL="/opt/homebrew/bin/pandoc"
|
||||
fi
|
||||
export PANDOC_ARGS="-f markdown -t html --fail-if-warnings=true"
|
||||
export PANDOC_WRAPPER="bin/pandoc_wapper.sh"
|
||||
export PANDOC_WRAPPER_OPTSTR="-f markdown -t html --fail-if-warnings=true"
|
||||
export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
||||
export TOP_URL="https://ioccc-src.github.io/temp-test-ioccc"
|
||||
|
||||
# set usage message
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N]
|
||||
[-d topdir] [-p pandoc_tool] [-P pandoc_opts]
|
||||
[-u repo_url] [-U top_url] [-e string ..] [-E exitcode]
|
||||
file.md output.html
|
||||
|
||||
-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)
|
||||
|
||||
-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 pandoc_tool path to the pandoc tool (not the wrapper) (def: $PANDOC_TOOL)
|
||||
-P pandoc_opts options given to the pandoc tool (def: $PANDOC_ARGS)
|
||||
|
||||
-u repo_url Base level URL of target git repo (def: $REPO_URL)
|
||||
-U top_url Top level URL of web site where HTML files will be viewed (def: $TOP_URL)
|
||||
|
||||
-e string output string, followed by newline, to stderr (def: do not)
|
||||
-E exitcode force exit with exitcode (def: exit based on success or failure of the action)
|
||||
|
||||
file.md markdown file to convert into HTML
|
||||
output.html HTML generated by pandoc from file.md
|
||||
NOTE: Use - to write to standard output (stdout)
|
||||
NOTE: Without -n, will prepend '-o output.html' as first pandoc options
|
||||
With -n, will append '-o /dev/null' as last pandoc options before file.md
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 pandoc exited non-zero
|
||||
2 -h and help string printed or -V and version string printed
|
||||
3 command line error
|
||||
4 bash version is < 4.2
|
||||
5 file.md file not found or not readable file
|
||||
6 pandoc tool not found or not executable
|
||||
>= 10 < 200 ((not used))
|
||||
>= 200 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
# setup
|
||||
#
|
||||
export NOOP=
|
||||
export DO_NOT_PROCESS=
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nNp:P:u:U:e:E: flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
n) NOOP="-n"
|
||||
;;
|
||||
N) DO_NOT_PROCESS="-N"
|
||||
;;
|
||||
p) PANDOC_TOOL="$OPTARG"
|
||||
;;
|
||||
P) PANDOC_ARGS="$OPTARG"
|
||||
;;
|
||||
u) REPO_URL="$OPTARG"
|
||||
;;
|
||||
U) TOP_URL="$OPTARG"
|
||||
;;
|
||||
e) echo "$OPTARG" 1>&2
|
||||
;;
|
||||
E) exit "$OPTARG"
|
||||
;;
|
||||
\?) 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 1 ]]; then
|
||||
echo "$0: debug[1]: debug level: $V_FLAG" 1>&2
|
||||
fi
|
||||
#
|
||||
shift $(( OPTIND - 1 ));
|
||||
#
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: argument count: $#" 1>&2
|
||||
fi
|
||||
if [[ $# -ne 2 ]]; then
|
||||
echo "$0: ERROR: expected 2 args, found: $#" 1>&2
|
||||
exit 3
|
||||
fi
|
||||
#
|
||||
export MARKDOWN_INPUT="$1"
|
||||
export HTML_OUTPUT="$2"
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: MARKDOWN_INPUT=$MARKDOWN_INPUT" 1>&2
|
||||
echo "$0: debug[1]: HTML_OUTPUT=$HTML_OUTPUT" 1>&2
|
||||
fi
|
||||
|
||||
# firewall - validate args
|
||||
#
|
||||
if [[ ! -e $MARKDOWN_INPUT ]]; then
|
||||
echo "$0: ERROR: markdown input file does not exist: $MARKDOWN_INPUT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -f $MARKDOWN_INPUT ]]; then
|
||||
echo "$0: ERROR: markdown input is not a file: $MARKDOWN_INPUT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -r $MARKDOWN_INPUT ]]; then
|
||||
echo "$0: ERROR: markdown input is not a readable file: $MARKDOWN_INPUT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -x $PANDOC_TOOL ]]; then
|
||||
echo "$0: ERROR: cannot find an executable pandoc tool: $PANDOC_TOOL" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
|
||||
# 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 201
|
||||
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 202
|
||||
fi
|
||||
|
||||
# verify that we have an author subdirectory
|
||||
#
|
||||
export AUTHOR_PATH="$TOPDIR/author"
|
||||
if [[ ! -d $AUTHOR_PATH ]]; then
|
||||
echo "$0: ERROR: author is not a directory under topdir: $AUTHOR_PATH" 1>&2
|
||||
exit 203
|
||||
fi
|
||||
export AUTHOR_DIR="author"
|
||||
|
||||
# verify that we have an inc subdirectory
|
||||
#
|
||||
export INC_PATH="$TOPDIR/inc"
|
||||
if [[ ! -d $INC_PATH ]]; then
|
||||
echo "$0: ERROR: inc is not a directory under topdir: $INC_PATH" 1>&2
|
||||
exit 204
|
||||
fi
|
||||
export INC_DIR="inc"
|
||||
|
||||
# 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 205
|
||||
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 206
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 207
|
||||
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 208
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
# parameter debugging
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
||||
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
||||
echo "$0: debug[3]: TOP_URL=$TOP_URL" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_PATH=$AUTHOR_PATH" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_DIR=$AUTHOR_DIR" 1>&2
|
||||
echo "$0: debug[3]: INC_PATH=$INC_PATH" 1>&2
|
||||
echo "$0: debug[3]: INC_DIR=$INC_DIR" 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]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
|
||||
echo "$0: debug[3]: NOOP=$NOOP" 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
|
||||
|
||||
# execute pandoc
|
||||
#
|
||||
if [[ -z $NOOP ]]; then
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: will execute pandoc as: $PANDOC_TOOL -o $HTML_OUTPUT $PANDOC_ARGS $MARKDOWN_INPUT" 1>&2
|
||||
fi
|
||||
# SC2086 (info): Double quote to prevent globbing and word splitting.
|
||||
# shellcheck disable=SC2086
|
||||
"$PANDOC_TOOL" -o "$HTML_OUTPUT" $PANDOC_ARGS "$MARKDOWN_INPUT"
|
||||
status="$?"
|
||||
else
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[3]: will execute pandoc as: $PANDOC_TOOL $PANDOC_ARGS -o /dev/null $MARKDOWN_INPUT" 1>&2
|
||||
fi
|
||||
# SC2086 (info): Double quote to prevent globbing and word splitting.
|
||||
# shellcheck disable=SC2086
|
||||
"$PANDOC_TOOL" $PANDOC_ARGS -o /dev/null "$MARKDOWN_INPUT"
|
||||
status="$?"
|
||||
fi
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$0: ERROR: pandoc: $PANDOC_TOOL exited non-zero: $status" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
exit 0
|
||||
Executable
+2064
File diff suppressed because it is too large.
Load diff
Executable
+355
@@ -0,0 +1,355 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# subst.default.sh - print default substitutions
|
||||
#
|
||||
# This tool is used in conjunction with the inc/md2html.cfg configuration
|
||||
# file, and the tools that use that use that configuration file
|
||||
# such as "readme2index.sh".
|
||||
#
|
||||
# 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
|
||||
#
|
||||
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 . nor ..
|
||||
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.1 2024-01-14"
|
||||
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 200
|
||||
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 REPO_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
||||
export TOP_URL="https://ioccc-src.github.io/temp-test-ioccc"
|
||||
|
||||
# set usage message
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N]
|
||||
[-d topdir] [-p tool] [-P optstr]
|
||||
[-u repo_url] [-U top_url] [-e string ..] [-E exitcode]
|
||||
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)
|
||||
|
||||
-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)
|
||||
|
||||
-u repo_url Base level URL of target git repo (def: $REPO_URL)
|
||||
-U top_url Top level URL of web site where HTML files will be viewed (def: $TOP_URL)
|
||||
|
||||
-e string output string, followed by newline, to stderr (def: do not)
|
||||
-E exitcode force exit with exitcode (def: exit based on success or failure of the action)
|
||||
|
||||
yyyy/dir path from topdir to winner directory: must contain the files: README.md, .path and .winner.json
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 pandoc exited non-zero
|
||||
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 winner directory
|
||||
>= 10 < 200 ((not used))
|
||||
>= 200 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
# setup
|
||||
#
|
||||
export NOOP=
|
||||
export DO_NOT_PROCESS=
|
||||
export DOCROOT_URL_SLASH="/"
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nNu:U:e:E: flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
n) NOOP="-n"
|
||||
;;
|
||||
N) DO_NOT_PROCESS="-N"
|
||||
;;
|
||||
u) REPO_URL="$OPTARG"
|
||||
;;
|
||||
U) TOP_URL="$OPTARG"
|
||||
;;
|
||||
e) echo "$OPTARG" 1>&2
|
||||
;;
|
||||
E) exit "$OPTARG"
|
||||
;;
|
||||
\?) 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 1 ]]; then
|
||||
echo "$0: debug[1]: 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 WINNER_PATH="$1"
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: WINNER_PATH=$WINNER_PATH" 1>&2
|
||||
fi
|
||||
|
||||
# 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 201
|
||||
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 202
|
||||
fi
|
||||
|
||||
# verify that we have an author subdirectory
|
||||
#
|
||||
export AUTHOR_PATH="$TOPDIR/author"
|
||||
if [[ ! -d $AUTHOR_PATH ]]; then
|
||||
echo "$0: ERROR: author is not a directory under topdir: $AUTHOR_PATH" 1>&2
|
||||
exit 203
|
||||
fi
|
||||
export AUTHOR_DIR="author"
|
||||
|
||||
# verify that we have an inc subdirectory
|
||||
#
|
||||
export INC_PATH="$TOPDIR/inc"
|
||||
if [[ ! -d $INC_PATH ]]; then
|
||||
echo "$0: ERROR: inc is not a directory under topdir: $INC_PATH" 1>&2
|
||||
exit 204
|
||||
fi
|
||||
export INC_DIR="inc"
|
||||
|
||||
# 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 205
|
||||
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 206
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 207
|
||||
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 208
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
# verify that WINNER_PATH is a winner directory
|
||||
#
|
||||
# WINNER_PATH must be in yyyy/dir form
|
||||
# yyyy must be a directory
|
||||
# yyyy must be a writable directory
|
||||
# yyyy/.year must be a non-empty file
|
||||
# yyyy/dir must be a directory
|
||||
# yyyy/dir/.path must be a non-empty file
|
||||
# WINNER_PATH must match the contents of yyyy/dir/.path
|
||||
# yyyy/dir/.winner.json must be a non-empty file
|
||||
#
|
||||
if [[ ! -d $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -w $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a writable directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export YEAR_DIR=${WINNER_PATH%%/*}
|
||||
if [[ -z $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: arg not in yyyy/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_DIR=${WINNER_PATH#*/}
|
||||
if [[ -z $WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH not in $YEAR_DIR/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ $WINNER_DIR = */* ]]; then
|
||||
echo "$0: ERROR: dir from arg: $WINNER_PATH contains a /: $WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy from arg: $WINNER_PATH is not a directory: $YEAR_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_ID="${YEAR_DIR}_${WINNER_DIR}"
|
||||
export DOT_YEAR="$YEAR_DIR/.year"
|
||||
if [[ ! -s $DOT_YEAR ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_YEAR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR/$WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy/dir from arg: $WINNER_PATH is not a directory: $YEAR_DIR/$WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export DOT_PATH="$YEAR_DIR/$WINNER_DIR/.path"
|
||||
if [[ ! -s $DOT_PATH ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
DOT_PATH_CONTENT=$(< "$DOT_PATH")
|
||||
if [[ $WINNER_PATH != "$DOT_PATH_CONTENT" ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH does not match $DOT_PATH contents: $DOT_PATH_CONTENT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_JSON="$YEAR_DIR/$WINNER_DIR/.winner.json"
|
||||
if [[ ! -e $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json does not exist: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a readable file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
|
||||
# parameter debugging
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_DIR=$WINNER_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_ID=$WINNER_ID" 1>&2
|
||||
echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
|
||||
echo "$0: debug[3]: DOT_PATH=$DOT_PATH" 1>&2
|
||||
echo "$0: debug[3]: WINNER_JSON=$WINNER_JSON" 1>&2
|
||||
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
||||
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
||||
echo "$0: debug[3]: TOP_URL=$TOP_URL" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_PATH=$AUTHOR_PATH" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_DIR=$AUTHOR_DIR" 1>&2
|
||||
echo "$0: debug[3]: INC_PATH=$INC_PATH" 1>&2
|
||||
echo "$0: debug[3]: INC_DIR=$INC_DIR" 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]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
|
||||
echo "$0: debug[3]: NOOP=$NOOP" 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
|
||||
|
||||
# output HEADER_1 substitution
|
||||
#
|
||||
echo "-s HEADER_1='The International Obfuscated C Code Contest'"
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
exit 0
|
||||
Executable
+408
@@ -0,0 +1,408 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# subst.winner-index.sh - print substitutions for a winner index.html
|
||||
#
|
||||
# This tool is used in conjunction with the inc/md2html.cfg configuration
|
||||
# file, and "readme2index.sh" to build an index.html file for a winner.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
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 . nor ..
|
||||
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.1 2024-01-14"
|
||||
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 200
|
||||
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 REPO_URL="https://github.com/ioccc-src/temp-test-ioccc"
|
||||
export TOP_URL="https://ioccc-src.github.io/temp-test-ioccc"
|
||||
|
||||
# set usage message
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N]
|
||||
[-d topdir] [-p tool] [-P optstr]
|
||||
[-u repo_url] [-U top_url] [-e string ..] [-E exitcode]
|
||||
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)
|
||||
|
||||
-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)
|
||||
|
||||
-u repo_url Base level URL of target git repo (def: $REPO_URL)
|
||||
-U top_url Top level URL of web site where HTML files will be viewed (def: $TOP_URL)
|
||||
|
||||
-e string output string, followed by newline, to stderr (def: do not)
|
||||
-E exitcode force exit with exitcode (def: exit based on success or failure of the action)
|
||||
|
||||
yyyy/dir path from topdir to winner directory: must contain the files: README.md, .path and .winner.json
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 pandoc exited non-zero
|
||||
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 winner directory
|
||||
6 subst.winner-navbar.awk tool not found
|
||||
>= 10 < 200 ((not used))
|
||||
>= 200 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
# setup
|
||||
#
|
||||
export NOOP=
|
||||
export DO_NOT_PROCESS=
|
||||
export DOCROOT_URL_SLASH="../../"
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nNu:U:e:E: flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
n) NOOP="-n"
|
||||
;;
|
||||
N) DO_NOT_PROCESS="-N"
|
||||
;;
|
||||
u) REPO_URL="$OPTARG"
|
||||
;;
|
||||
U) TOP_URL="$OPTARG"
|
||||
;;
|
||||
e) echo "$OPTARG" 1>&2
|
||||
;;
|
||||
E) exit "$OPTARG"
|
||||
;;
|
||||
\?) 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 1 ]]; then
|
||||
echo "$0: debug[1]: 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 WINNER_PATH="$1"
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: WINNER_PATH=$WINNER_PATH" 1>&2
|
||||
fi
|
||||
|
||||
# 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 201
|
||||
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 202
|
||||
fi
|
||||
|
||||
# verify that we have an author subdirectory
|
||||
#
|
||||
export AUTHOR_PATH="$TOPDIR/author"
|
||||
if [[ ! -d $AUTHOR_PATH ]]; then
|
||||
echo "$0: ERROR: author is not a directory under topdir: $AUTHOR_PATH" 1>&2
|
||||
exit 203
|
||||
fi
|
||||
export AUTHOR_DIR="author"
|
||||
|
||||
# verify that we have an inc subdirectory
|
||||
#
|
||||
export INC_PATH="$TOPDIR/inc"
|
||||
if [[ ! -d $INC_PATH ]]; then
|
||||
echo "$0: ERROR: inc is not a directory under topdir: $INC_PATH" 1>&2
|
||||
exit 204
|
||||
fi
|
||||
export INC_DIR="inc"
|
||||
|
||||
# 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 205
|
||||
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 206
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 207
|
||||
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 208
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
# verify that WINNER_PATH is a winner directory
|
||||
#
|
||||
# WINNER_PATH must be in yyyy/dir form
|
||||
# yyyy must be a directory
|
||||
# yyyy must be a writable directory
|
||||
# yyyy/.year must be a non-empty file
|
||||
# yyyy/dir must be a directory
|
||||
# yyyy/dir/.path must be a non-empty file
|
||||
# WINNER_PATH must match the contents of yyyy/dir/.path
|
||||
# yyyy/dir/.winner.json must be a non-empty file
|
||||
#
|
||||
if [[ ! -d $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -w $WINNER_PATH ]]; then
|
||||
echo "$0: ERROR: arg is not a writable directory: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export YEAR_DIR=${WINNER_PATH%%/*}
|
||||
if [[ -z $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: arg not in yyyy/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_DIR=${WINNER_PATH#*/}
|
||||
if [[ -z $WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH not in $YEAR_DIR/dir form: $WINNER_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ $WINNER_DIR = */* ]]; then
|
||||
echo "$0: ERROR: dir from arg: $WINNER_PATH contains a /: $WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy from arg: $WINNER_PATH is not a directory: $YEAR_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_ID="${YEAR_DIR}_${WINNER_DIR}"
|
||||
export DOT_YEAR="$YEAR_DIR/.year"
|
||||
if [[ ! -s $DOT_YEAR ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_YEAR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -d $YEAR_DIR/$WINNER_DIR ]]; then
|
||||
echo "$0: ERROR: yyyy/dir from arg: $WINNER_PATH is not a directory: $YEAR_DIR/$WINNER_DIR" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export DOT_PATH="$YEAR_DIR/$WINNER_DIR/.path"
|
||||
if [[ ! -s $DOT_PATH ]]; then
|
||||
echo "$0: ERROR: not a non-empty file: $DOT_PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
DOT_PATH_CONTENT=$(< "$DOT_PATH")
|
||||
if [[ $WINNER_PATH != "$DOT_PATH_CONTENT" ]]; then
|
||||
echo "$0: ERROR: arg: $WINNER_PATH does not match $DOT_PATH contents: $DOT_PATH_CONTENT" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
export WINNER_JSON="$YEAR_DIR/$WINNER_DIR/.winner.json"
|
||||
if [[ ! -e $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json does not exist: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -f $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
if [[ ! -r $WINNER_JSON ]]; then
|
||||
echo "$0: ERROR: .winner.json is not a readable file: $WINNER_JSON" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
|
||||
# verify we have our awk script
|
||||
#
|
||||
export WINNER_NAVBAR_AWK="$BIN_DIR/subst.winner-navbar.awk"
|
||||
if [[ ! -e $WINNER_NAVBAR_AWK ]]; then
|
||||
echo "$0: ERROR: bin/subst.winner-navbar.awk does not exist: $WINNER_NAVBAR_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -f $WINNER_NAVBAR_AWK ]]; then
|
||||
echo "$0: ERROR: bin/subst.winner-navbar.awk is not a file: $WINNER_NAVBAR_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -r $WINNER_NAVBAR_AWK ]]; then
|
||||
echo "$0: ERROR: bin/subst.winner-navbar.awk is not a readable file: $WINNER_NAVBAR_AWK" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
|
||||
# parameter debugging
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_DIR=$WINNER_DIR" 1>&2
|
||||
echo "$0: debug[3]: WINNER_ID=$WINNER_ID" 1>&2
|
||||
echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
|
||||
echo "$0: debug[3]: DOT_PATH=$DOT_PATH" 1>&2
|
||||
echo "$0: debug[3]: WINNER_JSON=$WINNER_JSON" 1>&2
|
||||
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
|
||||
echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
|
||||
echo "$0: debug[3]: TOP_URL=$TOP_URL" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_PATH=$AUTHOR_PATH" 1>&2
|
||||
echo "$0: debug[3]: AUTHOR_DIR=$AUTHOR_DIR" 1>&2
|
||||
echo "$0: debug[3]: INC_PATH=$INC_PATH" 1>&2
|
||||
echo "$0: debug[3]: INC_DIR=$INC_DIR" 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]: WINNER_NAVBAR_AWK=$WINNER_NAVBAR_AWK" 1>&2
|
||||
echo "$0: debug[3]: DOCROOT_URL_SLASH=$DOCROOT_URL_SLASH" 1>&2
|
||||
echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
|
||||
echo "$0: debug[3]: NOOP=$NOOP" 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
|
||||
|
||||
# output DOCROOT_URL_SLASH substitution
|
||||
#
|
||||
echo "-s 'DOCROOT_URL_SLASH=$DOCROOT_URL_SLASH'"
|
||||
|
||||
# output TITLE substitution
|
||||
#
|
||||
echo "-s 'TITIE=$YEAR_DIR/$WINNER_DIR'"
|
||||
|
||||
# output DESCRIPTION substitution
|
||||
#
|
||||
echo "-s 'DESCRIPTION=$YEAR_DIR IOCCC winner $WINNER_DIR'"
|
||||
|
||||
# output KEYWORDS substitution
|
||||
#
|
||||
echo "-s 'KEYWORDS=IOCCC, $YEAR_DIR, IOCCC $YEAR_DIR, IOCCC winner, $WINNER_DIR'"
|
||||
|
||||
# output HEADER_2 substitution
|
||||
#
|
||||
echo "-s 'HEADER_2=$YEAR_DIR/$WINNER_DIR'"
|
||||
|
||||
# output topnav links
|
||||
#
|
||||
awk -v winner_path="$YEAR_DIR/$WINNER_DIR" -f "$WINNER_NAVBAR_AWK" "$DOT_YEAR"
|
||||
status="$?"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "$0: ERROR: subst.winner-navbar.awk failed, error: $status" 1>&2
|
||||
exit 209
|
||||
fi
|
||||
|
||||
# form Nu Html Checker doc url string
|
||||
#
|
||||
export URL="$TOP_URL/$YEAR_DIR/$WINNER_DIR/index.html"
|
||||
VALIDATOR_ENCODED_URL=$(echo "$URL" | sed -e 's;/;%2F;g' -e 's;:;%3A;')
|
||||
export VALIDATOR_ENCODED_URL
|
||||
|
||||
# output the Validator encoded URL
|
||||
#
|
||||
echo "-s 'VALIDATOR_ENCODED_URL=$VALIDATOR_ENCODED_URL'"
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
exit 0
|
||||
Executable
+150
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env awk
|
||||
#
|
||||
# subst.winner-navbar.awk - output substitutions for navbar on behalf of a winner
|
||||
#
|
||||
# usage:
|
||||
#
|
||||
# awk -v winner_path=YYYY/dir -f bin/subst.winner-navbar.awk YYYY/.year
|
||||
#
|
||||
# where:
|
||||
#
|
||||
# YYYY IOCCC year or mock
|
||||
# dir name of winner directory under YYYY
|
||||
|
||||
BEGIN {
|
||||
|
||||
# setup
|
||||
#
|
||||
VERSION="1.0 2024-01-14"
|
||||
process_next_line = 0; # 1 ==> we found our winner_path, now process the next line
|
||||
found_winner_path = 0; # 1 ==> we found our winner_path
|
||||
prev_line = ""; # the previous YYYY/dir line
|
||||
topnav_phase = "mid"; # topnav name to use (-H topnav=topnav_phase)
|
||||
|
||||
# error if github is not set via -v github=REPO_URL
|
||||
#
|
||||
if (length(winner_path) == 0) {
|
||||
exit 200;
|
||||
}
|
||||
}
|
||||
|
||||
# process YYYY/dir lines
|
||||
#
|
||||
$0 ~ /[^\/]+\/[^\/]+/ {
|
||||
|
||||
# split line into year (file[1]) and dir (file[2])
|
||||
#
|
||||
len = split($0, file, "/");
|
||||
if (len != 2) {
|
||||
# ERROR: invalid split of a YYYY/dir line
|
||||
print "-e 'invalid split of:", $0, "expected 2 part, found:", len "'";
|
||||
print "-E 201";
|
||||
exit
|
||||
}
|
||||
year = file[1];
|
||||
dir = file[2];
|
||||
|
||||
# if we need the line after we found our winner_path
|
||||
#
|
||||
if (process_next_line) {
|
||||
|
||||
# process the line after we found our winner_path
|
||||
#
|
||||
# report the previous entry for this year
|
||||
print "-s 'RIGHT_LINK=../" dir "/index.html'";
|
||||
print "-s 'RIGHT_TEXT=" dir "'";
|
||||
process_next_line = 0;
|
||||
|
||||
# if we found our winner_path
|
||||
#
|
||||
} else if (winner_path == $0) {
|
||||
|
||||
# in case our our winner_path is the 1st line
|
||||
#
|
||||
if (NR == 1) {
|
||||
# no previous line winner_path is the 1st line
|
||||
topnav_phase = "first";
|
||||
}
|
||||
|
||||
# process the previous YYYY/dir line with this match
|
||||
#
|
||||
if (prev_line) {
|
||||
|
||||
# split previous line into year (file[1]) and dir (file[2])
|
||||
#
|
||||
prev_len = split(prev_line, file, "/");
|
||||
if (prev_len != 2) {
|
||||
# ERROR: invalid split of a previous YYYY/dir line
|
||||
print "-e 'invalid split of:", prev_line "expected 2 part, found:", prev_len "'";
|
||||
print "-E 202";
|
||||
exit
|
||||
}
|
||||
prev_year = file[1];
|
||||
prev_dir = file[2];
|
||||
if (year != prev_year) {
|
||||
# ERROR: previous YYYY/dir YYYY does not match current line
|
||||
print "-e 'previous line:", prev_line "year:", prev_year, "!= current line year:", year "'";
|
||||
print "-E 203";
|
||||
}
|
||||
|
||||
# report the next entry for this year
|
||||
print "-s 'LEFT_LINK=../" prev_dir "/index.html'";
|
||||
print "-s 'LEFT_TEXT=" prev_dir "'";
|
||||
}
|
||||
|
||||
# process our found winner_path
|
||||
#
|
||||
# report up link top year index.html
|
||||
print "-s 'UP_LINK=../index.html'";
|
||||
print "-s 'UP_TEXT=" year "'";
|
||||
process_next_line = 1;
|
||||
found_winner_path = 1;
|
||||
}
|
||||
|
||||
# save the line as the next previous line
|
||||
#
|
||||
prev_line = $0;
|
||||
}
|
||||
|
||||
# report any non-YYYY/dir line
|
||||
#
|
||||
$0 !~ /[^\/]+\/[^\/]+/ {
|
||||
|
||||
# bogus line found
|
||||
print "-e 'found a non-YYYY/dir line in", ARGV[1] ":", $0 "'";
|
||||
print "-E 204";
|
||||
exit
|
||||
}
|
||||
|
||||
END {
|
||||
|
||||
# error if github is not set via -v github=REPO_URL
|
||||
#
|
||||
if (length(winner_path) == 0) {
|
||||
print "-e 'ERROR: github variable not set, call with -v github=REPO_URL'";
|
||||
print "-E 200"; # use 200 to match exit code from BEGIN
|
||||
exit 200 # use 200 to match exit code from BEGIN
|
||||
}
|
||||
|
||||
# output inventory link information
|
||||
#
|
||||
print "-s 'INVENTORY_LINK=#inventory'";
|
||||
print "-s 'INVENTORY_TEXT=Inventory'";
|
||||
|
||||
# case: we did not find our winner_path
|
||||
#
|
||||
if (!found_winner_path) {
|
||||
# ERROR: winner_path was not found
|
||||
print "-e 'we did not find:", winner_path "'";
|
||||
print "-E 205";
|
||||
exit
|
||||
|
||||
} else if (process_next_line) {
|
||||
# no next line winner_path is the last line
|
||||
topnav_phase = "last";
|
||||
}
|
||||
|
||||
# output the topnav phase name
|
||||
#
|
||||
print "-H 'topnav=" topnav_phase "'";
|
||||
}
|
||||
Reference in new issue
Block a user