fsfe-website/tools/tagtool/tagtool.sh
Johannes Zarl-Zierl ad5d21aaca tagtool: allow removing empty content attribute.
AFAICS, empty content attributes are safe to remove.
2019-05-26 12:52:56 +02:00

205 lines
4.5 KiB
Bash
Executable File

#!/bin/bash
# Tools to transform the tag data by bulk.
# Copyright (C) 2019 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
###
VERBOSE=0
NO_ACT=0
print_help()
{
cat <<EOF >&2
Usage: tagstool [-n|--no-act] [-v|--verbose] -b|--bulk-process TAGSDATAFILE
tagstool [-n|--no-act] [-v|--verbose] --remove-empty
Transform tag data by bulk.
Options:
-n|--no-act Don't perform any changes.
-v|--verbose Add verbose output of changes.
Actions (only one action per invocation):
-b|--bulk TAGSDATAFILE Transform bulk transformations a defined in the
csv file. See README.md for details.
Available transformations:
- rm: delete tag
- mv:newtag: move the tag to a newtag
--remove-empty Remove empty content attribute for tags.
EOF
}
performAction()
# performAction CMD ARGS..
# Perform the given command, if NO_ACT is not set.
# If VERBOSE is set, also print the command.
# Please use this for all actions that perform a change on the data!
{
if [[ VERBOSE -eq 1 ]]
then
echo "${@@Q}" >&2
fi
if [[ NO_ACT -eq 1 ]]
then
echo "NOT calling $1..." >&2
else
"$@"
fi
}
findTaggedFiles()
# findTaggedFiles TAG_ID
# grep for files containing the tag
{
local tagId="$1"
git grep -i -l ">$tagId</tag>"
}
renameTag()
# renameTag OLD NEW
# rename the tag using case-insensitive matching in all files.
{
local oldTagId="$1"
local newTagId="$2"
echo "Renaming tag $oldTagId to $newTagId..." >&2
for f in $(findTaggedFiles "$oldTagId")
do
echo " $f" >&2
if ! performAction sed -E -i "s;>\W*$oldTagId\W*</tag>;>$newTagId</tag>;i" "$f"
then
echo "ERROR!" >&2
return 1
fi
done
}
removeTag()
# removeTag TAG
# remove the tag id in all files
# this will result in additional empty lines
{
local tagId="$1"
echo "Deleting tag $tagId..." >&2
for f in $(findTaggedFiles "$oldTagId")
do
echo " $f" >&2
if ! performAction sed -E -i "s;\W*<tag\W*content=\"[^\"]*\"\W*>\W*$TagId\W*</tag>\W*;;i" "$f"
then
echo "ERROR!" >&2
return 1
fi
done
}
process_action()
# process a single csv action line from stdin and call the appropriate method
{
IFS=";" read action name id section count || return 2
# ignore empty actions
if [[ -z "$action" ]]
then
return 0
fi
case "$action" in
rm)
removeTag "$id"
;;
mv:*)
renameTag "$id" "${action/mv:/}"
;;
*)
echo "Ignoring action: $action on tag $section/$id" >&2
;;
esac
}
process_actions()
{
read firstline
if [[ "$firstline" != "action;name;id;section;count" ]]
then
echo "Input data does not look like it contains the right columns. Bailing out..." >&2
exit 1
fi
while process_action
do
true
done
}
do_bulk()
# do_bulk TAGSDATAFILE
# perform a bulk action based on data in the given tags data csv file.
{
local TAGSDATAFILE="$1"
if [[ ! -f "$TAGSDATAFILE" ]]
then
echo "No data file. Please read the source for help..." >&2
return 1
fi
process_actions < "$TAGSDATAFILE"
}
do_removeEmpty()
# removeEmpty
{
echo "Removing empty 'content' attribute from tags..." >&2
for f in $(git grep -Eil '<tag\W+content="\W*"\W*>')
do
echo " $f" >&2
performAction sed -E -i 's;<tag\W+content="\W*"\W*>;<tag>;g' "$f"
done
}
###
# Parse commandline:
###
TEMP=`getopt -o hbvn --long help,bulk-process,verbose,no-act,remove-empty \
-n 'tagtool' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-b|--bulk-process) ACTION=do_bulk ; shift ;;
-h|--help) print_help ; exit ;;
-n|--no-act) NO_ACT=1 ; shift ;;
--remove-empty) ACTION=do_removeEmpty ; shift ;;
-v|--verbose) VERBOSE=1 ; shift ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
###
# Perform action:
###
if [ -z "$ACTION" ]
then
echo "No action chosen!" >&2
print_help
exit 1
fi
"$ACTION" "$@"