misc/vote: pointy-hatting

Pointy hat:	tcberner
2023Q1
Tobias C. Berner 2022-11-11 21:35:48 +01:00
parent 37cf0da23d
commit 4d04b78b33
2 changed files with 0 additions and 778 deletions

View File

@ -1,55 +0,0 @@
From 33a1a9ccf0df2fc73cd8d85ab4bcdbf585dce94b Mon Sep 17 00:00:00 2001
From: "Tobias C. Berner" <tcberner@FreeBSD.org>
Date: Fri, 11 Nov 2022 21:10:34 +0100
Subject: [PATCH] misc/vote: cleanup port
Reported by: diizzy
---
misc/vote/Makefile | 12 +++++++++---
misc/vote/distinfo | 6 +++---
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/misc/vote/Makefile b/misc/vote/Makefile
index 9f9a4b897479..e851900e94c7 100644
--- a/misc/vote/Makefile
+++ b/misc/vote/Makefile
@@ -1,16 +1,22 @@
PORTNAME= vote
-DISTVERSION= 1.1
+DISTVERSION= 1.2
CATEGORIES= misc
-MASTER_SITES= https://codeberg.org/tcberner/${PORTNAME}/archive/
+MASTER_SITES= https://codeberg.org/tcberner/${PORTNAME}/raw/v${DISTVERSION}/
+DISTFILES= ${PORTNAME}
+DIST_SUBDIR= vote-${DISTVERSION}
+EXTRACT_ONLY=
MAINTAINER= tcberner@FreeBSD.org
COMMENT= Transparent git based voting system
+LICENSE= BSD2CLAUSE
+
+NO_ARCH= yes
NO_BUILD= yes
PLIST_FILES= bin/vote
do-install:
- ${INSTALL_SCRIPT} ${WRKDIR}/vote/vote ${STAGEDIR}${PREFIX}/bin
+ ${INSTALL_SCRIPT} ${DISTDIR}/${DIST_SUBDIR}/vote ${STAGEDIR}${PREFIX}/bin
.include <bsd.port.mk>
diff --git a/misc/vote/distinfo b/misc/vote/distinfo
index d9414c8ce104..05be2b48d93c 100644
--- a/misc/vote/distinfo
+++ b/misc/vote/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1668195518
-SHA256 (vote-1.1.tar.gz) = de2ad0d28cf777239fdb7e6c7c44a5dda528283bef6b807ade5ca02246497705
-SIZE (vote-1.1.tar.gz) = 5196
+TIMESTAMP = 1668197328
+SHA256 (vote-1.2/vote) = 4c0769cd4ea4578f4d72377afd1404ae0cc08cd8008486557aa4f17eadbeca0e
+SIZE (vote-1.2/vote) = 16615
--
2.38.1

View File

@ -1,723 +0,0 @@
#!/bin/sh
VERSION=1.0
#
# Simple git based voting system
#
# if $VOTE_DIR is no defined the checkout happens in the shell-script directory
#
# To setup a new shared VOTE_DIR, use:
# freefall> git init --bare /path/to/votes.git
# local> git clone freefall:/path/to/votes.git votes
# local> cd votes
# local> git checkout -b main
# Create the voters file (username:Name <email>)
# local> git add voters
# local> git commit -m "Initialize votes directory"
# local> git push -u origin main:main
#
#
# The mark_* and color_* values can be overriden in ~/.voterc
#
col_reset="\033[0m"
# Color used to to show the output of shelled-out git calls.
col_git="\033[32m"
# Color for highlights within the script
col_highlight="\033[33m"
mark_ys="👍"
mark_no="👎"
mark_ab="💁"
mark_dn="💤"
mark_op="🔓"
mark_cl="🔒"
###
base_dir="$(dirname $(realpath $0))"
vote_dir="${VOTE_DIR:-${base_dir}/votes}"
###
text_ys="y"
text_no="n"
text_ab="a"
text_dn="-"
text_op="o"
text_op="c"
###
if [ -f ~/.voterc ] ; then
. ~/.voterc ;
fi
###
__message () {
echo -e "$@"
}
__error () {
echo -e "$@" >&2
exit 1
}
__usage() {
__error "No command given. Available commands are:\n\n" \
"- help\t\tShow this message:\n" \
"\t\t${col_highlight}% vote help${col_reset}\n\n" \
"- init\t\tInitialize a repository:\n" \
"\t\t${col_highlight}% vote init <url>${col_reset}\n" \
"- update\tUpdate the repository:\n" \
"\t\t${col_highlight}% vote update${col_reset}\n\n" \
"- list\t\tList current ongoing votes:\n" \
"\t\t${col_highlight}% vote list${col_reset}\n" \
"- all\t\tList all votes:\n" \
"\t\t${col_highlight}% vote all${col_reset}\n" \
"- info\t\tShow information on a vote:\n" \
"\t\t${col_highlight}% vote info <vid>${col_reset}\n\n" \
"- create\tCreate a new vote:\n" \
"\t\t${col_highlight}% vote create <subject> <duedate> <further description>${col_reset}\n" \
"- close\tMark a vote as closed:\n" \
"\t\t${col_highlight}% vote close <vid>${col_reset}\n" \
"- reopen\tReopen a vote:\n" \
"\t\t${col_highlight}% vote reopen <vid>${col_reset}\n\n" \
"- changedate\tChange the Due Date to something new\n" \
"\t\t${col_highlight}% vote changedate <vid> <date>${col_reset}\n" \
"- changesubject\tChange the Subject to something new\n" \
"\t\t${col_highlight}% vote changesubject <vid> <subject>${col_reset}\n\n" \
"- vote\t\tPlace a vote:\n" \
"\t\t${col_highlight}% vote vote <vid> <yes/no/abstain>${col_reset}\n" \
"- votefor\tPlace a vote for another person:\n" \
"\t\t${col_highlight}% vote votefor <vid> <yes/no/abstain> <voter>${col_reset}\n\n" \
"The checkout directory can be overridden using then ${col_highlight}VOTE_DIR${col_reset}\n" \
"\n" \
"Vote version ${VERSION}."
}
__want_args() {
local count=$1
shift
if [ $# -ne ${count} ] ; then
__error "Expected ${count} arguments, but got $#."
fi
}
__username () {
__want_args 1 "$@"
local vote_dir="$1"
username=$(git -C ${vote_dir} config user.email | awk -F '@' '{print $1}')
if [ $? -eq 0 ] ; then
echo "${username}"
return 0
fi
__error "Could not evaluate git user name"
}
__setup_voters() {
__want_args 2 "$@"
local votes_dir="$1"
local voters="$2"
if [ -d ${votes_dir} ] ; then
if [ -f ${voters} ] ; then
for voter in $(awk -F ':' '{print $1}' ${voters}) ; do
ln -s zzz ${votes_dir}/${voter}
done
fi
fi
}
# Managing votes
create_vote () {
__want_args 4 "$@"
local vote_dir="$1"
update_votes "${vote_dir}"
local subject="$2"
local duedate="$3"
local description="$4"
if [ $? -ne 0 ] ; then
__error "Could not update votes prior to creation"
fi
local vid=$(__next_vid "${vote_dir}")
local voters=$(awk -F ':' 'BEGIN{OFS=":"}{print " ",$0}' ${vote_dir}/voters | column -t -s ':')
local commit_message=$(printf "<${vid}> [CREATE] ${subject} (${duedate})\n\n${description}\n\nVoters:\n${voters}\n")
echo -e "${col_git}"
cd ${vote_dir} && \
mkdir -p ${vid} && \
cd ${vid} && \
echo "${subject}" > subject && \
echo "${duedate}" > duedate && \
echo "${description} " > description && \
mkdir votes && \
__setup_voters $(realpath votes) $(realpath ${vote_dir}/voters) && \
git add subject duedate description votes && \
git commit -m "${commit_message}" && \
git push
echo -e "${col_reset}"
__message ""
__pretty_print ${vote_dir} ${vid}
}
change_date () {
__want_args 3 "$@"
local vote_dir="$1"
update_votes "${vote_dir}"
local vid=$(__make_vid "$2")
local newdate="$3"
open=$(__is_open_vote ${vote_dir} ${vid})
if [ $? -ne 0 ] ; then
__error "Cannot modify a closed vote. ${vote_dir} ${vid}"
fi
local olddate=$(cat ${vote_dir}/${vid}/duedate)
local commit_message=$(printf "<${vid}> [CHANGE DATE] ${subject} (${olddate}->${newdate})\n")
echo -e "${col_git}"
cd ${vote_dir} && \
cd ${vid} && \
echo "${newdate}" > duedate && \
git add duedate && \
git commit -m "${commit_message}" && \
git push
echo -e "${col_reset}"
list_votes ${vote_dir}
}
change_subject () {
__want_args 3 "$@"
local vote_dir="$1"
update_votes "${vote_dir}"
local vid=$(__make_vid "$2")
local newsubject="$3"
open=$(__is_open_vote ${vote_dir} ${vid})
if [ $? -ne 0 ] ; then
__error "Cannot modify a closed vote. ${vote_dir} ${vid}"
fi
local oldsubject=$(cat ${vote_dir}/${vid}/subject)
local commit_message=$(printf "<${vid}> [CHANGE DATE] ${oldsubject} -> ${newsubject}\n")
echo -e "${col_git}"
cd ${vote_dir} && \
cd ${vid} && \
echo "${newsubject}" > subject && \
git add subject && \
git commit -m "${commit_message}" && \
git push
echo -e "${col_reset}"
list_votes ${vote_dir}
}
info_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
__pretty_print ${vote_dir} ${vid}
}
__is_open_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
if [ -f ${vote_dir}/${vid}/closeddate ] ; then
return 1
fi
return 0
}
__set_vote() {
__want_args 4 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
local username="$3"
local value="$4"
open=$(__is_open_vote ${vote_dir} ${vid})
if [ $? -ne 0 ] ; then
__error "Cannot vote on a closed vote. ${vote_dir} ${vid}"
fi
if [ ! -L ${vote_dir}/${vid}/votes/${username} ] ; then
__error "Invalid voter ${username}"
fi
local target=""
case "${value}" in
"yes") target="yes" ;;
"no") target="no" ;;
"abstain") target="abstain" ;;
*) __error "Invalid vote '${value}' (valid: yes, no, abstain)" ;;
esac
result=$(cd ${vote_dir}/${vid}/votes && ln -sf ${value} ${username})
return $?
}
__short_result () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
echo $(__tally_vote ${vote_dir} ${vid})
return 0
}
__pretty_print () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
local subject=$(cat ${vote_dir}/${vid}/subject)
local y_voters=""
local n_voters=""
local a_voters=""
local d_voters=""
for vote in $(find -s ${vote_dir}/${vid}/votes -type l) ; do
value=$(readlink ${vote})
voter=$(basename ${vote})
case "${value}" in
"yes")
y_voters="${y_voters}${y_voters:+, }${voter}"
;;
"no")
n_voters="${n_voters}${n_voters:+, }${voter}"
;;
"abstain")
a_voters="${a_voters}${a_voters:+, }${voter}"
;;
"zzz")
d_voters="${d_voters}${d_voters:+, }${voter}"
;;
*) __error "Invalid vote value ${value} in ${vote} (${vid})"
esac
done
result=$(printf "Vote on ${subject}.\n\nYes:\t\t${y_voters}\nNo:\t\t${n_voters}\nAbstained:\t${a_voters}\n\nDid not vote:\t${d_voters}")
echo "${result}"
return 0
}
reopen_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
open=$(__is_open_vote ${vote_dir} ${vid})
if [ $? -eq 0 ] ; then
__error "Vote already open"
fi
local closeddate=$(cat ${vote_dir}/${vid}/closeddate)
rm ${vote_dir}/${vid}/closeddate
local tally=$(__short_result ${vote_dir} ${vid})
local pretty=$(__pretty_print ${vote_dir} ${vid})
local commit_message=$(printf "<${vid}> [REOPEN] ${tally}\n\n${pretty}\nOld Closed Date:\t${closeddate}")
echo -e "${col_git}"
cd ${vote_dir} && \
git add ${vote_dir}/${vid}/closeddate && \
git commit -m "${commit_message}" && \
git push
echo -e "${col_reset}"
__pretty_print ${vote_dir} ${vid}
return 0
}
close_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
open=$(__is_open_vote ${vote_dir} ${vid})
if [ $? -ne 0 ] ; then
__error "Vote already closed"
fi
echo $(date -u '+%Y%m%d') > ${vote_dir}/${vid}/closeddate
local tally=$(__short_result ${vote_dir} ${vid})
local pretty=$(__pretty_print ${vote_dir} ${vid})
local commit_message=$(printf "<${vid}> [CLOSE] ${tally}\n\n${pretty}")
echo -e "${col_git}"
cd ${vote_dir} && \
git add ${vote_dir}/${vid}/closeddate && \
git commit -m "${commit_message}" && \
git push
echo -e "${col_reset}"
__pretty_print ${vote_dir} ${vid}
return 0
}
# Interacting with votes
init_votes () {
__want_args 2 "$@"
local vote_dir="$1"
local url="$2"
if [ -d "${vote_dir}" ] ; then
__error "Directory '${vote_dir}' already exists."
fi
echo -e "${col_git}"
git clone ${url} ${vote_dir}
if [ $? -ne 0 ] ; then
echo -e "${col_reset}"
__error "Could not clone ${url} to ${vote_dir}"
fi
echo -e "${col_reset}"
list_all_votes ${vote_dir}
return 0
}
update_votes () {
__want_args 1 "$@"
local vote_dir="$1"
__check_git ${vote_dir}
if [ $? -ne 0 ] ; then
__error "Directory '${vote_dir}' is not a repository."
fi
echo -e "${col_git}"
cd "${vote_dir}" && git pull --rebase --autostash
if [ $? -ne 0 ] ; then
echo -e "${col_reset}"
__error "Failed to update '${vote_dir}' -- please try manual merge."
fi
echo -e "${col_reset}"
list_votes ${vote_dir}
return 0
}
__list_vids () {
local vote_dir="$1"
vids=$(find -E "${vote_dir}" -type d -regex ".*/[0-9][0-9][0-9][0-9]$" | sort | awk -F '/' '{print $NF}')
if [ $? -ne 0 ] ; then
__error "Failed to enumerate vids"
fi
echo "${vids}"
return 0
}
__last_vid () {
local vote_dir="$1"
result=$(__list_vids "${vote_dir}" | tail -n1)
echo ${result}
}
__make_vid () {
__want_args 1 "$@"
echo $(printf "%04d" $(expr $1 + 0))
return 0
}
__next_vid () {
__want_args 1 "$@"
local vote_dir="$1"
last=$(__last_vid "${vote_dir}")
if [ -z ${last} ] ; then
last=0
fi
echo $(__make_vid $(expr ${last} + 1))
return 0
}
__list_vote_entry () {
__want_args 3 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
local include_closed="$3"
if [ ! -d ${vote_dir}/${vid} ] ; then
__error "Failed to read info on ${vid} from ${vote_dir}"
fi
local state=${mark_cl}
__is_open_vote ${vote_dir} ${vid}
if [ $? -eq 0 ] ; then
state=${mark_op}
fi
local duedate=$(cat ${vote_dir}/${vid}/duedate)
local subject=$(cut -c 1-50 ${vote_dir}/${vid}/subject)
local votes=$(__tally_vote ${vote_dir} ${vid})
local own_vote=$(__own_vote ${vote_dir} ${vid})
local closed_info=""
if [ "${include_closed}" = "yes" ] ; then
if [ -f ${vote_dir}/${vid}/closeddate ] ; then
closed_info="|$(cat ${vote_dir}/${vid}/closeddate)"
else
closed_info="|"
fi
fi
echo "${state}|${duedate}|${vid}|${subject}|${votes}|${own_vote}${closed_info}"
}
__vote_mark () {
__want_args 1 "$@"
local result=${mark_dn}
case "$1" in
"yes") result=${mark_ys} ;;
"no") result=${mark_no} ;;
"abstain") result=${mark_ab} ;;
esac
echo "${result}"
}
__vote_text() {
__want_args 1 "$@"
local result=${text_dn}
case "$1" in
"yes") result=${text_ys} ;;
"no") result=${text_no} ;;
"abstain") result=${text_ab} ;;
esac
echo "${result}"
}
__get_vote () {
__want_args 3 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
local username="$3"
if [ ! -d ${vote_dir}/${vid} ] ; then
__error "Failed to read info on ${vid} from ${vote_dir}"
fi
local uservote=""
local vote=${vote_dir}/${vid}/votes/${username}
voted=1
local result=${mark_dn}
if [ -L ${vote} ] ; then
vote_value=$(readlink ${vote})
if [ "${vote_value}" != "zzz" ] ; then
voted=0
fi
result=$(__vote_mark ${vote_value})
fi
echo "${result}"
return ${voted}
}
__own_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
local username=$(__username ${vote_dir})
local result=$(__get_vote ${vote_dir} ${vid} ${username})
echo "${result}"
return 0
}
__tally_vote () {
__want_args 2 "$@"
local vote_dir="$1"
local vid=$(__make_vid "$2")
if [ ! -d ${vote_dir}/${vid} ] ; then
__error "Failed to read info on ${vid} from ${vote_dir}"
fi
local count_yes=0
local count_no=0
local count_abstain=0
local count_dnv=0
for vote in $(find ${vote_dir}/${vid}/votes -type l) ; do
value=$(readlink ${vote})
voter=$(basename ${vote})
case "${value}" in
"yes") count_yes=$(expr ${count_yes} + 1) ;;
"no") count_no=$(expr ${count_no} + 1) ;;
"abstain") count_abstain=$(expr ${count_abstain} + 1) ;;
"zzz") count_dnv=$(expr ${count_dnv} + 1) ;;
*) __error "Invalid vote value ${value} in ${vote} (${vid})"
esac
done
result=$(printf "${mark_ys}%2d, ${mark_no}%2d, ${mark_ab}%2d, ${mark_dn}%2d" ${count_yes} ${count_no} ${count_abstain} ${count_dnv})
echo "${result}"
return 0
}
list_votes () {
__want_args 1 "$@"
local vote_dir="$1"
result=""
for vid in $(__list_vids "$@") ; do
__is_open_vote ${vote_dir} ${vid}
if [ $? -eq 0 ] ; then
result="${result}\n$(__list_vote_entry ${vote_dir} ${vid} no)"
fi
done
result=$(echo -e "${result}" | sort -r)
result=$(printf "State|Due Date|VID|Subject|Tally|Own Vote\n${result}")
echo "${result}" | column -t -s '|'
}
list_all_votes () {
__want_args 1 "$@"
local vote_dir="$1"
result=""
for vid in $(__list_vids "$@") ; do
result="${result}\n$(__list_vote_entry ${vote_dir} ${vid} yes)"
done
result=$(echo -e "${result}" | sort -r)
result=$(printf "State|Due Date|VID|Subject|Tally|Own Vote|Closed On\n${result}")
echo "${result}" | column -t -s '|'
}
place_vote () {
__vote "$@"
}
place_vote_for () {
__vote_for "$@"
}
__vote_for () {
__want_args 4 "$@"
local vote_dir="$1"
update_votes "${vote_dir}"
local vid=$(__make_vid "$2")
local value="$3"
local username="$4"
if [ ! -L ${vote_dir}/${vid}/votes/${username} ] ; then
__error "Invalid voter ${username}"
fi
local author=$(awk -F : "/${username}/{print \$NF}" ${vote_dir}/voters)
if [ -z "${author}" ] ; then
__error "Could not read author for ${username}"
fi
local action=""
local msg=""
oldvote=$(__get_vote ${vote_dir} ${vid} ${username})
if [ $? -eq 0 ] ; then
action="[CHANGE VOTE]"
message="${oldvote} -> $(__vote_text ${value})"
else
action="[SET VOTE]"
message="$(__vote_text ${value})"
fi
local foreignvote=""
gituser=$(__username ${vote_dir})
if [ ${username} != ${gituser} ] ; then
foreignvote=" (vote placed by ${gituser})"
fi
__set_vote "${vote_dir}" "${vid}" "${username}" "${value}"
if [ $? -ne 0 ] ; then
__error "Could not place vote ${value} on ${vid}"
fi
local subject=$(cut -c 1-50 ${vote_dir}/${vid}/subject)
local commit_message=$(printf "<${vid}> ${action} ${subject} :: ${username} ${message}${foreignvote}\n\n$(__pretty_print ${vote_dir} ${vid})")
echo -e "${col_git}"
cd ${vote_dir} && \
git add ${vid}/votes/${username} && \
git commit -m "${commit_message}" --author="${author}" && \
git push
echo -e "${col_reset}"
__message ""
__pretty_print ${vote_dir} ${vid}
}
__vote () {
__want_args 3 "$@"
local username=$(__username ${vote_dir})
if [ -z "${username}" ] ; then
__error "Could not read your git username"
fi
__vote_for "$@" ${username}
}
# utils
__check_git () {
local git_dir=$(realpath "$1")
if [ ! -d "${git_dir}" ] ; then
return 1
fi
(
cd "${git_dir}"
git rev-parse --is-inside-work-tree > /dev/null 2>&1
if [ $? -ne 0 ] ; then
return 1
fi
)
return 0
}
if [ -z $1 ] ; then
__usage
fi
command=$1
shift
case "${command}" in
"help") __usage ;;
"init") init_votes ${vote_dir} "$@" ;;
"update") update_votes ${vote_dir} ;;
"list") list_votes ${vote_dir} ;;
"all") list_all_votes ${vote_dir} ;;
"create") create_vote ${vote_dir} "$@" ;;
"info") info_vote ${vote_dir} "$@" ;;
"close") close_vote ${vote_dir} "$@" ;;
"reopen") reopen_vote ${vote_dir} "$@" ;;
"changedate") change_date ${vote_dir} "$@" ;;
"changesubject") change_subject ${vote_dir} "$@" ;;
"vote") place_vote ${vote_dir} "$@" ;;
"votefor") place_vote_for ${vote_dir} "$@" ;;
*) __usage ;;
esac