summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--signoffs.pl247
1 files changed, 247 insertions, 0 deletions
diff --git a/signoffs.pl b/signoffs.pl
new file mode 100644
index 0000000..d908ada
--- /dev/null
+++ b/signoffs.pl
@@ -0,0 +1,247 @@
+#!/usr/bin/perl
+#
+# Author: Florian Pritz <bluewind@xinu.at>
+#
+# Licensed under GPLv3
+#
+use warnings;
+no warnings 'once';
+use strict;
+use diagnostics;
+use JSON;
+use WWW::Mechanize;
+use Data::Dumper;
+use Text::Wrap;
+use Getopt::Long;
+use Pod::Usage;
+
+my $configfile = "$ENV{HOME}/.signoffsrc";
+{ package Settings;
+
+ # define default values
+ # these can be overridden from the config file
+ our $domain = "https://www.archlinux.org";
+ our $pacman_db = "/var/lib/pacman";
+ chomp (our $system_arch = `uname -m`);
+ our $display_disabled = 0;
+ our $only_pending = 0;
+ our $hide_signed_off = 0;
+ our $display_comments = 1;
+ our @target_repos = qw(core unknown);
+
+ unless (my $return = do $configfile) {
+ die "couldn't parse $configfile: $@" if $@;
+ die "couldn't do $configfile: $!" unless defined $return;
+ }
+}
+
+sub make_links {
+ my $text = shift;
+
+ $text =~ s|FS#([0-9]+)|<https://bugs.archlinux.org/task/$1>|;
+
+ return $text;
+}
+
+Getopt::Long::Configure ("bundling");
+GetOptions(
+ "help" => sub {pod2usage(0);},
+ "h" => sub {pod2usage(2);},
+ "comments|c!" => \$Settings::display_comments
+);
+
+# check if all vars are configured
+for my $varname (qw(username password)) {
+ unless (${$Settings::{$varname}}) {
+ print STDERR "$varname not defined in config file \"$configfile\"\n";
+ exit 1;
+ }
+}
+
+# sanity checks
+if (! -d $Settings::pacman_db) {
+ print STDERR "\$pacman_db set to non-directory \"$Settings::pacman_db\": $!\n";
+ exit 1;
+}
+
+$Text::Wrap::columns = 80;
+
+# array to hold information of installed packages
+my @installed_groups;
+
+my $mech = WWW::Mechanize->new(cookie_jar => {});
+#$mech->proxy(['https', 'http', 'ftp'], 'http://localhost:8080');
+
+# log in
+$mech->get("$Settings::domain/login/");
+$mech->submit_form(
+ form_id => "dev-login-form",
+ fields => {
+ username => $Settings::username,
+ password => $Settings::password
+ }
+);
+
+if ($mech->content() =~ m/Please enter a correct username and password/) {
+ print STDERR "Login credentials are incorrect.\n";
+ exit 1;
+}
+
+$mech->get("$Settings::domain/packages/signoffs/json");
+my $json = JSON::decode_json($mech->content());
+
+my $id = 0;
+for my $signoff_groups ($json->{signoff_groups}) {
+ for my $signoff_group (@{$signoff_groups}) {
+ # skip packages for different arch
+ next unless ($signoff_group->{arch} eq $Settings::system_arch
+ || $signoff_group->{arch} eq "any");
+
+ my $target_repo = lc $signoff_group->{target_repo};
+
+ # skip package that are not going to repos listed in the config
+ if (!grep $_ eq $target_repo, @Settings::target_repos) {
+ next;
+ }
+
+ if (!$Settings::display_disabled) {
+ # skip disabled packages
+ next if !$signoff_group->{enabled};
+ }
+
+ if ($Settings::only_pending) {
+ # skip packages with enough signoffs
+ next if $signoff_group->{approved};
+ }
+
+ # loop over packages, print some information and push it to @installed_groups
+ # if the package is installed
+ for my $pkgname (@{$signoff_group->{pkgnames}}) {
+ # if package is installed save to @installed_groups, else skip it
+ next unless -e "$Settings::pacman_db/local/$pkgname-$signoff_group->{version}";
+ $installed_groups[$id] = $signoff_group;
+
+ print "\e[1;33m$id\e[0m - \e[0;33m$pkgname $signoff_group->{version}\e[0m\n";
+
+ if ($signoff_group->{known_bad}) {
+ print " \e[1;31mKnown bad!\e[0m\n";
+ }
+
+ if ($pkgname ne $signoff_group->{pkgbase}) {
+ print " \e[0;31mPkgbase: $signoff_group->{pkgbase}\e[0m\n";
+ }
+
+ unless ($signoff_group->{required} == 2) {
+ print " Required signoffs: $signoff_group->{required}\n";
+ }
+
+ my $i = 0;
+ my $signoff_count = @{$signoff_group->{signoffs}};
+ print " Signoffs: ";
+ if ($signoff_group->{enabled}) {
+ for my $signoff (@{$signoff_group->{signoffs}}) {
+ # if it's our signoff, save that info for later so we can revoke it
+ if ($signoff->{user} eq $Settings::username && !$signoff->{revoked}) {
+ $signoff_group->{can_revoke} = 1;
+ print "\e[0;32m$signoff->{user}\e[0m";
+ } else {
+ print $signoff->{user};
+ print " (revoked)" if $signoff->{revoked};
+ }
+ print ", " if $i+1 < $signoff_count;
+
+ $i++;
+ }
+ } else {
+ print "<disabled for this package>";
+ }
+ print "\n";
+
+ if ($signoff_group->{comments} ne "" && $Settings::display_comments) {
+ print " \e[0;35mComment:\e[0m\n";
+ print wrap(" ", " ", make_links($signoff_group->{comments}));
+ print "\n";
+ }
+
+ $id++;
+ }
+ }
+}
+
+print "\n";
+print STDERR"\e[0;34mPlease enter IDs of packages to sign off/revoke: \e[0m";
+my $input = <STDIN>;
+
+# sign off or revoke
+for my $id (split(" ", $input)) {
+ unless ($id =~ /^\d+$/ && exists ($installed_groups[$id])) {
+ print STDERR "Invalid ID \"$id\". Skipping...\n";
+ }
+ my $pkg = $installed_groups[$id];
+
+ print "processing pkgbase $pkg->{pkgbase} ... ";
+
+ my $url = "$Settings::domain/packages/$pkg->{repo}/$pkg->{arch}/$pkg->{pkgbase}/signoff/";
+
+ if ($pkg->{can_revoke}) {
+ $mech->get("$url/revoke");
+ print "revoked.\n";
+ } else {
+ $mech->get($url);
+ print "signed off.\n";
+ }
+}
+
+__END__
+=head1 SYNOPSIS
+
+signoffs.pl [options]
+
+ Options:
+ --help, -h display help message
+ --comments, -c display comments (can be negated)
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>, B<-h>
+
+Print a help message.
+
+=item B<--comments>, B<-c>
+
+Display comments. This option can be negated with --no: --no-comments
+
+=back
+
+=head1 EXAMPLE CONFIG
+
+Save this as ~/.signoffsrc
+
+ # your login credentials
+ $username = "whatever";
+ $password = "secret";
+ # if you want to use a script:
+ # chomp ($password = `getpw whatever`);
+
+ # Everthing below this line is optional
+
+ # should we display packages that's can't be signed off?
+ $display_disabled = 1;
+
+ # only display packages that don't have enough signoffs
+ $only_pending = 0;
+
+ # hide packages you have signed off already
+ $hide_signed_off = 0;
+
+ # only display packages that will move to these repos
+ @target_repos = qw(core unknown);
+
+ # you probably don't have to change those
+ $domain = "https://www.archlinux.org";
+ #chomp ($system_arch = `uname -m`);
+ $pacman_db = "/var/lib/pacman";
+
+=cut