Hi Tomasz, > A quick glimpse tells me that it should be ok. Would you mind adding a > test to cover this functionality?
No problem — updated patch attached: commit d71b37d49e57dd6e31b4d6db5752dcdc607a2dd1 Author: Chris Lamb <la...@debian.org> Date: Sun Aug 20 16:25:45 2017 -0700 Support storing and retrieval of upstream signatures. (Closes: #871809) This commit adds support for optionally storing and regenerating an upstream signature with the tarball so that it can be verified by, for example, dpkg-source(1). Regardless of the original signature filename provided, it is always stored alongside the .delta and .id files as .sig for deterministic retrieval. The existing behaviour of pristine-tar is unchanged unless you specify the `-s` option; in particular, extraction of signatures is not performed by default - one must specify the filename. This is to prevent breaking existing behaviour. README | 3 ++ debian/control | 3 ++ pristine-tar | 62 ++++++++++++++++++++++++------ test/samples/signatures/foo-1.0.tar.gz.asc | 16 ++++++++ test/test_checkout.sh | 14 +++++++ 5 files changed, 87 insertions(+), 11 deletions(-) > Thanks, the amount of love pristine-tar is getting these days must > make it blush. :) :) Best wishes, -- ,''`. : :' : Chris Lamb `. `'` la...@debian.org / chris-lamb.co.uk `-
>From d71b37d49e57dd6e31b4d6db5752dcdc607a2dd1 Mon Sep 17 00:00:00 2001 From: Chris Lamb <la...@debian.org> Date: Sun, 20 Aug 2017 16:25:45 -0700 Subject: [PATCH] Support storing and retrieval of upstream signatures. (Closes: #871809) This commit adds support for optionally storing and regenerating an upstream signature with the tarball so that it can be verified by, for example, dpkg-source(1). Regardless of the original signature filename provided, it is always stored alongside the .delta and .id files as .sig for deterministic retrieval. The existing behaviour of pristine-tar is unchanged unless you specify the `-s` option; in particular, extraction of signatures is not performed by default - one must specify the filename. This is to prevent breaking existing behaviour. --- README | 3 ++ debian/control | 3 ++ pristine-tar | 62 ++++++++++++++++++++++++------ test/samples/signatures/foo-1.0.tar.gz.asc | 16 ++++++++ test/test_checkout.sh | 14 +++++++ 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 test/samples/signatures/foo-1.0.tar.gz.asc diff --git a/README b/README index c792882..710c2ff 100644 --- a/README +++ b/README @@ -9,3 +9,6 @@ The delta file is designed to be checked into revision control along-side the upstream branch, thus allowing Debian packages to be built entirely using sources in revision control, without the need to keep copies of upstream tarballs. See `delta-format.txt` for details on the format of the delta file. + +An optional upstream signature may be attached to tarballs for verification +by, for example, dpkg-source(1). diff --git a/debian/control b/debian/control index 35e3a4a..dab3b3f 100644 --- a/debian/control +++ b/debian/control @@ -37,3 +37,6 @@ Description: regenerate pristine tarballs the upstream branch, thus allowing Debian packages to be built entirely using sources in revision control, without the need to keep copies of upstream tarballs. + . + An optional upstream signature may be attached to tarballs for verification + by, for example, dpkg-source(1). diff --git a/pristine-tar b/pristine-tar index d4f4b0e..1c4eaf0 100755 --- a/pristine-tar +++ b/pristine-tar @@ -10,7 +10,7 @@ B<pristine-tar> [-vdk] gendelta I<tarball> I<delta> B<pristine-tar> [-vdk] gentar I<delta> I<tarball> -B<pristine-tar> [-vdk] [-m message] commit I<tarball> [I<upstream>] +B<pristine-tar> [-vdk] [-m message] [-s signaturefile] commit I<tarball> [I<upstream>] B<pristine-tar> [-vdk] checkout I<tarball> @@ -120,6 +120,14 @@ Don't clean up the temporary directory on exit. Use this option to specify a custom commit message to pristine-tar commit. +=item -s signaturefile + +=item --signature-file=signaturefile + +Use this option to optionally commit or checkout an upstream signature +file for the tarball. Note that extraction of signatures is not +performed by default. + =back =head1 EXAMPLES @@ -198,6 +206,7 @@ use Pristine::Tar; use Pristine::Tar::Delta; use Pristine::Tar::Formats; use Pristine::Tar::DeltaTools; +use File::Copy; use File::Path; use File::Basename; use Cwd qw{getcwd abs_path}; @@ -226,7 +235,7 @@ use constant { XDELTA_LONG => "2.0" }; -my $message; +my ($message, $signature_file); my $genversion = version_from_env(XDELTA3, "xdelta" => XDELTA, "xdelta3" => XDELTA3); @@ -243,7 +252,8 @@ dispatch( verify => [ \&verify, 1 ], }, options => { - "m|message=s" => \$message, + "m|message=s" => \$message, + "s|signature-file=s" => \$signature_file, }, ); @@ -251,8 +261,9 @@ sub usage { print STDERR "Usage: pristine-tar [-vdk] gendelta tarball delta\n"; print STDERR " pristine-tar [-vdk] gentar delta tarball\n"; print STDERR - " pristine-tar [-vdk] [-m message] commit tarball [upstream]\n"; - print STDERR " pristine-tar [-vdk] checkout tarball\n"; +" pristine-tar [-vdk] [-m message] [-s signaturefile] commit tarball [upstream]\n"; + print STDERR + " pristine-tar [-vdk] [-s signaturefile] checkout tarball\n"; print STDERR " pristine-tar [-vdk] verify tarball\n"; print STDERR " pristine-tar list\n"; exit 1; @@ -780,8 +791,9 @@ sub checkoutdelta { my $branch = "pristine-tar"; my $deltafile = basename($tarball) . ".delta"; my $idfile = basename($tarball) . ".id"; + my $sigfile = basename($tarball) . ".asc"; - my ($delta, $id); + my ($delta, $id, $signature); my $vcs = vcstype(); if ($vcs eq "git") { @@ -810,11 +822,19 @@ sub checkoutdelta { if (!length $id) { error "git show $branch:$idfile returned no id"; } + if (defined $signature_file) { + # We only extract the signature if the user specifically requested + # it and we assume the data will fit comfortably into memory. + $signature = `git show $branch:\Q$sigfile\E`; + if ($?) { + error "git show $branch:$sigfile failed"; + } + } } else { die "unsupported vcs $vcs"; } - return ($delta, $id); + return ($delta, $id, $signature); } sub commitdelta { @@ -825,6 +845,7 @@ sub commitdelta { my $branch = "pristine-tar"; my $deltafile = basename($tarball) . ".delta"; my $idfile = basename($tarball) . ".id"; + my $sigfile = basename($tarball) . ".asc"; my $commit_message = defined $message ? $message @@ -839,6 +860,9 @@ sub commitdelta { open(OUT, ">$tempdir/$idfile") || die "$tempdir/$idfile: $!"; print OUT "$id\n"; close OUT; + if (defined $signature_file) { + copy($signature_file, "$tempdir/$sigfile") || die "$tempdir/$sigfile: $!"; + } # Commit the delta to a branch in git without affecting the # index, and without touching the working tree. Aka deep @@ -867,6 +891,9 @@ sub commitdelta { "git ls-tree -r --full-name $branch | git update-index --index-info"); } doit("git", "update-index", "--add", $deltafile, $idfile); + if (defined $signature_file) { + doit("git", "update-index", "--add", $sigfile); + } my $sha = `git write-tree`; if ($?) { error("git write-tree failed"); @@ -896,6 +923,9 @@ sub commitdelta { } message("committed $deltafile to branch $branch"); + if (defined $signature_file) { + message("committed $sigfile to branch $branch"); + } } else { die "unsupported vcs $vcs"; } @@ -910,6 +940,9 @@ sub commit { } check_file_exists($tarball); + if (defined $signature_file) { + check_file_exists($signature_file); + } my $tempdir = tempdir(); my ($sourcedir, $id) = export($upstream); @@ -937,7 +970,7 @@ sub checkout { check_directory_exists(dirname($tarball)); - my ($delta, $id) = checkoutdelta($tarball); + my ($delta, $id, $signature) = checkoutdelta($tarball); my ($sourcedir, undef) = export($id); my $pid = open(GENTAR, "|-"); if (!$pid) { @@ -950,6 +983,13 @@ sub checkout { print GENTAR $delta; close GENTAR || error "failed to generate tarball"; message("successfully generated $tarball") unless $opts{quiet}; + + if (defined $signature_file) { + open(OUT, ">$signature_file") || die "$signature_file: $!"; + print OUT $signature; + close OUT; + message("successfully generated $signature_file") unless $opts{quiet}; + } } sub list { @@ -975,7 +1015,7 @@ sub verify { check_file_exists($tarball); - my ($deltadata, $id) = checkoutdelta($tarball); + my ($deltadata, $id, undef) = checkoutdelta($tarball); my $deltafile = File::Temp->new(); print $deltafile $deltadata; @@ -988,14 +1028,14 @@ sub verify { sub check_directory_exists { my $dirname = shift; if (!-d $dirname) { - error "The directory $dirname does not exist."; + error "The directory $dirname does not exist."; } } sub check_file_exists { my $filename = shift; if (!$filename eq "-" and !-f $filename) { - error "The file $filename does not exist."; + error "The file $filename does not exist."; } } diff --git a/test/samples/signatures/foo-1.0.tar.gz.asc b/test/samples/signatures/foo-1.0.tar.gz.asc new file mode 100644 index 0000000..4007584 --- /dev/null +++ b/test/samples/signatures/foo-1.0.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEwv5L0nHBObhsUz5GHpU+J9QxHlgFAlmaJtQACgkQHpU+J9Qx +Hlhp4w/+Mar21XUcP2rsNXSUl/+bwW87tNGuGSCQscclPuJHz754mQJwFQvVqLT3 +72xL4xwv60+CTOLvH9iFvGGt8oFKBpPOOducPXm/l3J/IkY4B7wuYY6J8ZbFE6ue +jpC8VFj/JX2jAWrqiF0eC95MIyOtvFO52cr76/7vdmnrUpnY1Bv6dKGb2UQenYjO +F17Y85ZKugYnuvHy+4dbi4mhTuNUE6tEKwK/kiY3tc5e64b3KkqOvRMjxiW+I7oR +Be8b2CIKoBbfGOYb5qfE2Fmvd7XqdC/rqoYf/hMm8I4wzJ1IQa1kAnkvtqh0nbbP +NET1XE8YF80SDfmsslBsbAhH2s+dnJq1kMtyC+0RZN4y/qdcmuXnl2VGtyXFxWgS +QdoXGFcxmbQOeaPsAFcFAnalyG5sjQT+FfzXeBa2iSamvFz4o/8EyHEvUrXrAieM +YLFPwd5pvThV4/rB3cHG3Kyw6gxhM5tMAG9a8yHRaGq0r9q7QZJIC2dRMBCuSyTc +s9zeUgmEVwtpAYLb5ESgmFRU0xiVh3smyks36SuoaiZjknJwkC0LIG/Ptc5c7ZL3 +Bn5uAV8W0f3JeEQJZD7aFlKqOyiaGLfuOmsh1LUSpJov+voRBGxrJK6+Yl60ZQtb +g9oqBXp6AmGnFwOCImwXD17qQct3qXRn0vmwIki3bxcEY+c8Yvg= +=ZDm8 +-----END PGP SIGNATURE----- diff --git a/test/test_checkout.sh b/test/test_checkout.sh index b661ba9..ad13b75 100644 --- a/test/test_checkout.sh +++ b/test/test_checkout.sh @@ -16,4 +16,18 @@ test_checkout_noop() { assertTrue "$tarball should not be overwritten" "test '$tarball' -ot NOW" } +test_checkout_signature() { + local orig_tarball=$SAMPLES/tarballs/foo-1.0.tar.gz + local upstream_signature=$SAMPLES/signatures/foo-1.0.tar.gz.asc + local tarball=$(basename "$orig_tarball") + local signature=$(basename "$upstream_signature") + + git_init pkg + import_tarball "$orig_tarball" + pristine-tar commit -s "${upstream_signature}" "$orig_tarball" + false + assertSuccess pristine-tar checkout -s "$signature" "$tarball" + assertTrue "$signature generated successfully" "cmp '$upstream_signature' '$signature'" +} + . shunit2 -- 2.14.1