Hello Guillem, Adam, all,

wow, this took a full year to actually implement, sorry for that. Long
plain rides are sometimes useful :-)

Guillem Jover [2015-03-10  5:39 +0100]:
> So given all the above, I'd say:
> 
>   Testsuite-Triggers: foo, bar, baz
> 
> from the union of all testsuites test depends, minus @ and @builddeps@,
> without versions, and with alternatives split (i.e. a simple comma
> separated package list). If the field is present then it overrides the
> automatically extracted value.

The attached patch against current git does that now, plus the
additional "drop binary packages produced by your own source". I'm not
really familiar with the dpkg code nor Perl, so I'm sure you have a
ton of simplifications, style nitpicks, and others.

In set_testsuite_triggers_field() I currently do:

+    return if $fields->{'Testsuite-Triggers'} || 
$fields->{'XS-Testsuite-Triggers'} ;

But I'm not sure at which point the Xs- prefix disappears, nor when the new
field would become official -- is it necessary to check for it here? Or just
for 'Testsuite-Triggers'?

Conversely, how do I say that the field should only aperar in the
.dsc, not in the .changes? This actually behaves correctly, and I
assume dpkg-genchanges has a whitelist of which fields to include, but
it'd be nice if you could confirm that.

I tested this against the following synthetic d/t/control which I
think covers all cases:

    -------- 8< ------------
    Tests: a
    Depends: @, pmount

    Tests: b
    Depends: gzip,
      coreutils,
      @builddeps@,
      blergh-dev,

    Tests: c

    Tests: d
    Depends: foo (>= 4) | bar (<< 5)
    -------- 8< ------------

This gives

    Testsuite-Triggers: bar, blergh-dev, coreutils, foo, pmount

in the .dsc: "gzip" got filtered out, all dependencies flattened and
finally sorted for a predictable/reproducible result.

I also tested it against the autopkgtest source package, a source
package with an explicit "XS-Testsuite-Triggers:" in d/control, and a
package without a test suite.

dpkg with this patch applied still builds and succeeds its tests
(although that doesn't say much as AFAICS dpkg-source.pl itself is not
covered by tests). I installed the built dpkg binaries and re-checked
dpkg-buildpackage -S on the above source packages.

Thanks for considering!

Martin
-- 
Martin Pitt                        | http://www.piware.de
Ubuntu Developer (www.ubuntu.com)  | Debian Developer  (www.debian.org)
From f76846ea3fe45c0c42245c6d0646a05e77498377 Mon Sep 17 00:00:00 2001
From: Martin Pitt <[email protected]>
Date: Sun, 1 May 2016 09:43:39 -0500
Subject: [PATCH] dpkg-source: Generate Testsuite-Triggers field from test
 dependencies

Sometimes autopkgtests regress due to change in a package which is only a test
dependency (Depends: in debian/tests/control), not a build or binary one. It is
useful to trigger a test if such a test dependency changes.

Record the union of all test dependency packages in a new Testsuite-Triggers:
field in the .dsc, so that they will be recorded in the Sources package index.
Ignore versions and flatten OR dependencies as they are not interesting for
determining reverse test dependencies and should not be (ab)used for replacing
debian/tests/control parsing.

Closes: #779559
LP: #1491145
---
 debian/changelog                   |  5 ++++
 scripts/Dpkg/Control/FieldsCore.pm |  4 +++
 scripts/dpkg-source.pl             | 51 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index c0b9735..f88f689 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -141,6 +141,11 @@ dpkg (1.18.5) UNRELEASED; urgency=medium
   [ Updated manpages translations ]
   * German (Helge Kreutzmann).
 
+  [ Martin Pitt ]
+  * dpkg-source: Record the union of all autopkgtest dependency packages in a
+    new Testsuite-Triggers: field in the .dsc, so that they will be recorded
+    in the Sources package index. Closes: #779559, LP: #1491145
+
  -- Guillem Jover <[email protected]>  Fri, 25 Dec 2015 14:20:16 +0100
 
 dpkg (1.18.4) unstable; urgency=medium
diff --git a/scripts/Dpkg/Control/FieldsCore.pm b/scripts/Dpkg/Control/FieldsCore.pm
index 3af6fa7..36e591d 100644
--- a/scripts/Dpkg/Control/FieldsCore.pm
+++ b/scripts/Dpkg/Control/FieldsCore.pm
@@ -332,6 +332,10 @@ our %FIELDS = (
         allowed => ALL_SRC,
         separator => FIELD_SEP_COMMA,
     },
+    'Testsuite-Triggers' => {
+        allowed => ALL_SRC,
+        separator => FIELD_SEP_COMMA,
+    },
     'Triggers-Awaited' => {
         allowed => CTRL_FILE_STATUS,
         separator => FIELD_SEP_SPACE,
diff --git a/scripts/dpkg-source.pl b/scripts/dpkg-source.pl
index 1cde71c..ca34f2a 100755
--- a/scripts/dpkg-source.pl
+++ b/scripts/dpkg-source.pl
@@ -356,6 +356,7 @@ if ($options{opmode} =~ /^(build|print-format|(before|after)-build|commit)$/) {
 
     # Check if we have a testsuite, and handle manual and automatic values.
     set_testsuite_field($fields);
+    set_testsuite_triggers_field($fields, @binarypackages);
 
     # Scan fields of dpkg-parsechangelog
     foreach (keys %{$changelog}) {
@@ -510,6 +511,56 @@ sub set_testsuite_field
     $fields->{'Testsuite'} = join ', ', sort keys %testsuite;
 }
 
+# recursively walk Dpkg::Deps tree, flatten AND and OR dependencies, add
+# package names to the given hash ref
+sub collect_test_deps
+{
+    my $dep = shift;
+    my $pkghash = shift;
+    return if $dep->is_empty();
+    if ($dep->isa('Dpkg::Deps::Simple')) {
+        $pkghash->{$dep->{package}} = 1;
+    } else {
+        foreach my $d ($dep->get_deps()) {
+            collect_test_deps($d, $pkghash);
+        }
+    }
+}
+
+sub set_testsuite_triggers_field
+{
+    my $fields = shift;
+    my @binarypackages = shift;
+    my $tc_path = "$dir/debian/tests/control";
+    my %testdeps;
+
+    # never overwrite a manually defined field
+    return if $fields->{'Testsuite-Triggers'} || $fields->{'XS-Testsuite-Triggers'} ;
+
+    # autopkgtest is the only test we can parse
+    return unless -e $tc_path;
+
+    # parse Tests: from debian/tests/control
+    my $control = Dpkg::Control::HashCore->new(
+        drop_empty => 1,
+        allow_duplicate => 1,
+        name => 'autopkgtest control');
+    open(my $tc_fh, '<', $tc_path)
+        or syserr(g_('cannot read %s'), $tc_path);
+    while($control->parse($tc_fh, $tc_path)) {
+        # strip out autopkgtest macro deps, dpkg cannot parse them
+        $control->{'Depends'} =~ s/(^|,)\s*(@|\@builddeps@)([[:space:],]|$)/$1$3/g;
+        my $deps = deps_parse($control->{'Depends'}, use_arch => 0);
+        collect_test_deps($deps, \%testdeps) if $deps;
+    }
+
+    # remove our own binaries
+    foreach my $p (@binarypackages) {
+        delete $testdeps{$p};
+    }
+    $fields->{'Testsuite-Triggers'} = join(', ', sort keys %testdeps) if %testdeps;
+}
+
 sub setopmode {
     my $opmode = shift;
 
-- 
2.7.4

Attachment: signature.asc
Description: PGP signature

Reply via email to