File: jetring-review

package info (click to toggle)
jetring 0.30
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 532 kB
  • sloc: perl: 462; sh: 175; makefile: 25
file content (121 lines) | stat: -rwxr-xr-x 2,949 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/perl
# Given a keyring and a changeset, shows what gpg would do if it
# applied the changeset to the keyring. The keyring is not modified.
use warnings;
use strict;
use File::Temp qw(tempdir);
use Cwd q{abs_path};

my @allowed_actions=qw(import edit-key delete-key);
my @gpgopts=qw(--command-fd 0 --no-auto-check-trustdb --options /dev/null
	--no-default-keyring);

my $diff=0;
if (@ARGV && $ARGV[0] eq '-d') {
	$diff=1;
	shift;
}
my $keyring=shift || usage();
my $changeset=shift || usage();

# avoid gnupg touching ~/.gnupg
$ENV{GNUPGHOME}=tempdir("jetring.XXXXXXXXXX", TMPDIR => 1, CLEANUP => 1);

$keyring=abs_path($keyring); # gpg works better with an absolute path

my $testring=$keyring.".tmp.$$";
if (-e $testring) {
	die "$testring exists";
}
system("cp", $keyring, $testring) == 0 || die "copy failed";
push @gpgopts, "--keyring", $testring;

my $secring="secret-dummy.$$";
sub END {
	unlink $secring if defined $secring;
	if (defined $testring) {
		unlink $testring;
		unlink $testring."~";# gpg backup file
		unlink $testring.".cache"; # generated by jetring-diff
	}
}
open (SECRET_DUMMY, ">$secring") || die "$secring: $!";
close SECRET_DUMMY;
push @gpgopts, "--secret-keyring", abs_path($secring);

my %fields;
my $field;
open(CHANGESET, "<", $changeset) || die "$changeset: $!";
while (<CHANGESET>) {
	chomp;
	if ($_ eq "-----BEGIN PGP SIGNED MESSAGE-----") {
		<CHANGESET> for 1..2;
		next;
	}
	elsif ($_ eq "-----BEGIN PGP SIGNATURE-----") {
		last;
	}
	if (/^([^\s]+):(?:\s+(.*))?/) {
		$field=lc $1;
		if (defined $2) {
			$fields{$field}=$2;
		}
		else {
			$fields{$field}='';
		}
	}
	elsif (/^\s+(.*)/ && defined $field) {
		$fields{$field}.="\n" if length $fields{$field};
		$fields{$field}.=$1;
	}
	elsif ($_ eq "") {
		process() if defined $field;
		%fields=();
		$field=undef;
	}
	else {
		die "parse error on line $. of $changeset";
	}
}
close CHANGESET;
process() if defined $field;

if ($diff) {
	system("jetring-diff", $keyring, $testring) == 0 ||
		die "jetring-diff exited nonzero";
}

sub process {
	if (! exists $fields{action}) {
		die "$changeset missing action field";
	}
	my @action=split(' ', $fields{action});
	my $command=shift @action;
	if (! grep { $_ eq $command } @allowed_actions) {
		die "$changeset contains disallowed action \"$command\"";
	}
	if (! exists $fields{data}) {
		die "$changeset missing data field";
	}

	print "gpg --$command @action\n";
	my $pid = open(GPG, "|-");
	$SIG{PIPE} = 'IGNORE';
	if (! $pid) {
		exec("gpg", @gpgopts, "--$command", @action) ||
			die("failed to run gpg");
	}
	$|=1;
	GPG->autoflush(1);
	foreach my $line (split("\n", $fields{data})) {
		print ">> $line\n" if $command ne 'import';
		print GPG "$line\n" || die "failed talking to gpg";
		sleep 1 if $command ne 'import';  # makes output clearer
	}
	close GPG || die "gpg exited nonzero";
	print "gpg operation complete\n\n";
}

sub usage {
	die "Usage: jetring-review [-d] keyring changeset\n"; 
}