Updates for show "repair" processing
InternetArchive/future_upload: Added logging and debugging InternetArchive/ia_db.sql: Added new tables InternetArchive/recover_transcripts: New script to run on 'borg' and copy missing files from the backup disk to the IA InternetArchive/repair_assets: More comments, including one about a bug in the design. InternetArchive/repair_item: Fix relating to octal numbers (if there are leading zeroes in a number). '_DEBUG' is now in the function library. Added comments to explain obscure stuff. InternetArchive/snapshot_metadata: New Bash script (to run on my desktop) which collects metadata for a show and stores in in the '~/HPR/IA/assets' directory. Runs 'view_derivatives' on it to find derivative files for deletion. InternetArchive/tidy_uploaded: Moves files and directories containing uploaded files into a holding area for later backup. Added debugging, logging and a 'force' mode. InternetArchive/upload_manager: Manages 'ia.db' (on my workstation). Needs many updates which have just started to be added. InternetArchive/weekly_upload: Old script, now obsolete.
This commit is contained in:
parent
dc0f29e957
commit
19030fee71
@ -13,9 +13,9 @@
|
||||
# NOTES: Contains methods from 'delete_uploaded' and 'weekly_upload' as
|
||||
# well as 'update_state'
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.14
|
||||
# VERSION: 0.0.15
|
||||
# CREATED: 2021-01-07 12:11:02
|
||||
# REVISION: 2024-03-03 14:12:30
|
||||
# REVISION: 2024-07-29 23:17:45
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
@ -26,7 +26,7 @@ SCRIPT=${0##*/}
|
||||
|
||||
STDOUT="/dev/fd/2"
|
||||
|
||||
VERSION="0.0.14"
|
||||
VERSION="0.0.15"
|
||||
|
||||
#
|
||||
# Load library functions
|
||||
@ -36,6 +36,8 @@ LIB="$HOME/bin/function_lib.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$LIB"
|
||||
|
||||
# {{{ -- Functions -- check_uploads, _log, _usage
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: check_uploads
|
||||
# DESCRIPTION: Determines if files exist for uploading
|
||||
@ -59,6 +61,31 @@ check_uploads () {
|
||||
return 0
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _log
|
||||
# DESCRIPTION: Writes a log record to the predefined $LOGFILE in this script
|
||||
# using the predefined $LOGREC, a template for 'printf'. If the
|
||||
# latter is not defined the function will use a default.
|
||||
# For some reason 'shellcheck' objects to this function. The
|
||||
# first argument to 'printf' needs to be -1 to make the
|
||||
# '%(fmt)T' use today's date and time.
|
||||
# PARAMETERS: 1 - the message to write
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2317 disable=SC2059
|
||||
_log () {
|
||||
local msg="$1"
|
||||
|
||||
# echo "D> $LOGFILE $LOGREC"
|
||||
[ -v LOGFILE ] || { echo "${FUNCNAME[0]}: \$LOGFILE is not defined"; exit 1; }
|
||||
[ -v LOGREC ] || { local LOGREC='%(%F %T)T %s\n'; }
|
||||
|
||||
# echo "D> $LOGFILE $LOGREC"
|
||||
printf "$LOGREC" -1 "$msg" >> "$LOGFILE"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _usage
|
||||
# DESCRIPTION: Report usage
|
||||
@ -108,18 +135,7 @@ endusage
|
||||
exit "$res"
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _DEBUG
|
||||
# DESCRIPTION: Writes a message if in DEBUG mode
|
||||
# PARAMETERS: List of messages
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_DEBUG () {
|
||||
[ "$DEBUG" == 0 ] && return
|
||||
for msg in "$@"; do
|
||||
printf 'D> %s\n' "$msg"
|
||||
done
|
||||
}
|
||||
# }}}
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -144,6 +160,7 @@ cd "$BASEDIR" || { echo "Can't cd to $BASEDIR"; exit 1; }
|
||||
#
|
||||
LOGS="$BASEDIR/logs"
|
||||
LOGFILE="$LOGS/$SCRIPT.log"
|
||||
LOGREC='%(%F %T)T %s\n'
|
||||
|
||||
#
|
||||
# Tools
|
||||
@ -157,8 +174,8 @@ UPSTATE="$BASEDIR/update_state"
|
||||
#
|
||||
# Fallback URL
|
||||
#
|
||||
URL_BAK="http://hub.hackerpublicradio.org/cms/status.php"
|
||||
QUERY2_BAK="${BASECOM} -o - ${URL_BAK}"
|
||||
# URL_BAK="http://hub.hackerpublicradio.org/cms/status.php"
|
||||
# QUERY2_BAK="${BASECOM} -o - ${URL_BAK}"
|
||||
|
||||
#
|
||||
# Prerequisites
|
||||
@ -575,4 +592,4 @@ fi
|
||||
|
||||
exit
|
||||
|
||||
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21
|
||||
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21:fdm=marker
|
||||
|
@ -3,11 +3,11 @@
|
||||
* =========
|
||||
*
|
||||
* Schema for SQLite database 'ia.db' used to hold IA upload information
|
||||
* Last updated: 2022-06-16
|
||||
* Last updated: 2024-07-15
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: episodes
|
||||
*
|
||||
* id show number from HPR
|
||||
@ -44,7 +44,7 @@ CREATE TABLE episodes (
|
||||
notes text
|
||||
);
|
||||
|
||||
/*
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: assets
|
||||
*
|
||||
* id primary key
|
||||
@ -62,7 +62,7 @@ CREATE TABLE assets (
|
||||
uploaded integer default 0
|
||||
);
|
||||
|
||||
/*
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Index: assets_filename_idx
|
||||
*
|
||||
* Attempt to constrain duplicates in the assets table
|
||||
@ -70,7 +70,7 @@ CREATE TABLE assets (
|
||||
*/
|
||||
CREATE UNIQUE INDEX assets_filename_idx ON assets (episode_id, filename);
|
||||
|
||||
/*
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: dirlist
|
||||
*
|
||||
* id primary key
|
||||
@ -82,6 +82,66 @@ CREATE TABLE dirlist (
|
||||
filename text NOT NULL
|
||||
);
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: hpr_repairs
|
||||
*
|
||||
* episode_id Primary key, foreign key for 'episodes'
|
||||
* repaired Boolean showing whether the show has been repaired
|
||||
* repair_date Date of repair
|
||||
* notes Notes about any anomalies
|
||||
* asset_count Number of assets (after ignoring transcripts, etc)
|
||||
*
|
||||
*/
|
||||
CREATE TABLE hpr_repairs (
|
||||
episode_id integer PRIMARY KEY REFERENCES episodes(id),
|
||||
repaired integer default 0,
|
||||
repair_date integer default 0,
|
||||
notes text default null,
|
||||
asset_count integer default 0
|
||||
|
||||
);
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: ia_repairs
|
||||
*
|
||||
* episode_id Primary key, foreign key for 'episodes'
|
||||
* repaired Boolean showing whether the show has been repaired
|
||||
* repair_date Date of repair
|
||||
* notes Notes about any anomalies
|
||||
*
|
||||
*/
|
||||
CREATE TABLE ia_repairs (
|
||||
episode_id integer PRIMARY KEY REFERENCES episodes(id),
|
||||
repaired integer default 0,
|
||||
repair_date integer default 0,
|
||||
notes text default null
|
||||
);
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Table: show_host_xref
|
||||
*
|
||||
* episode_id Foreign key for 'episodes'
|
||||
* hostid Host number from MySQL database
|
||||
* hostname Host name from MySQL database
|
||||
*
|
||||
*/
|
||||
CREATE TABLE "show_host_xref" (
|
||||
"episode_id" integer,
|
||||
"hostid" integer,
|
||||
"hostname" text DEFAULT null,
|
||||
FOREIGN KEY("episode_id") REFERENCES "episodes"("id")
|
||||
);
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Index: show_host_xref_idx
|
||||
*
|
||||
* Attempt to constrain duplicates in the show_host_xref table
|
||||
*
|
||||
*/
|
||||
CREATE UNIQUE INDEX "show_host_xref_idx" ON "show_host_xref" (
|
||||
"episode_id" ASC
|
||||
);
|
||||
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* View: episodes_view
|
||||
*
|
||||
|
590
InternetArchive/recover_transcripts
Executable file
590
InternetArchive/recover_transcripts
Executable file
@ -0,0 +1,590 @@
|
||||
#!/bin/bash -
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: recover_transcripts
|
||||
#
|
||||
# USAGE: ./recover_transcripts item
|
||||
#
|
||||
# DESCRIPTION: Intended to be run on `borg`; collects assets from the
|
||||
# locally-mounted backup disk and places them in a local
|
||||
# directory (organised to be compatible with the IA), then
|
||||
# uploads anything that is missing on the IA.
|
||||
#
|
||||
# Version 0.1.* looks for assets in the 'eps/' directory and
|
||||
# copies them to the cache. Also moves the IA copies so all is
|
||||
# aligned. Many shows earlier than mid 2019 are likely to need
|
||||
# this addition.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.1.4
|
||||
# CREATED: 2024-07-14 13:22:58
|
||||
# REVISION: 2024-08-20 17:38:19
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
# set -o nounset # Treat unset variables as an error
|
||||
|
||||
VERSION="0.1.4"
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
# DIR=${0%/*}
|
||||
|
||||
STDOUT="/dev/fd/2"
|
||||
|
||||
#
|
||||
# Select the appropriate working directory for the host
|
||||
#
|
||||
case $(hostname) in
|
||||
i7-desktop)
|
||||
echo "To be run only on 'borg'"
|
||||
exit 1
|
||||
;;
|
||||
borg)
|
||||
BASEDIR="$HOME/IA"
|
||||
REPAIRS="$BASEDIR/repairs"
|
||||
BACKUP="/mnt/backup_disk/HPR/HPR-MIRROR"
|
||||
;;
|
||||
*)
|
||||
echo "Wrong host!"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
cd "$BASEDIR" || { echo "Failed to cd to $BASEDIR"; exit 1; }
|
||||
|
||||
#
|
||||
# Load library functions
|
||||
#
|
||||
LIB="$HOME/bin/function_lib.sh"
|
||||
[ -e "$LIB" ] || { echo "Unable to source functions"; exit; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$LIB"
|
||||
|
||||
#
|
||||
# Enable coloured messages
|
||||
#
|
||||
define_colours
|
||||
|
||||
#
|
||||
# Sanity checks
|
||||
#
|
||||
JQ=$(command -v jq)
|
||||
[ -n "$JQ" ] || { echo "Program 'jq' was not found"; exit 1; }
|
||||
IA=$(command -v ia)
|
||||
[ -n "$IA" ] || { echo "Program 'ia' was not found"; exit 1; }
|
||||
REPIT="$BASEDIR/repair_item"
|
||||
[ -e "$REPIT" ] || { echo "Program '$REPIT' was not found"; exit 1; }
|
||||
IADB="$BASEDIR/ia.db"
|
||||
[ -e "$IADB" ] || { echo "Database '$IADB' was not found"; exit 1; }
|
||||
|
||||
# {{{ -- Functions -- _IA_move, queued_tasks, _verbose, _usage
|
||||
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _IA_move
|
||||
# DESCRIPTION: Performs a file move on the IA, with retries if it fails.
|
||||
# Assumes the existence of functions 'coloured', '_log',
|
||||
# '_verbose' and '_DEBUG'
|
||||
# PARAMETERS: $1 IA command to run (as a string)
|
||||
# $2 The path to move from
|
||||
# $3 The path to move to
|
||||
# RETURNS: False if the number of retries is exceeded, otherwise true.
|
||||
#===============================================================================
|
||||
_IA_move () {
|
||||
local from="${1:?Usage _IA_move command from to}"
|
||||
local to="${2:?Usage _IA_move command from to}"
|
||||
|
||||
local retry_threshold=5
|
||||
local retries=0
|
||||
local sleeptime=20
|
||||
local command="ia move \"$from\" \"$to\" --no-derive --no-backup > /dev/null 2>&1"
|
||||
_DEBUG "$command"
|
||||
|
||||
# coloured 'blue' "Moving $from to $to"
|
||||
|
||||
#
|
||||
# Run 'command'. If it succeeds then exit. If it fails enter the 'until'
|
||||
# loop and report the problem, then sleep and try again. Count the number
|
||||
# of times this is done, so it doesn't loop forever. If we have reached
|
||||
# the limit count this as a failure and exit with an error. If we haven't
|
||||
# retried enough yet, sleep for a while and try again. The intention is to
|
||||
# catch the case when an upload times out. The 'ia' command is performing
|
||||
# its own retries per upload when the system is overloaded, but these are
|
||||
# non-fatal.
|
||||
#
|
||||
until eval "$command"; do
|
||||
coloured 'red' "Failure when moving $from to $to"
|
||||
((retries++))
|
||||
|
||||
_log "$(printf 'Failed to move %s to %s [%d]' "$from" "$to" $retries)"
|
||||
|
||||
[ "$retries" -eq "$retry_threshold" ] && {
|
||||
_verbose \
|
||||
"$(coloured 'red' "Retry limit reached; abandoning this move")"
|
||||
return 1
|
||||
}
|
||||
|
||||
_verbose "$(coloured 'blue' "Pausing for $sleeptime seconds and retrying")"
|
||||
sleep $sleeptime
|
||||
done # until eval ...
|
||||
|
||||
coloured 'green' "Moved $from to $to on the IA"
|
||||
_log "Moved $from to $to on the IA"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: queued_tasks
|
||||
# DESCRIPTION: Queries the IA for any queued or running tasks for an item.
|
||||
# Writes the number to STDOUT so it can be captured.
|
||||
# PARAMETERS: $1 IA item (like hpr1192)
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
queued_tasks () {
|
||||
local item="${1:?Usage: queued_tasks item}"
|
||||
local -i count=0
|
||||
|
||||
count="$(ia tasks "$item" |\
|
||||
jq -s '[.[] | if .category == "catalog" then .status else empty end] | length')"
|
||||
|
||||
echo "$count"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: make_dir
|
||||
# DESCRIPTION: Make a directory if it doesn't exist, failing gracefully on
|
||||
# errors.
|
||||
# PARAMETERS: $1 directory path
|
||||
# RETURNS: True if success, otherwise exits the caller script
|
||||
#===============================================================================
|
||||
make_dir () {
|
||||
local dir="${1}"
|
||||
|
||||
if [[ ! -d $dir ]]; then
|
||||
mkdir -p "$dir" || {
|
||||
coloured 'red' "Failed to create $dir"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _ifbool
|
||||
# DESCRIPTION: Simplifies conditional expressions when they nned to return
|
||||
# one of two strings. Use as:
|
||||
# echo "Hello $(_ifbool 1 'World' 'Everyone')" → "Hello World"
|
||||
# PARAMETERS: $1 Integer being tested. If 1 then it's true, otherwise
|
||||
# it's false. Non-numeric is treated as 0/false.
|
||||
# $2 String returned for True
|
||||
# $3 String returned for False
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_ifbool () {
|
||||
local -i _bool="${1:-0}"
|
||||
local _t="${2:-true}"
|
||||
local _f="${3:-false}"
|
||||
|
||||
if [ "$_bool" -eq 1 ]; then
|
||||
echo "$_t"
|
||||
else
|
||||
echo "$_f"
|
||||
fi
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _log
|
||||
# DESCRIPTION: Appends a record to the file "$LOGFILE"
|
||||
# PARAMETERS: $1 Message to write
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_log () {
|
||||
local message="${1}"
|
||||
|
||||
echo "$(date +%F\ %T) $message" >> "$LOGFILE"
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _verbose
|
||||
# DESCRIPTION: Writes a message in verbose mode
|
||||
# PARAMETERS: * message strings to write
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_verbose () {
|
||||
[ "$VERBOSE" -eq 0 ] && return
|
||||
for msg; do
|
||||
printf '%s\n' "$msg"
|
||||
done
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _usage
|
||||
# DESCRIPTION: Reports usage; always exits the script after doing so
|
||||
# PARAMETERS: 1 - the integer to pass to the 'exit' command
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_usage () {
|
||||
local -i result=${1:-0}
|
||||
|
||||
cat >$STDOUT <<-endusage
|
||||
${SCRIPT} - version: ${VERSION}
|
||||
|
||||
Usage: ./${SCRIPT} [-h] [-D] [-F] [-v] item
|
||||
|
||||
Attempts to repair an IA item where the upload has failed for some reason.
|
||||
|
||||
Options:
|
||||
-h Print this help.
|
||||
-d 0|1 Dry run: -d 1 (the default) runs the script in dry-run
|
||||
mode where nothing is changed but the actions that
|
||||
will be taken are reported; -d 0 turns off dry-run
|
||||
mode and the actions will be carried out.
|
||||
-D Run in debug mode where a lot more information is
|
||||
reported.
|
||||
-F Ignore (some) interlocks that will cause failure, such
|
||||
as the existence of the local cache directory for the
|
||||
item being processed.
|
||||
-v Run in verbose mode where more information is
|
||||
reported. Default is off.
|
||||
|
||||
Arguments:
|
||||
item The item in the form 'hpr1234'
|
||||
|
||||
endusage
|
||||
exit "$result"
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Directories and files
|
||||
#-------------------------------------------------------------------------------
|
||||
LOGS="$BASEDIR/logs"
|
||||
make_dir "${LOGS}"
|
||||
LOGFILE="$LOGS/$SCRIPT.log"
|
||||
|
||||
while getopts :d:DFhv opt
|
||||
do
|
||||
case "${opt}" in
|
||||
D) DEBUG=1;;
|
||||
d) DRYRUN=$OPTARG;;
|
||||
F) FORCE=1;;
|
||||
h) _usage 0;;
|
||||
v) VERBOSE=1;;
|
||||
*) echo "** Unknown option"
|
||||
_usage 1;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
#
|
||||
# Set option defaults and check their values
|
||||
#
|
||||
DRYRUN=${DRYRUN:-1}
|
||||
if [[ $DRYRUN -ne 0 && $DRYRUN -ne 1 ]]; then
|
||||
echo "** Use '-d 0' or '-d 1'"
|
||||
_usage 1
|
||||
fi
|
||||
[[ $DRYRUN -eq 1 ]] && echo "Dry run mode"
|
||||
|
||||
DEBUG=${DEBUG:-0}
|
||||
[[ $DEBUG -eq 1 ]] && coloured 'yellow' "Debug mode"
|
||||
|
||||
FORCE=${FORCE:-0}
|
||||
|
||||
VERBOSE=${VERBOSE:-0}
|
||||
|
||||
#
|
||||
# Should have one argument
|
||||
#
|
||||
if [[ $# != 1 ]]; then
|
||||
coloured 'red' "Missing argument"
|
||||
_usage 1
|
||||
fi
|
||||
item="${1}"
|
||||
|
||||
#
|
||||
# Ensure item spec is correctly formatted
|
||||
#
|
||||
if [[ $item =~ hpr([0-9]+) ]]; then
|
||||
printf -v item 'hpr%04d' "$((10#${BASH_REMATCH[1]}))"
|
||||
else
|
||||
coloured 'red' "Incorrect show specification: $item"
|
||||
coloured 'yellow' "Use 'hpr9999' format"
|
||||
exit 1
|
||||
fi
|
||||
_DEBUG "Parsed item: $item"
|
||||
|
||||
_log "$SCRIPT $VERSION ($(_ifbool "$DRYRUN" 'dry-run' 'live'))"
|
||||
|
||||
#
|
||||
# Having an entry for the show in 'ia.db' is important, so check there is one
|
||||
#
|
||||
SQL="select 1 from episodes where id = ${item:3}"
|
||||
if [[ $(sqlite3 -list "$IADB" "$SQL" 2>/dev/null) -ne 1 ]]; then
|
||||
coloured 'red' "Unable to find show $item in the local IA database"
|
||||
coloured 'yellow' "Can't continue"
|
||||
exit 1
|
||||
fi
|
||||
_verbose "$(coloured 'yellow' "Show $item is in the local IA database")"
|
||||
_log "Show $item is in the local IA database"
|
||||
|
||||
#
|
||||
# It's possible that the show upload failed before anything was uploaded, even
|
||||
# the metadata. It's never been seen, but it seems wise to cater for it.
|
||||
#
|
||||
# TODO: uncomment below; disabled for speed
|
||||
if ! ia metadata "$item" --exists > /dev/null 2>&1; then
|
||||
coloured 'red' "This item is not apparently on the IA; can't continue"
|
||||
exit 1
|
||||
fi
|
||||
_verbose "$(coloured 'yellow' "Show $item is on the IA")"
|
||||
_log "Show $item is on the IA"
|
||||
|
||||
#
|
||||
# Directory paths
|
||||
#
|
||||
FROMPARENTDIR="$BACKUP/public_html/eps"
|
||||
FROMDIR="$FROMPARENTDIR/$item"
|
||||
TOPARENTDIR="$REPAIRS/$item"
|
||||
TOASSETDIR="$TOPARENTDIR/$item"
|
||||
|
||||
#
|
||||
# RE to ignore certain files using 'grep -v -E ...'
|
||||
#
|
||||
IGNORE="($item\.(flac|mp3|ogg|opus|spx|wav)$)"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Check there are asset files on the backup disk before proceeding. At least
|
||||
# we need the transcripts. If no files at all we can't continue.
|
||||
#-------------------------------------------------------------------------------
|
||||
declare -a BACKUPFILES
|
||||
mapfile -t BACKUPFILES < \
|
||||
<(find "$FROMPARENTDIR" -type f -name "$item*" | grep -v -E "${IGNORE}")
|
||||
_DEBUG "$(coloured 'purple' "Backup files")" "${BACKUPFILES[@]}"
|
||||
|
||||
if [[ ! -d $FROMDIR || ${#BACKUPFILES[@]} -eq 0 ]]; then
|
||||
coloured 'red' "No files found in $FROMDIR"
|
||||
coloured 'red' "Can't continue!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_log "Files found on backup disk ${#BACKUPFILES[*]}"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Make the needed local cache directory for later
|
||||
#-------------------------------------------------------------------------------
|
||||
if [[ $FORCE -ne 1 && -e $TOPARENTDIR ]]; then
|
||||
coloured 'red' "Directory $TOPARENTDIR already exists; can't continue".
|
||||
coloured 'yellow' 'This implies that all files have been copied already.'
|
||||
coloured 'yellow' "If you're sure, consider running: '$REPIT -X -d0 $item'"
|
||||
coloured 'yellow' 'Otherwise, consider running again with option -F.'
|
||||
exit 1
|
||||
else
|
||||
if [[ $DRYRUN -eq 1 ]]; then
|
||||
coloured 'yellow' "Would have created directory $TOPARENTDIR"
|
||||
else
|
||||
mkdir -p "$TOASSETDIR"
|
||||
_verbose "$(coloured 'yellow' "Created directory $TOASSETDIR")"
|
||||
_log "Created directory $TOASSETDIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Collect asset data from the database
|
||||
#-------------------------------------------------------------------------------
|
||||
SQL="select filename from assets where episode_id = ${item:3}"
|
||||
declare -a IADBASSETS
|
||||
mapfile -t IADBASSETS < <(sqlite3 -list "$IADB" "$SQL" 2>/dev/null)
|
||||
_DEBUG "$(coloured 'purple' "SQLite IA DB files")" "${IADBASSETS[@]}"
|
||||
_log "Files found in ia.db ${#IADBASSETS[*]}"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Collect IA data, only original files generated by HPR. We exclude audio
|
||||
# files from this set.
|
||||
#-------------------------------------------------------------------------------
|
||||
JQPROG='.files[] | select(.source == "original" and .format != "Metadata" and '
|
||||
JQPROG+='.format != "Item Tile") | (.name) | @text'
|
||||
declare -a IAFILES
|
||||
mapfile -t IAFILES < \
|
||||
<(ia metadata "$item" | $JQ -r "$JQPROG" | grep -v -E "${IGNORE}")
|
||||
_DEBUG "$(coloured 'purple' "IA files (originals)")" "${IAFILES[@]}"
|
||||
_log "Files found on IA (originals) ${#IAFILES[*]}"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Work out whether to copy assets from the backup disk, or whether to move
|
||||
# files on the IA. Whatever we decide we also need to copy transcripts from
|
||||
# the backup disk and upload to the IA
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Check each asset from the $IADB database to see if it's on the IA. We'll get back
|
||||
# a path if it's where we want it, otherwise just a filename.
|
||||
#
|
||||
declare -a MOVES
|
||||
|
||||
coloured 'purple' "Checking IA files for moves"
|
||||
|
||||
#
|
||||
# If we find an asset by looking for its basename in the list of files we got
|
||||
# from the IA and if they are the same we need to move such files to the
|
||||
# sub-directory.
|
||||
#
|
||||
for asset in "${IAFILES[@]}"; do
|
||||
#
|
||||
# Skip IA files with directories
|
||||
#
|
||||
if [[ $asset =~ / ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
IA_match=$( grep "${asset}" <(printf '%s\n' "${IADBASSETS[@]}") )
|
||||
if [[ $IA_match = "$asset" ]]; then
|
||||
MOVES+=("$IA_match")
|
||||
fi
|
||||
done
|
||||
|
||||
#
|
||||
# If we found any moves then we can move them in the IA item now and copy the
|
||||
# files from the backup disk to the cache in case we need them. They will
|
||||
# eventually get deleted by 'cron'.
|
||||
#
|
||||
if [[ ${#MOVES[@]} -gt 0 ]]; then
|
||||
_DEBUG "$(coloured 'purple' "Files to be moved")" "${MOVES[@]}" "----"
|
||||
|
||||
mcount=0
|
||||
for asset in "${MOVES[@]}"; do
|
||||
# source & destination for IA moves
|
||||
iafrom="$item/$asset"
|
||||
iato="$item/$item/$asset"
|
||||
_DEBUG "\$iafrom: $iafrom" "\$iato: $iato" ""
|
||||
|
||||
#
|
||||
# If IA source and destination are the same no moves are needed. For
|
||||
# the local cache the later 'rsync' will be enough.
|
||||
#
|
||||
if [[ $iafrom != "$iato" ]]; then
|
||||
if [[ $DRYRUN -eq 1 ]]; then
|
||||
coloured 'yellow' "ia move $iafrom $iato --no-derive --no-backup"
|
||||
coloured 'yellow' "cp $FROMPARENTDIR/$asset $TOASSETDIR/"
|
||||
else
|
||||
#
|
||||
# Perform the move. If the retries are exceeded things get
|
||||
# complicated, so just abort so we can try again later.
|
||||
#
|
||||
_verbose "$(coloured 'blue' "Moving $iafrom → $iato on IA")"
|
||||
if _IA_move "$iafrom" "$iato"; then
|
||||
#
|
||||
# Update the cache (but only if the move occurred)
|
||||
#
|
||||
_verbose "$(coloured 'blue' "Copying from backup disk to cache")"
|
||||
cp "$FROMPARENTDIR/$asset" "$TOASSETDIR/"
|
||||
|
||||
((mcount++))
|
||||
else
|
||||
coloured 'red' "Retries exhausted. Aborting recovery"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
done
|
||||
#
|
||||
# Report what was done
|
||||
#
|
||||
coloured 'green' "Moved $mcount $(ngettext file files "$mcount")"
|
||||
_log "Moved $mcount $(ngettext file files "$mcount")"
|
||||
|
||||
else
|
||||
coloured 'yellow' "No moves needed"
|
||||
_log "No moves needed"
|
||||
fi
|
||||
|
||||
#
|
||||
# Wait for the IA moves to finish
|
||||
#
|
||||
if [[ $DRYRUN -eq 0 ]]; then
|
||||
if [[ $mcount -gt 0 ]]; then
|
||||
until [[ $(queued_tasks "$item") -eq 0 ]]; do
|
||||
coloured 'yellow' "Waiting for IA tasks to complete"
|
||||
sleep 1m
|
||||
done
|
||||
fi
|
||||
else
|
||||
if [[ $mcount -gt 0 ]]; then
|
||||
coloured 'yellow' "Would have waited for any IA tasks to complete"
|
||||
fi
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Copy files from the backup disk to the cache
|
||||
#-------------------------------------------------------------------------------
|
||||
if [[ $DRYRUN -eq 1 ]]; then
|
||||
coloured 'yellow' "Would have copied files from backup disk → cache"
|
||||
rsync -n -vaP --exclude=index.html "$FROMDIR" "$TOPARENTDIR"
|
||||
else
|
||||
rsync -vaP --exclude=index.html "$FROMDIR" "$TOPARENTDIR"
|
||||
_verbose "$(coloured 'yellow' "Copied files from $FROMDIR")"
|
||||
_log "Copied files from $FROMDIR"
|
||||
fi
|
||||
|
||||
# TODO: Is this needed?
|
||||
#
|
||||
# Put any source audio in the right place.
|
||||
#
|
||||
# if [[ $DRYRUN -eq 1 ]]; then
|
||||
# coloured 'yellow' "Would have moved source files if found"
|
||||
# else
|
||||
# #
|
||||
# # Turn on 'nullglob' to get an empty result if the glob expression doesn't
|
||||
# # match.
|
||||
# #
|
||||
# NG=$(shopt -p nullglob)
|
||||
# shopt -s nullglob
|
||||
#
|
||||
# #
|
||||
# # Any source files should be in repairs/hpr1234/ and should go to the IA
|
||||
# # in the comparable place. We will not put it on the HPR server though.
|
||||
# #
|
||||
# # TODO: Is this right?
|
||||
# movecount=0
|
||||
# for file in "$TOPARENTDIR"/*_source.*; do
|
||||
# if mv "$file" "$TOPARENTDIR"; then
|
||||
# ((movecount++))
|
||||
# fi
|
||||
# done
|
||||
#
|
||||
# eval "$NG"
|
||||
#
|
||||
# #
|
||||
# # Show the directories after any move
|
||||
# #
|
||||
# if [[ $movecount -gt 0 ]]; then
|
||||
# _verbose "$(coloured 'yellow' "Moved source file(s)")"
|
||||
# ls -lR "$REPAIRS/$item/"
|
||||
# fi
|
||||
#
|
||||
# fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Using the cache as the reference upload whatever is missing to the IA
|
||||
#-------------------------------------------------------------------------------
|
||||
if [[ $DRYRUN -eq 1 ]]; then
|
||||
coloured 'yellow' "Would have found and repaired missing files"
|
||||
else
|
||||
_verbose "$(coloured 'yellow' "Finding and repairing missing files")"
|
||||
_log "Finding and repairing missing files (with $REPIT)"
|
||||
"$REPIT" -X -d0 "$item"
|
||||
fi
|
||||
|
||||
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21:fdm=marker
|
||||
|
@ -15,15 +15,15 @@
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.6
|
||||
# VERSION: 0.0.7
|
||||
# CREATED: 2024-05-10 21:26:31
|
||||
# REVISION: 2024-07-10 15:12:54
|
||||
# REVISION: 2024-08-04 19:40:52
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
# set -o nounset # Treat unset variables as an error
|
||||
|
||||
VERSION="0.0.6"
|
||||
VERSION="0.0.7"
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
# DIR=${0%/*}
|
||||
@ -357,7 +357,7 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_DEBUG "$(printf '%s\n' "${iacache[@]}")"
|
||||
_DEBUG "IA cache" "${iacache[@]}"
|
||||
|
||||
#
|
||||
# Determine which files are assets
|
||||
@ -461,6 +461,10 @@ fi
|
||||
#-------------------------------------------------------------------------------
|
||||
# Compare the two asset lists and return what's missing on the HPR server
|
||||
#-------------------------------------------------------------------------------
|
||||
# TODO: This algorithm does not handle the instance where there are pictures
|
||||
# in one directory and a lower directory containing thumbnails, AND THE FILE
|
||||
# NAMES ARE THE SAME!
|
||||
#
|
||||
declare -a missing
|
||||
find_missing ia_asset hpr_asset missing
|
||||
_verbose "$(coloured 'cyan' "** missing (${#missing[@]}):")"
|
||||
@ -471,7 +475,8 @@ if [[ ${#missing[@]} -eq 0 ]]; then
|
||||
_log "No missing assets detected; nothing to do"
|
||||
exit
|
||||
else
|
||||
coloured 'yellow' "Found ${#missing[@]} files missing on the HPR server"
|
||||
coloured 'yellow' \
|
||||
"Found ${#missing[@]} $(ngettext file files ${#missing[@]}) missing on the HPR server"
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -548,6 +553,10 @@ fi
|
||||
#-------------------------------------------------------------------------------
|
||||
# Synchronise assets to the directory
|
||||
#-------------------------------------------------------------------------------
|
||||
# We perform an 'rsync' over 'ssh' to synchronise files from
|
||||
# ~/HPR/InternetArchive/assets/hprXXXX/files/hprXXXX to
|
||||
# public_html/eps/hprXXXX (on the HPR server)
|
||||
#
|
||||
# shellcheck disable=SC2059 disable=SC2089
|
||||
printf -v command "$RSYNCTPL" "$LOCAL_PARENTDIR/" "$REMOTE_PARENTDIR/"
|
||||
|
||||
|
@ -6,19 +6,24 @@
|
||||
# USAGE: ./repair_item [-h] [-v] [-d {0|1}] [-D] [-l N] [-X] itemname
|
||||
#
|
||||
# DESCRIPTION: Repairs an IA "item" (HPR show) if something has failed during
|
||||
# the upload.
|
||||
# the upload (and when recovering deleted files from the
|
||||
# changeover to the HPR static site).
|
||||
#
|
||||
# The most common failures are caused by the file upload
|
||||
# processes timing out and being aborted (by the 'ia' tool which
|
||||
# performs the item creation and the uploads). This failure
|
||||
# means that a show being processed on 'borg' does not get all
|
||||
# of the components loaded to the IA.
|
||||
# of the components loaded to the IA. This happens during the
|
||||
# sequence of running the 'make_metadata' Perl script which
|
||||
# generates a CSV file of show data, followed by 'ia metadata
|
||||
# --spreadsheet=<CSV file>'. Failures in the second part cause
|
||||
# it to be aborted
|
||||
#
|
||||
# This script looks at the files belonging to the show (stored
|
||||
# temporarily on 'borg') and determines which have not been
|
||||
# uploaded, then takes steps to perform the uploads.
|
||||
#
|
||||
# Version 0.0.10 onwards has the capability to repair an IA item
|
||||
# Version 0.0.11 onwards has the capability to repair an IA item
|
||||
# from the HPR backup disk. This seems to be necessary because
|
||||
# the transcripts were not carried over (although we are
|
||||
# adding them to the IA for new shows now, older ones were never
|
||||
@ -30,20 +35,24 @@
|
||||
# source file is in the upper one. This emulates the placement
|
||||
# on the IA itself.
|
||||
#
|
||||
# This script can be called directly to recover a new show which
|
||||
# failed during creation/upload, or by 'recover_transcripts'
|
||||
# which is repairing shows with missing assets.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.10
|
||||
# VERSION: 0.0.11
|
||||
# CREATED: 2020-01-05 22:42:46
|
||||
# REVISION: 2024-07-12 14:39:38
|
||||
# REVISION: 2024-07-20 17:06:10
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
#set -o nounset # Treat unset variables as an error
|
||||
|
||||
VERSION="0.0.10"
|
||||
VERSION="0.0.11"
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
# DIR=${0%/*}
|
||||
@ -55,6 +64,7 @@ STDOUT="/dev/fd/2"
|
||||
#
|
||||
case $(hostname) in
|
||||
i7-desktop)
|
||||
# TODO: consider not allowing this to be run anywhere but on 'borg'
|
||||
BASEDIR="$HOME/HPR/InternetArchive"
|
||||
UPLOADS="$HOME/HPR/IA/uploads"
|
||||
REPAIRS="$BASEDIR/repairs"
|
||||
@ -100,7 +110,7 @@ TMP1=$(mktemp) || { echo "$SCRIPT: creation of temporary file failed!"; exit 1;
|
||||
trap 'cleanup_temp $TMP1' SIGHUP SIGINT SIGPIPE SIGTERM EXIT
|
||||
|
||||
|
||||
# {{{ -- Functions -- Upload, exists_in, queued_tasks, _DEBUG, _usage
|
||||
# {{{ -- Functions -- Upload, exists_in, queued_tasks, _usage
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: Upload
|
||||
@ -174,19 +184,6 @@ queued_tasks () {
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _DEBUG
|
||||
# DESCRIPTION: Writes a message if in DEBUG mode
|
||||
# PARAMETERS: List of messages
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_DEBUG () {
|
||||
[ "$DEBUG" == 0 ] && return
|
||||
for msg in "$@"; do
|
||||
printf 'D> %s\n' "$msg"
|
||||
done
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _usage
|
||||
# DESCRIPTION: Reports usage; always exits the script after doing so
|
||||
@ -297,10 +294,11 @@ fi
|
||||
item="${1}"
|
||||
|
||||
#
|
||||
# Ensure item spec is correctly formatted
|
||||
# Ensure item spec is correctly formatted. Have to cater for leading zeroes
|
||||
# being interpreted as octal.
|
||||
#
|
||||
if [[ $item =~ hpr([0-9]+) ]]; then
|
||||
printf -v item 'hpr%04d' "${BASH_REMATCH[1]}"
|
||||
printf -v item 'hpr%04d' "$((10#${BASH_REMATCH[1]}))"
|
||||
else
|
||||
coloured 'red' "Incorrect show specification: $item"
|
||||
coloured 'yellow' "Use 'hpr9999' format"
|
||||
@ -310,7 +308,7 @@ _DEBUG "Parsed item: $item"
|
||||
|
||||
#
|
||||
# It's possible that the show upload failed before anything was uploaded, even
|
||||
# the metadata. It's never been seen, but it seems wise to cater for it.
|
||||
# the metadata. It's rarely seen, but it seems wise to cater for it.
|
||||
#
|
||||
if ! ia metadata "$item" --exists > /dev/null 2>&1; then
|
||||
coloured 'red' "This item is not apparently on the IA; can't continue"
|
||||
@ -323,7 +321,7 @@ fi
|
||||
# mysteriously vanished from the IA. The directories here are equivalent to
|
||||
# those used by 'repair_assets'. There is a top-level directory the represents
|
||||
# the IA item, and below that a hierarchy defining placement under the item.
|
||||
# There is a 'repairs' directory per host in case we need to preair IA stuff
|
||||
# There is a 'repairs' directory per host in case we need to repair IA stuff
|
||||
# from elsewhere.
|
||||
#
|
||||
if [[ $EXTENDED -eq 1 ]]; then
|
||||
|
197
InternetArchive/snapshot_metadata
Executable file
197
InternetArchive/snapshot_metadata
Executable file
@ -0,0 +1,197 @@
|
||||
#!/bin/bash -
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: snapshot_metadata
|
||||
#
|
||||
# USAGE: ./snapshot_metadata episode_number
|
||||
#
|
||||
# DESCRIPTION: Collects metadata from the IA for a given show and stores it
|
||||
# in the cache.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.2
|
||||
# CREATED: 2024-08-16 20:36:51
|
||||
# REVISION: 2024-08-17 10:31:15
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
set -o nounset # Treat unset variables as an error
|
||||
|
||||
VERSION="0.0.2"
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
# DIR=${0%/*}
|
||||
|
||||
STDOUT="/dev/fd/2"
|
||||
|
||||
#
|
||||
# Select the appropriate working directory for the host
|
||||
#
|
||||
case $(hostname) in
|
||||
i7-desktop)
|
||||
BASEDIR="$HOME/HPR/InternetArchive"
|
||||
;;
|
||||
borg)
|
||||
BASEDIR="$HOME/IA"
|
||||
;;
|
||||
*)
|
||||
echo "Wrong host!"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
cd "$BASEDIR" || { echo "Failed to cd to $BASEDIR"; exit 1; }
|
||||
|
||||
#
|
||||
# Load library functions
|
||||
#
|
||||
LIB="$HOME/HPR/function_lib.sh"
|
||||
[ -e "$LIB" ] || { echo "Unable to source functions"; exit; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$LIB"
|
||||
|
||||
#
|
||||
# Enable coloured messages
|
||||
#
|
||||
define_colours
|
||||
|
||||
#
|
||||
# Sanity checks
|
||||
#
|
||||
IA=$(command -v ia)
|
||||
[ -n "$IA" ] || { echo "Program 'ia' was not found"; exit 1; }
|
||||
VIEWD="$BASEDIR/view_derivatives"
|
||||
[ -e "$VIEWD" ] || { echo "Program '$VIEWD' was not found"; exit 1; }
|
||||
|
||||
# {{{ -- Functions -- _usage
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: make_dir
|
||||
# DESCRIPTION: Make a directory if it doesn't exist, failing gracefully on
|
||||
# errors.
|
||||
# PARAMETERS: $1 directory path
|
||||
# RETURNS: True if success, otherwise exits the caller script
|
||||
#===============================================================================
|
||||
make_dir () {
|
||||
local dir="${1}"
|
||||
|
||||
if [[ ! -d $dir ]]; then
|
||||
mkdir -p "$dir" || {
|
||||
coloured 'red' "Failed to create $dir"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _usage
|
||||
# DESCRIPTION: Reports usage; always exits the script after doing so
|
||||
# PARAMETERS: 1 - the integer to pass to the 'exit' command
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_usage () {
|
||||
local -i result=${1:-0}
|
||||
|
||||
cat >$STDOUT <<-endusage
|
||||
${SCRIPT} - version: ${VERSION}
|
||||
|
||||
Usage: ./${SCRIPT} showid
|
||||
|
||||
Collects notes for a show and adds them to the cache directory
|
||||
|
||||
Arguments:
|
||||
showid The show id in the form 'hpr1234'
|
||||
|
||||
endusage
|
||||
exit "$result"
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Argument check
|
||||
#-------------------------------------------------------------------------------
|
||||
# Should have one argument
|
||||
#
|
||||
if [[ $# != 1 ]]; then
|
||||
coloured 'red' "Missing argument"
|
||||
_usage 1
|
||||
fi
|
||||
show="${1,,}"
|
||||
|
||||
#
|
||||
# Ensure show id is correctly formatted. We want it to be 'hpr1234'
|
||||
#
|
||||
if [[ $show =~ (hpr)?([0-9]+) ]]; then
|
||||
printf -v show 'hpr%04d' "${BASH_REMATCH[2]}"
|
||||
else
|
||||
coloured 'red' "Incorrect show specification: $show"
|
||||
coloured 'yellow' "Use 'hpr9999' or '9999' format"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Setting up paths
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# CACHEDIR is where we store asset details and files
|
||||
#
|
||||
CACHEDIR="$BASEDIR/assets"
|
||||
[ ! -d "$CACHEDIR" ] && {
|
||||
coloured 'red' "Creating cache directory"
|
||||
make_dir "$CACHEDIR"
|
||||
}
|
||||
|
||||
#
|
||||
# Pointers into the cache:
|
||||
# LOCAL_ASSETDIR - where the cache for this show lives
|
||||
#
|
||||
LOCAL_ASSETDIR="$CACHEDIR/${show}"
|
||||
[ ! -d "$LOCAL_ASSETDIR" ] && {
|
||||
coloured 'green' "Creating cache directory for $show"
|
||||
make_dir "$LOCAL_ASSETDIR"
|
||||
}
|
||||
|
||||
METADATA="$CACHEDIR/$show/metadata.json"
|
||||
DERIVED="$CACHEDIR/$show/derived.lis"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Save the IA metadata unless we already have the file
|
||||
#-------------------------------------------------------------------------------
|
||||
if [[ ! -e $METADATA ]]; then
|
||||
if ia metadata "$show" > "$METADATA"; then
|
||||
coloured 'green' "Created metadata file"
|
||||
if [[ ! -s $METADATA ]]; then
|
||||
coloured 'red' "Metadata file is empty"
|
||||
fi
|
||||
else
|
||||
coloured 'red' "Creation of metadata file failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
coloured 'yellow' "Metadata already exists, not replacing it"
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Use the collected metadata to view the state of the IA, and collect the derived file names
|
||||
#-------------------------------------------------------------------------------
|
||||
coloured 'blue' "Viewing IA files"
|
||||
"$VIEWD" -verb "$METADATA"
|
||||
|
||||
if "$VIEWD" -list "$METADATA" > "$DERIVED"; then
|
||||
nfiles="$(wc -l < "$DERIVED")"
|
||||
coloured 'green' "Saved 'derived' files for show $show ($nfiles)"
|
||||
else
|
||||
coloured 'red' "Creation of $DERIVED file failed"
|
||||
fi
|
||||
|
||||
exit
|
||||
|
||||
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21:fdm=marker
|
@ -13,15 +13,15 @@
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.10
|
||||
# VERSION: 0.0.11
|
||||
# CREATED: 2022-03-30 17:38:01
|
||||
# REVISION: 2022-07-30 14:30:43
|
||||
# REVISION: 2024-07-29 18:24:26
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
set -o nounset # Treat unset variables as an error
|
||||
|
||||
VERSION="0.0.10"
|
||||
VERSION="0.0.11"
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
# DIR=${0%/*}
|
||||
@ -55,6 +55,8 @@ case $HOSTNAME in
|
||||
*) echo "Wrong host!"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# {{{ -- Functions -- exists_in, queued_tasks, movefile, is_empty, _log, _usage
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: exists_in
|
||||
# DESCRIPTION: Checks the existence of a key in an associative array
|
||||
@ -99,9 +101,12 @@ queued_tasks () {
|
||||
# RETURNS: True if a move was done, otherwise False
|
||||
#===============================================================================
|
||||
movefile () {
|
||||
local fromdir="${1:?Usage: movefile fromdir todir path}"
|
||||
local todir="${2:?Usage: movefile fromdir todir path}"
|
||||
local path="${3:?Usage: movefile fromdir todir path}"
|
||||
local fromdir="${1:?Usage: movefile fromdir todir path [FORCE]}"
|
||||
local todir="${2:?Usage: movefile fromdir todir path [FORCE]}"
|
||||
local path="${3:?Usage: movefile fromdir todir path [FORCE]}"
|
||||
local FORCE="${4:-0}"
|
||||
|
||||
[[ ! -v FORCE ]] && FORCE=0
|
||||
|
||||
#
|
||||
# Chop up the path. If it's just a file name then $dir and $file are the
|
||||
@ -126,8 +131,16 @@ movefile () {
|
||||
# TODO: Compare the two files?
|
||||
#
|
||||
if [[ -e $todir/$path ]]; then
|
||||
echo "File already exists: $todir/$path"
|
||||
return 1
|
||||
if [[ $FORCE -eq 1 ]]; then
|
||||
echo "File exists: $todir/$path"
|
||||
echo "FORCE mode is ON so overwriting"
|
||||
mv --force "$fromdir/$path" "$todir/$path"
|
||||
echo "Moved $fromdir/$path"
|
||||
return 0
|
||||
else
|
||||
echo "File already exists: $todir/$path"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
mv "$fromdir/$path" "$todir/$path"
|
||||
echo "Moved $fromdir/$path"
|
||||
@ -147,16 +160,28 @@ is_empty() {
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _DEBUG
|
||||
# DESCRIPTION: Writes a message if in DEBUG mode
|
||||
# PARAMETERS: List of messages
|
||||
# NAME: _log
|
||||
# DESCRIPTION: Writes a log record to the predefined $LOGFILE in this script
|
||||
# using the predefined $LOGREC, a template for 'printf'. If the
|
||||
# latter is not defined the function will use a default.
|
||||
# For some reason 'shellcheck' objects to this function. The
|
||||
# first argument to 'printf' needs to be -1 to make the
|
||||
# '%(fmt)T' use today's date and time.
|
||||
# PARAMETERS: 1 - the message to write
|
||||
# RETURNS: Nothing
|
||||
#===============================================================================
|
||||
_DEBUG () {
|
||||
[ "$DEBUG" == 0 ] && return
|
||||
for msg in "$@"; do
|
||||
printf 'D> %s\n' "$msg"
|
||||
done
|
||||
# shellcheck disable=SC2317 disable=SC2059
|
||||
_log () {
|
||||
local msg="$1"
|
||||
|
||||
# echo "D> $LOGFILE $LOGREC"
|
||||
[ -v LOGFILE ] || { echo "${FUNCNAME[0]}: \$LOGFILE is not defined"; exit 1; }
|
||||
[ -v LOGREC ] || { local LOGREC='%(%F %T)T %s\n'; }
|
||||
|
||||
# echo "D> $LOGFILE $LOGREC"
|
||||
printf "$LOGREC" -1 "$msg" >> "$LOGFILE"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
@ -189,6 +214,11 @@ Options:
|
||||
to stop at.
|
||||
-D Run in debug mode where a lot more information is
|
||||
reported
|
||||
-F Turn on FORCE mode (normally off). In this mode when
|
||||
the files being tidied (moved) already exist, they are
|
||||
overwritten. This is for the very rare case when
|
||||
a show's audio has to be re-uploaded because of bad
|
||||
audio or the wrong file being sent.
|
||||
|
||||
Examples
|
||||
./tidy_uploaded # Run in (default) dry-run mode
|
||||
@ -196,11 +226,14 @@ Examples
|
||||
./tidy_uploaded -d0 # Live mode (without verbose messages)
|
||||
./tidy_uploaded -c1 # Process 1 show in dry-run mode
|
||||
./tidy_uploaded -D # Run with debugging enabled
|
||||
./tidy_uploaded -F # Run with FORCE mode on
|
||||
|
||||
endusage
|
||||
exit "$res"
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
@ -208,16 +241,18 @@ endusage
|
||||
#
|
||||
LOGS="$BASEDIR/logs"
|
||||
LOGFILE="$LOGS/$SCRIPT.log"
|
||||
LOGREC='%(%F %T)T %s\n'
|
||||
|
||||
#
|
||||
# Process options
|
||||
#
|
||||
while getopts :c:d:Dhv opt
|
||||
while getopts :c:d:DFhv opt
|
||||
do
|
||||
case "${opt}" in
|
||||
c) COUNT=$OPTARG;;
|
||||
D) DEBUG=1;;
|
||||
d) DRYRUN=$OPTARG;;
|
||||
F) FORCE=1;;
|
||||
h) _usage 0;;
|
||||
v) VERBOSE=1;;
|
||||
*) echo "** Unknown option"
|
||||
@ -239,6 +274,9 @@ if [[ $DRYRUN -ne 0 && $DRYRUN -ne 1 ]]; then
|
||||
fi
|
||||
[[ $DRYRUN -eq 1 ]] && echo "Dry run mode"
|
||||
|
||||
FORCE=${FORCE:-0}
|
||||
[[ $FORCE -eq 1 ]] && echo "Force mode - overwriting existing files"
|
||||
|
||||
VERBOSE=${VERBOSE:-0}
|
||||
|
||||
DEBUG=${DEBUG:-0}
|
||||
@ -361,12 +399,17 @@ while read -r path; do
|
||||
#
|
||||
# A file on the IA exists in the upload area. Move the
|
||||
# local one if we're not in dry-run mode, otherwise just
|
||||
# report the move we would do.
|
||||
# report the move we would do. If FORCE mode is on
|
||||
# overwrite the file.
|
||||
#
|
||||
if [[ $DRYRUN -eq 0 ]]; then
|
||||
movefile "$UPLOADS" "$ARCHIVE" "$file" && ((moves++))
|
||||
movefile "$UPLOADS" "$ARCHIVE" "$file" "$FORCE" && ((moves++))
|
||||
else
|
||||
printf 'Would move %s\n\tto %s\n' "$frompath" "$topath"
|
||||
if [[ $FORCE -eq 0 ]]; then
|
||||
printf 'Would move %s\n\tto %s\n' "$frompath" "$topath"
|
||||
else
|
||||
printf 'Would move %s\n\toverwriting %s\n' "$frompath" "$topath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done < "$TMP1"
|
||||
|
@ -33,11 +33,12 @@
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
use 5.010;
|
||||
use v5.36;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
#use experimental 'smartmatch';
|
||||
# TODO: use experimental::try;
|
||||
|
||||
use match::smart;
|
||||
|
||||
|
@ -8,6 +8,9 @@
|
||||
# DESCRIPTION: Run the commands necessary to upload a batch of HPR shows to
|
||||
# archive.org
|
||||
#
|
||||
# ** NOW OBSOLETE **
|
||||
# We do uploads differently now.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
@ -19,6 +22,9 @@
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
echo "Obsolete script. Do not use!"
|
||||
cmd='exit'; $cmd
|
||||
|
||||
set -o nounset # Treat unset variables as an error
|
||||
|
||||
SCRIPT=${0##*/}
|
||||
|
Loading…
Reference in New Issue
Block a user