From nobody Fri Nov 11 20:19:01 2022 X-Original-To: dev-commits-ports-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4N895d6RTPz4fvWB; Fri, 11 Nov 2022 20:19:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4N895d69J2z4NJm; Fri, 11 Nov 2022 20:19:01 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668197941; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3d/O/sZOGNAwqruz7oBOtIyBkKp3X/zBUrZCmkeimOw=; b=q3BQH+vAkIq2Laiy6AKaoY4lrnW9dfrp+cR6zouPEQfB7jwv6SCHi2saDSx0f4AxMlt88b YN3Gtrof7Ijun/2+eYLp0v9dyUeT3Ef5ZXl1IwfjAy6JIDCHufbh1jqNLYXSu6fTB2GIBw aw5JtF2wgxLJPUAuwxn3ixmwjmz34+IctFwb6XyQFxl+xU0834nrt9ok+b6zDTACWXxVpz kPrzRFdnPLDgb8jc7hZ/IRtzev9WyEy1pGAwGG0RrEGRtRfMArBnrVNew8l3sQA3ibfldf j5HJz/90oCjtefq7nw1zrxTIOHWJ/KeQef96F3PSHSKamkIyODBKF1hel5EPQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668197941; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3d/O/sZOGNAwqruz7oBOtIyBkKp3X/zBUrZCmkeimOw=; b=vjI92L/vTuqDBtotVaxh/rOJ3mjcJ7sQU9aK8RXsWROOMsGs1Wkl94fxd6jGjXCXZRvada mjN+zrJqU+VB4OgmORCtQDWAkJWSXiQjmZIcm1EsAAn9dpvIrszO4m6lMtTSlvFeYRwpGu /DfzEAOUgU3HLOFWlY9iia9hAoky6W0ewc+LyUtyAbJ0yR5FAq5yG+t1F6OD+TGcCLM/tF ZOWMhgOw8/QvysdWPRl3/s/NGqn7Zu9oGdL32t72wpOiuhXb0HuMdI88HTNbS5/ngcEaMb Eo31mgrp4aV+JSVbDILDSY2WuJVaWaCwjLuk/jJSJ6Fm6cpSn0CoTe8p3MoTGQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1668197941; a=rsa-sha256; cv=none; b=BxVtbanARhl+K+IeANb5a7c5KoMUE028BJHASU6bcZ7cQJ9ABPY328vg5v/QXHm9swvFin si0YthNweUSpJhaDmWXyIv1yAp1GkE/Nkqi0XEx+Y5liih/JGtAu9HosQ/ZA3hp4un9Xnn As9D5RPW5qFnG2pyR3SfiKR0vMCOKqd8S5O86PuaRmOwD3vKpZx0drKgfSlSQTl+9pgwzj DjfXt9WwQKHFPjIkfc5sM2hq7ferS6C8oIqVvmTi+8G/dcWZz86/Wmh6YbAqrknsSxWSN1 ViEDpKVX8LXEU5qKAkogJpWSMrO8yMRw1vgyvXj1vcDZiYlDnBnh/+WUYPXqyw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4N895d58PBzwN5; Fri, 11 Nov 2022 20:19:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2ABKJ1ul048581; Fri, 11 Nov 2022 20:19:01 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2ABKJ1KZ048580; Fri, 11 Nov 2022 20:19:01 GMT (envelope-from git) Date: Fri, 11 Nov 2022 20:19:01 GMT Message-Id: <202211112019.2ABKJ1KZ048580@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: "Tobias C. Berner" Subject: git: 95fe54732a25 - main - misc/vote: cleanup port List-Id: Commits to the main branch of the FreeBSD ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-main@freebsd.org X-BeenThere: dev-commits-ports-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tcberner X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 95fe54732a25fcf021f52574bb400a862230f129 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by tcberner: URL: https://cgit.FreeBSD.org/ports/commit/?id=95fe54732a25fcf021f52574bb400a862230f129 commit 95fe54732a25fcf021f52574bb400a862230f129 Author: Tobias C. Berner AuthorDate: 2022-11-11 20:10:34 +0000 Commit: Tobias C. Berner CommitDate: 2022-11-11 20:18:53 +0000 misc/vote: cleanup port - fix wrong version number inside script Reported by: diizzy --- misc/vote/0001-misc-vote-cleanup-port.patch | 55 +++ misc/vote/Makefile | 13 +- misc/vote/distinfo | 6 +- misc/vote/fetch.out | 723 ++++++++++++++++++++++++++++ 4 files changed, 791 insertions(+), 6 deletions(-) diff --git a/misc/vote/0001-misc-vote-cleanup-port.patch b/misc/vote/0001-misc-vote-cleanup-port.patch new file mode 100644 index 000000000000..2a42eea651b1 --- /dev/null +++ b/misc/vote/0001-misc-vote-cleanup-port.patch @@ -0,0 +1,55 @@ +From 33a1a9ccf0df2fc73cd8d85ab4bcdbf585dce94b Mon Sep 17 00:00:00 2001 +From: "Tobias C. Berner" +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 +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 + diff --git a/misc/vote/Makefile b/misc/vote/Makefile index 9f9a4b897479..db31d0f28693 100644 --- a/misc/vote/Makefile +++ b/misc/vote/Makefile @@ -1,16 +1,23 @@ 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 +WWW= https://codeberg.org/tcberner/vote +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 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 diff --git a/misc/vote/fetch.out b/misc/vote/fetch.out new file mode 100644 index 000000000000..925be6ae4b9c --- /dev/null +++ b/misc/vote/fetch.out @@ -0,0 +1,723 @@ +#!/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 ) +# 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 ${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 ${col_reset}\n\n" \ + "- create\tCreate a new vote:\n" \ + "\t\t${col_highlight}% vote create ${col_reset}\n" \ + "- close\tMark a vote as closed:\n" \ + "\t\t${col_highlight}% vote close ${col_reset}\n" \ + "- reopen\tReopen a vote:\n" \ + "\t\t${col_highlight}% vote reopen ${col_reset}\n\n" \ + "- changedate\tChange the Due Date to something new\n" \ + "\t\t${col_highlight}% vote changedate ${col_reset}\n" \ + "- changesubject\tChange the Subject to something new\n" \ + "\t\t${col_highlight}% vote changesubject ${col_reset}\n\n" \ + "- vote\t\tPlace a vote:\n" \ + "\t\t${col_highlight}% vote vote ${col_reset}\n" \ + "- votefor\tPlace a vote for another person:\n" \ + "\t\t${col_highlight}% vote votefor ${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