From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id 57D231382BD for ; Sat, 18 Jun 2016 17:29:06 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id CFF1BE0A8A; Sat, 18 Jun 2016 17:29:05 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 60EBAE0A8A for ; Sat, 18 Jun 2016 17:29:05 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 6047E33FD24 for ; Sat, 18 Jun 2016 17:29:04 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id C16AD2323 for ; Sat, 18 Jun 2016 17:28:57 +0000 (UTC) From: "Robin H. Johnson" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Robin H. Johnson" Message-ID: <1435469615.274977d0840c8a1879946234c4d07575e8bde153.robbat2@gentoo> Subject: [gentoo-commits] proj/elections:master commit in: / X-VCS-Repository: proj/elections X-VCS-Files: Votify.pm countify listify votify X-VCS-Directories: / X-VCS-Committer: robbat2 X-VCS-Committer-Name: Robin H. Johnson X-VCS-Revision: 274977d0840c8a1879946234c4d07575e8bde153 X-VCS-Branch: master Date: Sat, 18 Jun 2016 17:28:57 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 8c966c29-e573-4f5c-a6aa-ed516822c483 X-Archives-Hash: 81f6e59aa18ad6aac45316b5d19eaab6 commit: 274977d0840c8a1879946234c4d07575e8bde153 Author: Robin H. Johnson gentoo org> AuthorDate: Sun Jun 28 05:32:45 2015 +0000 Commit: Robin H. Johnson gentoo org> CommitDate: Sun Jun 28 05:33:35 2015 +0000 URL: https://gitweb.gentoo.org/proj/elections.git/commit/?id=274977d0 Refactor elections, so we can have common fetching of which elections are open, and then consistently use the epoch timestamp inside the start/stop files. Signed-off-by: Robin H. Johnson gentoo.org> Votify.pm | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- countify | 38 ++++++------------- listify | 58 +++++++++------------------- votify | 55 ++++++++------------------- 4 files changed, 157 insertions(+), 121 deletions(-) diff --git a/Votify.pm b/Votify.pm index 1be8de7..289be2c 100644 --- a/Votify.pm +++ b/Votify.pm @@ -9,10 +9,14 @@ package Votify; use POSIX; +use Cwd qw(abs_path); +use File::Spec::Functions; use List::Util; use strict; -our ($datadir) = '/etc/elections/current'; +our $datefmt = '%Y-%m-%d %H:%M:%S UTC'; + +our ($basedir) = List::Util::first { -d $_ } ('/etc/elections', '.'); (our $zero = $0) =~ s,.*/,,; our $version = '1.6'; @@ -21,6 +25,98 @@ sub import { $Votify::mode = $mode; } +my @REQUIRED_FILES = qw(ballot officials start stop voters); + +sub get_datadir { + my $election_name = shift; + my $election_dir = abs_path(catfile($Votify::basedir, $election_name)); + if(!validate_election_dir()) { + die "$election_name is not a valid election!" + } + return $election_dir; +} + +sub validate_election_dir { + return 0 unless $_; + my $election_dir = $_; + my $election_name = $election_dir; + $election_name =~ /.*\//; + return 0 unless -d $election_dir; + return 0 if substr($election_name,0,1) eq "."; + my $valid = List::Util::reduce { + $a or $b ? 1 : 0; + } map { + my $file_valid = 0; + # Legacy naming: + $file_valid = 1 if -f sprintf("%s/%s-%s", $election_name, $_, $election_name); + # New naming: + $file_valid = 1 if -f sprintf("%s/%s", $election_name, $_); + #printf "File %s valid=%d\n", $_, $file_valid; + $file_valid; + } @REQUIRED_FILES; + return $valid; +} + +sub get_elections_list { + my @elections; + opendir(D, $Votify::basedir) or die; + @elections = sort grep { + my $valid = validate_election_dir(catfile($Votify::basedir, $_)); + $valid; + } readdir D; + closedir D; + return @elections; +} + +sub grabfile_int { + my $f = shift; + #print "Checking $f\n"; + my $i = 0; + open my $fh, '<', $f or return -1; + local $/ = undef; + $i = <$fh> if defined($fh); + close $fh; + #print "Raw file: $i\n"; + chomp $i if $i; + return $i; +} + + +sub get_single_election_hashref { + my $election_name = shift; + my $election_dir = catfile($Votify::basedir, $election_name); + my %election; + foreach my $fn (@REQUIRED_FILES){ + #print "Scan $fn\n"; + my @filenames = (sprintf("%s/%s", $election_name, $fn), sprintf("%s/%s-%s", $election_name, $fn, $election_name)); + #print Dumper(@filenames); + my $filename = abs_path(List::Util::first { -f $_ } @filenames); + $election{"${fn}file"} = $filename; + }; + #print Dumper(%election); + $election{starttime} = grabfile_int($election{'startfile'}); + $election{stoptime} = grabfile_int($election{'stopfile'}); + return \%election; +} + +sub get_elections_hash { + my %elections; + %elections = map { $_ => get_single_election_hashref($_) } get_elections_list(); + return %elections; +} + +sub get_open_elections_hash { + my %elections = get_elections_hash(); + my @open_elections = grep { + my $starttime = $elections{$_}{'starttime'}; + my $stoptime = $elections{$_}{'stoptime'}; + my $valid = ((not defined $starttime or $starttime < time) and + (not defined $stoptime or $stoptime > time)); + $valid; + } keys %elections; + return map { $_ => $elections{$_} } @open_elections; +} + ###################################################################### # OfficialList ###################################################################### @@ -28,14 +124,15 @@ sub import { package OfficialList; sub new { - my ($class, $election) = @_; + my ($class, $election_name) = @_; my ($self) = { - election => $election, + election => $election_name, officials => [], }; + my $election = Votify::get_single_election_hashref($self->{'election'}); # no point in waiting to load - open(F, "<$Votify::datadir/officials-$election") + open(F, '<', $election->{'officialsfile'}) or die("failed to open officials file"); chomp(@{$self->{'officials'}} = ); close(F); @@ -56,18 +153,20 @@ sub officials { package VoterList; sub new { - my ($class, $election) = @_; + my ($class, $election_name) = @_; my (@voterlist, $r); + my $datadir = Votify::get_datadir($election_name); my ($self) = { - election => $election, - default_filename => "$Votify::datadir/confs-$election", + election => $election_name, + default_filename => catfile($datadir, "confs-$election_name"), filename => '', voters => {}, # confnum => voter confs => {}, # voter => confnum }; # no point in waiting to load - open(F, "<$Votify::datadir/voters-$election") + my $election = Votify::get_single_election_hashref($self->{'election'}); + open(F, '<', $election->{'votersfile'}) or die("failed to open voters file"); chomp(@voterlist = ); close(F); @@ -133,10 +232,11 @@ package MasterBallot; use Data::Dumper; sub new { - my ($class, $election, $vl) = @_; + my ($class, $election_name, $vl) = @_; + my $datadir = Votify::get_datadir($election_name); my ($self) = { - election => $election, - default_filename => "$Votify::datadir/master-$election", + election => $election_name, + default_filename => catfile($datadir, "master-$election_name"), filename => '', voterlist => $vl, ballots => {}, # indexed by conf num @@ -296,7 +396,7 @@ sub display_table { @shortnames = sort values %{$self->{'candidates'}}; $minlen = length scalar keys %{$self->{'ballots'}}; $minlen = 5 if $minlen < 5; - + # build the format string for my $s (@shortnames) { if (length($s) > $minlen) { @@ -491,7 +591,8 @@ sub read { sub populate { my ($self) = @_; - $self->read("$Votify::datadir/ballot-$self->{election}"); + my $election = Votify::get_single_election_hashref($self->{'election'}); + $self->read($election->{'ballotfile'}); @{$self->{'choices'}} = List::Util::shuffle(@{$self->{'choices'}}); } diff --git a/countify b/countify index 975a7ec..1465da4 100755 --- a/countify +++ b/countify @@ -8,7 +8,13 @@ # #BEGIN { push @INC, (getpwnam 'fox2mike')[7].'/elections' } -BEGIN { push @INC, '/etc/elections/current' } +BEGIN { + if(-f '/etc/elections/Votify.pm') { + push @INC, '/etc/elections'; + } else { + push @INC, '.' if -f 'Votify.pm'; + } +} use POSIX; use Getopt::Long; @@ -24,33 +30,11 @@ use strict; (my $version = $Votify::version) =~ s/.*?(\d.*\d).*/$zero version $1\n/; my %opt; -sub grabfile_int { - my $f = shift; - open FILE, "<", $f; - my $i = ; - close FILE; - chomp $i; - return $i + 0; -} - # Collect the open elections -my (@open_elections, $usage_elections); -opendir(D, "$Votify::datadir/") or die; -@open_elections = sort grep { - s/^start-// and do { - my ($startfile) = sprintf "%s/start-%s", $Votify::datadir, $_; - my ($stopfile) = sprintf "%s/stop-%s", $Votify::datadir, $_; - my ($starttime) = grabfile_int($startfile); - my ($stoptime) = grabfile_int($stopfile); - $starttime = (stat _)[9] if stat($startfile) and (!defined($starttime) or ($starttime <= 0)); - $stoptime = (stat _)[9] if stat($stopfile) and (!defined($stoptime) or ($stoptime <= 0)); - ((not defined $starttime or $starttime < time) and - (not defined $stoptime or $stoptime > time)) - } -} readdir D; -closedir D; -if (@open_elections) { - $usage_elections = join("\n ", @open_elections); +my (%open_elections, $usage_elections); +%open_elections = Votify::get_open_elections_hash(); +if (scalar keys %open_elections) { + $usage_elections = join("\n ", keys %open_elections); } else { $usage_elections = "(no elections currently open)"; } diff --git a/listify b/listify index 10b4b82..c8c24eb 100755 --- a/listify +++ b/listify @@ -7,8 +7,13 @@ # votify: generate, verify and submit voting ballots for trustee elections # -#BEGIN { push @INC, (getpwnam 'fox2mike')[7].'/elections' } -BEGIN { push @INC, '/etc/elections/current' } +BEGIN { + if(-f '/etc/elections/Votify.pm') { + push @INC, '/etc/elections'; + } else { + push @INC, '.' if -f 'Votify.pm'; + } +} use POSIX; use Getopt::Long; @@ -24,46 +29,17 @@ use strict; (my $version = $Votify::version) =~ s/.*?(\d.*\d).*/$zero version $1\n/; my (%opt, %elections); -sub grabfile_int { - my $f = shift; - my $i = 0; - open FILE, "<", $f; - $i = if defined(); - close FILE; - chomp $i if $i; - return $i; -} - # Collect the open elections -my (@open_elections, $usage_elections); -opendir(D, "$Votify::datadir/") or die; -@open_elections = sort grep { - s/^start-// and do { - my ($name) = $_; - my ($startfile) = sprintf "%s/start-%s", $Votify::datadir, $_; - my ($stopfile) = sprintf "%s/stop-%s", $Votify::datadir, $_; - my ($starttime) = grabfile_int($startfile); - my ($stoptime) = grabfile_int($stopfile); - $starttime = (stat _)[9] if stat($startfile) and (!defined($starttime) or ($starttime <= 0)); - $stoptime = (stat _)[9] if stat($stopfile) and (!defined($stoptime) or ($stoptime <= 0)); - my $valid = ((not defined $starttime or $starttime < time) and - (not defined $stoptime or $stoptime > time)); - if($valid) { - $elections{$name} = {}; - $elections{$name}{starttime} = $starttime; - $elections{$name}{stoptime} = $stoptime; - } - $valid; - } -} readdir D; -closedir D; -my $datefmt = '%Y-%m-%d %H:%M UTC'; -if (@open_elections) { - $usage_elections = "Presently available elections:\n" . join('', map { - my ($name) = $_; - my ($start) = strftime($datefmt, localtime($elections{$name}{starttime})); - my ($stop) = strftime($datefmt, localtime($elections{$name}{stoptime})); - sprintf("\t%s: %s to %s\n", $name, $start, $stop) } @open_elections); +my ($usage_elections); + +%elections = Votify::get_open_elections_hash(); + +if (scalar(keys %elections) > 0) { + $usage_elections = "Presently available elections:\n" . join('', map { + my ($name) = $_; + my ($start) = strftime($Votify::datefmt, gmtime($elections{$name}{starttime})); + my ($stop) = strftime($Votify::datefmt, gmtime($elections{$name}{stoptime})); + sprintf("\t%s: %s to %s\n", $name, $start, $stop) } keys %elections); $usage_elections .= < if defined(); - close FILE; - chomp $i if $i; - return $i; -} - # Collect the open elections -my (@open_elections, $usage_elections); -opendir(D, "$Votify::datadir/") or die; -@open_elections = sort grep { - s/^start-// and do { - my ($startfile) = sprintf "%s/start-%s", $Votify::datadir, $_; - my ($stopfile) = sprintf "%s/stop-%s", $Votify::datadir, $_; - my ($starttime) = grabfile_int($startfile); - my ($stoptime) = grabfile_int($stopfile); - $starttime = (stat _)[9] if stat($startfile) and (!defined($starttime) or ($starttime <= 0)); - $stoptime = (stat _)[9] if stat($stopfile) and (!defined($stoptime) or ($stoptime <= 0)); - ((not defined $starttime or $starttime < time) and - (not defined $stoptime or $stoptime > time)) - } -} readdir D; -closedir D; -if (@open_elections) { - $usage_elections = join("\n ", @open_elections); +my (%open_elections, $usage_elections); +%open_elections = Votify::get_open_elections_hash(); +if (scalar keys %open_elections) { + $usage_elections = join("\n ", keys %open_elections); } else { $usage_elections = "(no elections currently open)"; } @@ -104,7 +87,7 @@ Instructions: (4) Submit your ballot. This renames your ballot to ~/.ballot--submitted so that it will be tallied when the votes are collected. - + \$ $zero --submit EOT @@ -141,16 +124,8 @@ my ($b) = Ballot->new($election); # Check if the election is open. This should really happen in an # Election class in Votify.pm eventually my ($starttime, $stoptime); -my ($startfile) = sprintf "%s/start-%s", $Votify::datadir, $election; -my ($stopfile) = sprintf "%s/stop-%s", $Votify::datadir, $election; -if ( -f $startfile ) { - $starttime = grabfile_int($startfile); - $starttime = (stat _)[9] if stat($startfile) and (!defined($starttime) or ($starttime <= 0)); -} -if ( -f $stopfile ) { - ($stoptime) = grabfile_int($stopfile); - $stoptime = (stat _)[9] if stat($stopfile) and (!defined($stoptime) or ($stoptime <= 0)); -} +$starttime = $open_elections{$election}{'starttime'}; +$stoptime = $open_elections{$election}{'stoptime'}; if ($starttime && $starttime > time) { print "\n", "*" x 75, "\n"; print "WARNING: Specified election doesn't start until ", @@ -166,7 +141,7 @@ if ($stoptime && $stoptime < time) { if ($opt{'new'}) { # Make sure the user is eligible - open(F, "<$Votify::datadir/voters-$election") or die "Failed to open voters file"; + open(F, '<', $open_elections{$election}{'votersfile'}) or die "Failed to open voters file"; my (@voters) = ; chomp(@voters); close(F);