#!/usr/bin/env bash

# update-elf2tag-manpage - update the elf2tag.1 manpage from adoc source
#
# Usage:
#    ./path/to/update-elf2tag-manpage
#    ./path/to/update-elf2tag-manpage --verify
#
# Without a command line argument given, changes into the directory
# where update-elf2tag-manpage and elf2tag.1.adoc are, runs
# asciidoctor to produce a man page elf2tag.1 from elf2tag.1.adoc, but
# only updates the elf2tag.1 file in the case of actual changes.
#
# Just the asciidoctor version or the current date being different
# from the last asciidoctor run is not considered an actual change.
#
# With the --verify argument given, only verify that elf2tag.1 and
# elf2tag.1.adoc are consistent with each other, i.e. elf2tag.1 would
# not be changed.
#
# Requires asciidoctor to be installed.
#
# Environment variables used (if unset, uses the command from PATH):
# ASCIIDOCTOR  the asciidoctor command to run
# CMP          the cmp command to run (e.g. "busybox cmp")
# DIFF         the diff command to run with -u (used with --verify only)
# SED          the sed command to run (e.g. "busybox sed")

# This script uses the shell feature called "process substitution" which
# is implemented by bash and busybox sh, but not by e.g. dash and can
# therefore not be a /bin/sh script.

set -e

prog="$(basename "$0")"

if test "$#" -gt 1; then
  echo "$prog: Too many command line arguments"
  exit 2
fi

verify=false
if test "$#" -eq 1; then
  case "$1" in
    -h | --help )
      ${SED-sed} -n '/^#\( .*\)$/,$p' "$0" \
        | ${SED-sed} '/^#\( .*\)\?$/!q' \
        | ${SED-sed} '/^$/d' \
        | ${SED-sed} 's|^#$||; s|^# ||'
      exit 0
      ;;
    --verify )
      verify=:
      ;;
    * )
      echo "$prog: Unhandled command line argument."
      exit 2
      ;;
  esac
fi

cd "$(dirname "$0")"

test -s elf2tag.1.adoc
test -s elf2tag

# Usage: normalize_manpage original.1 normalized.1
#
# Normalizes a man page generated by asciidoctor by replacing data not
# present in the sources such as generation date, asciidoctor version.
normalize_manpage() {
  ${SED-sed} -f <(cat<<EOF
#s|^\.\\\\|==TITLE==|
s|^\.\\\\" Generator: Asciidoctor .*|.\\" Generator: GENERATOR|
s|^\.\\\\"      Date: 20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]|.\\"      Date: DATE|
s|^\.TH "ELF2TAG" "1" "20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]" "avrdude" "avrdude Manual"|\.\\" TH HEADER|
EOF
) < "$1" > "$2"
}

tmpdir="tmp$$"

if ! ${ASCIIDOCTOR-asciidoctor} -b manpage -D "$tmpdir" elf2tag.1.adoc; then
  echo "$prog: Error updating elf2tag.1"
  rm -rf "$tmpdir"
  exit 2
fi

# Have sed ensure a trailing newline character by appending empty string
#
# This is necessary as asciidoctor likes to create files without a
# trailing newline, while it is good form for text editors to add one.
if ${SED-sed} '$a\' < "$tmpdir/elf2tag.1" > "$tmpdir/elf2tag.1.newline"; then
  mv -f "$tmpdir/elf2tag.1.newline" "$tmpdir/elf2tag.1"
else
  echo "$prog: Error ensuring trailing newline character"
  rm -rf "$tmpdir"
  exit 2
fi

if ! test -e elf2tag.1; then
  if "$verify"; then
    echo "$prog: Cannot ensure consistency if there is no old elf2tag.1 file"
    rm -rf "$tmpdir"
    exit 1
  fi
  echo "$prog: Generate elf2tag.1"
  mv -f "$tmpdir/elf2tag.1" elf2tag.1
  rmdir "$tmpdir"
  exit 0
fi

normalize_manpage elf2tag.1           "$tmpdir/elf2tag.1.norm-old"
normalize_manpage "$tmpdir/elf2tag.1" "$tmpdir/elf2tag.1.norm-new"

if ${CMP-cmp} "$tmpdir/elf2tag.1.norm-old" "$tmpdir/elf2tag.1.norm-new" > /dev/null; then
  echo "$prog: elf2tag.1 is up to date"
  rm -f "$tmpdir/elf2tag.1"
  rm -f "$tmpdir/elf2tag.1.norm-old"
  rm -f "$tmpdir/elf2tag.1.norm-new"
  rmdir "$tmpdir"
  exit 0
fi

if "$verify"; then
  echo "$prog: Error: src/elf2tag.1 is inconsistent with src/elf2tag.1.adoc"
  ${DIFF-diff} -u "$tmpdir/elf2tag.1.norm-old" "$tmpdir/elf2tag.1.norm-new" ||:
  rm -f "$tmpdir/elf2tag.1"
  rm -f "$tmpdir/elf2tag.1.norm-old"
  rm -f "$tmpdir/elf2tag.1.norm-new"
  rmdir "$tmpdir"
  exit 1
fi

echo "Updating elf2tag.1"
mv -f "$tmpdir/elf2tag.1" elf2tag.1
rm -f "$tmpdir/elf2tag.1.norm-old"
rm -f "$tmpdir/elf2tag.1.norm-new"
rmdir "$tmpdir"
exit 0
