summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdh154
-rw-r--r--lib/Debian/Debhelper/Sequence.pm127
-rw-r--r--lib/Debian/Debhelper/SequencerUtil.pm143
-rwxr-xr-xt/dh-sequencer.t157
4 files changed, 456 insertions, 125 deletions
diff --git a/dh b/dh
index b86e525d..a44bd12d 100755
--- a/dh
+++ b/dh
@@ -12,6 +12,7 @@ use constant {
'UNSKIPPABLE_CLI_OPTIONS_BUILD_SYSTEM' => q(-S|--buildsystem|-D|--sourcedir(?:ectory)?|-B|--builddir(?:ectory)?),
};
use Debian::Debhelper::Dh_Lib;
+use Debian::Debhelper::Sequence;
use Debian::Debhelper::SequencerUtil;
our $VERSION = DH_BUILTIN_VERSION;
@@ -404,13 +405,19 @@ qw{
dh_fixperms
dh_missing
});
-my @ba=(
+my @ba=(map {
+ {
+ 'command' => $_,
+ 'command-options' => [],
+ 'sequence-limitation' => SEQUENCE_TYPE_ARCH_ONLY,
+ }
+} (
(!compat(11) ? qw(dh_dwz) : qw()),
qw{
dh_strip
dh_makeshlibs
dh_shlibdeps
-});
+}));
if (! getpackages("arch")) {
@ba=();
}
@@ -420,19 +427,28 @@ my @b=qw{
dh_md5sums
dh_builddeb
};
-$sequences{clean} = [@bd_minimal, qw{
+
+sub _add_sequence {
+ my @args = @_;
+ my $seq = Debian::Debhelper::Sequence->new(@args);
+ my $name = $seq->name;
+ $sequences{$name} = $seq;
+ if ($seq->allowed_subsequences eq SEQUENCE_ARCH_INDEP_SUBSEQUENCES) {
+ for my $subseq ((SEQUENCE_TYPE_ARCH_ONLY, SEQUENCE_TYPE_INDEP_ONLY)) {
+ my $subname = "${name}-${subseq}";
+ $sequences{$subname} = $seq;
+ }
+ }
+ return;
+}
+
+_add_sequence('build', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, @bd);
+_add_sequence('install', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, to_rules_target("build"), @i);
+_add_sequence('binary', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, to_rules_target("install"), @ba, @b);
+_add_sequence('clean', SEQUENCE_NO_SUBSEQUENCES, @bd_minimal, qw{
dh_auto_clean
dh_clean
-}];
-$sequences{'build-indep'} = [@bd];
-$sequences{'build-arch'} = [@bd];
-$sequences{build} = [to_rules_target("build-arch"), to_rules_target("build-indep")];
-$sequences{'install-indep'} = [to_rules_target("build-indep"), @i];
-$sequences{'install-arch'} = [to_rules_target("build-arch"), @i];
-$sequences{'install'} = [to_rules_target("build"), to_rules_target("install-arch"), to_rules_target("install-indep")];
-$sequences{'binary-indep'} = [to_rules_target("install-indep"), @b];
-$sequences{'binary-arch'} = [to_rules_target("install-arch"), @ba, @b];
-$sequences{binary} = [to_rules_target("install"), to_rules_target("binary-arch"), to_rules_target("binary-indep")];
+});
# Additional command options
my %command_opts;
@@ -452,34 +468,18 @@ sub _filter_sequences_for_conditional_add_ons {
my @sequences = @_;
# If it is unconditional, then there is no issues.
return @sequences if $DH_INTERNAL_ADDON_TYPE eq 'both' or not @sequences;
- # Typically, if you add a command to a sequence, then you will in fact add it to two. E.g.
- # Adding dh_foo after dh_installdocs will affect both install-arch AND install-indep. We want
- # this to "just work(tm)" with a conditional add-on to avoid too much hassle (i.e. only affect
- # the relevant sequence). At the same time, we must abort if a sequence like "clean" is
- # affected.
- my (%sequence_stems, @filtered);
-
- for my $sequence_name (@sequences) {
- my $sequence_type = _sequence_type($sequence_name);
- my $sequence_stem = $sequence_name;
- if ($sequence_type ne 'both') {
- $sequence_stem =~ s/-\Q${sequence_type}//;
- }
- if ($sequence_type eq $DH_INTERNAL_ADDON_TYPE) {
- push(@filtered, $sequence_name);
- $sequence_stems{$sequence_stem} = 1;
- }
- elsif (not exists($sequence_stems{$sequence_stem})) {
- $sequence_stems{$sequence_stem} = 0;
- }
- }
- for my $sequence_name (@sequences) {
- my $sequence_type = _sequence_type($sequence_name);
- my $sequence_stem = $sequence_name;
- if ($sequence_type ne 'both') {
- $sequence_stem =~ s/-\Q${sequence_type}//;
- }
- if (not $sequence_stems{$sequence_stem}) {
+ for my $seq (@sequences) {
+ # Typically, if you add a command to a sequence, then you will in fact add it to two. E.g.
+ # Adding dh_foo after dh_installdocs will affect both install-arch AND install-indep. We want
+ # this to "just work(tm)" with a conditional add-on to avoid too much hassle (i.e. only affect
+ # the relevant sequence). At the same time, we must abort if a sequence like "clean" is
+ # affected.
+ #
+ # We solve the above by checking if the sequence has an -arch + an -indep variant and then
+ # insert the command only for that sequence variant.
+
+ if ($seq->allowed_subsequences ne SEQUENCE_ARCH_INDEP_SUBSEQUENCES) {
+ my $sequence_name = $seq->name;
warning("The add-on ${DH_INTERNAL_ADDON_NAME} attempted to modify the sequence ${sequence_name} (possibly "
. "indirectly) but the add-on is conditional for \"*-${DH_INTERNAL_ADDON_TYPE}\" targets");
warning("Hint: You may have to move the build-dependency for dh-sequence-${DH_INTERNAL_ADDON_NAME} to "
@@ -488,7 +488,7 @@ sub _filter_sequences_for_conditional_add_ons {
. " targets\n");
}
}
- return @filtered;
+ return @sequences;
}
sub _register_cmd_added_by_addon {
@@ -522,9 +522,10 @@ sub _sequences_containing_cmd {
my ($cmd) = @_;
my @sequences;
foreach my $sequence_name (keys %sequences) {
- for my $scmd (@{$sequences{$sequence_name}}) {
- if ($scmd eq $cmd) {
- push(@sequences, $sequence_name);
+ my $seq = $sequences{$sequence_name};
+ for my $scmd (@{$seq->{'_cmds'}}) {
+ if ($scmd->{'command'} eq $cmd) {
+ push(@sequences, $seq);
last;
}
}
@@ -532,6 +533,15 @@ sub _sequences_containing_cmd {
return @sequences;
}
+sub _seq_cmd {
+ my ($cmd_name) = @_;
+ return {
+ 'command' => $cmd_name,
+ 'command-options' => [],
+ 'sequence-limitation' => $DH_INTERNAL_ADDON_TYPE,
+ };
+}
+
# sequence addon interface
sub _insert {
my ($offset, $existing, $new) = @_;
@@ -539,20 +549,8 @@ sub _insert {
@affected_sequences = _filter_sequences_for_conditional_add_ons(@affected_sequences);
return if not @affected_sequences;
_register_cmd_added_by_addon($new);
- foreach my $sequence (@affected_sequences) {
- my @list=@{$sequences{$sequence}};
- my @new;
- foreach my $command (@list) {
- if ($command eq $existing) {
- push @new, $new if $offset < 0;
- push @new, $command;
- push @new, $new if $offset > 0;
- }
- else {
- push @new, $command;
- }
- }
- $sequences{$sequence}=\@new;
+ for my $seq (@affected_sequences) {
+ $seq->_insert($offset, $existing, _seq_cmd($new));
}
}
sub insert_before {
@@ -568,25 +566,38 @@ sub remove_command {
my @affected_sequences = _sequences_containing_cmd($command);
@affected_sequences = _filter_sequences_for_conditional_add_ons(@affected_sequences);
return if not @affected_sequences;
- foreach my $sequence (@affected_sequences) {
- $sequences{$sequence}=[grep { $_ ne $command } @{$sequences{$sequence}}];
+ for my $seq (@affected_sequences) {
+ $seq->remove_command($command);
}
return;
}
sub add_command {
my ($command, $sequence) = @_;
- _filter_sequences_for_conditional_add_ons($sequence);
+ _assert_not_conditional_sequence_addon('add_command');
_register_cmd_added_by_addon($command);
- unshift @{$sequences{$sequence}}, $command;
+ if (not exists($sequences{$sequence})) {
+ _add_sequence($sequence, SEQUENCE_NO_SUBSEQUENCES, _seq_cmd($command));
+ } else {
+ my $seq = $sequences{$sequence};
+ _filter_sequences_for_conditional_add_ons($seq);
+ $seq->add_command_at_start(_seq_cmd($command))
+ }
return;
}
sub add_command_at_end {
my ($command, $sequence) = @_;
- _filter_sequences_for_conditional_add_ons($sequence);
+ _assert_not_conditional_sequence_addon('add_command');
_register_cmd_added_by_addon($command);
- push(@{$sequences{$sequence}}, $command);
+ if (not exists($sequences{$sequence})) {
+ _add_sequence($sequence, SEQUENCE_NO_SUBSEQUENCES, _seq_cmd($command));
+ } else {
+ my $seq = $sequences{$sequence};
+ _filter_sequences_for_conditional_add_ons($seq);
+ $seq->add_command_at_end(_seq_cmd($command))
+ }
return;
}
+
sub add_command_options {
my $command=shift;
# Implement if actually needed (Complicated as dh_foo becomes dh_foo -a && dh_foo -i <extra_options>
@@ -595,6 +606,7 @@ sub add_command_options {
push @{$command_opts{$command}}, @_;
return;
}
+
sub remove_command_options {
my ($command, @cmd_options) = @_;
# Implement if actually needed (Complicated as dh_foo <extra_options> becomes
@@ -643,7 +655,7 @@ sub _compute_addons {
my ($sequence_name, @addon_requests_from_args) = @_;
my (@enabled_addons, %disabled_addons, %enabled, $bd_dh_sequences_ref);
my @addon_requests;
- my $sequence_type = _sequence_type($sequence_name);
+ my $sequence_type = sequence_type($sequence_name);
# Order is important; DH_EXTRA_ADDONS must come before everything
# else; then comes built-in and finally argument provided add-ons
@@ -1165,16 +1177,6 @@ sub can_skip {
return 1;
}
-sub _sequence_type {
- my ($sequence_name) = @_;
- if ($sequence_name =~ m/-indep$/) {
- return 'indep';
- } elsif ($sequence_name =~ m/-arch/) {
- return 'arch';
- }
- return 'both';
-}
-
=head1 SEE ALSO
L<debhelper(7)>
diff --git a/lib/Debian/Debhelper/Sequence.pm b/lib/Debian/Debhelper/Sequence.pm
new file mode 100644
index 00000000..fc857055
--- /dev/null
+++ b/lib/Debian/Debhelper/Sequence.pm
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+#
+# Internal library functions for the dh(1) command
+
+package Debian::Debhelper::Sequence;
+use strict;
+use warnings;
+
+use Exporter qw(import);
+
+use Debian::Debhelper::SequencerUtil qw(extract_rules_target_name sequence_type SEQUENCE_NO_SUBSEQUENCES
+ SEQUENCE_ARCH_INDEP_SUBSEQUENCES SEQUENCE_TYPE_ARCH_ONLY SEQUENCE_TYPE_INDEP_ONLY SEQUENCE_TYPE_BOTH);
+
+
+sub _as_command {
+ my ($input) = @_;
+ if (ref($input) eq 'HASH') {
+ return $input;
+ }
+ my $rules_target = extract_rules_target_name($input);
+ if (defined($rules_target)) {
+ my $sequence_type = sequence_type($rules_target);
+ return {
+ 'command' => $input,
+ 'command-options' => [],
+ 'sequence-limitation' => $sequence_type,
+ }
+ }
+ return {
+ 'command' => $input,
+ 'command-options' => [],
+ 'sequence-limitation' => SEQUENCE_TYPE_BOTH,
+ }
+}
+
+sub new {
+ my ($class, $name, $sequence_type, @cmds) = @_;
+ return bless({
+ '_name' => $name,
+ '_subsequences' => $sequence_type,
+ '_cmds' => [map {_as_command($_)} @cmds],
+ }, $class);
+}
+
+sub name {
+ my ($this) = @_;
+ return $this->{'_name'};
+}
+
+sub allowed_subsequences {
+ my ($this) = @_;
+ return $this->{'_subsequences'};
+}
+
+sub _insert {
+ my ($this, $offset, $existing, $new) = @_;
+ my @list = @{$this->{'_cmds'}};
+ my @new;
+ my $new_cmd = _as_command($new);
+ foreach my $command (@list) {
+ if ($command->{'command'} eq $existing) {
+ push(@new, $new_cmd) if $offset < 0;
+ push(@new, $command);
+ push(@new, $new_cmd) if $offset > 0;
+ } else {
+ push(@new, $command);
+ }
+ }
+ $this->{'_cmds'} = \@new;
+ return;
+}
+
+sub remove_command {
+ my ($this, $command) = @_;
+ $this->{'_cmds'} = [grep { $_->{'command'} ne $command } @{$this->{'_cmds'}}];
+ return;
+}
+
+sub add_command_at_start {
+ my ($this, $command) = @_;
+ unshift(@{$this->{'_cmds'}}, _as_command($command));
+ return;
+}
+
+sub add_command_at_end {
+ my ($this, $command) = @_;
+ push(@{$this->{'_cmds'}}, _as_command($command));
+ return;
+}
+
+sub rules_target_name {
+ my ($this, $sequence_type) = @_;
+ die("Internal error: Invalid sequence type $sequence_type") if $sequence_type eq SEQUENCE_NO_SUBSEQUENCES;
+ my $name = $this->{'_name'};
+ my $allowed_sequence_type = $this->{'_subsequences'};
+ if ($sequence_type ne SEQUENCE_TYPE_BOTH and $allowed_sequence_type eq SEQUENCE_NO_SUBSEQUENCES) {
+ die("Internal error: Requested subsequence ${sequence_type} of sequence ${name}, but it has no subsequences");
+ }
+ if ($sequence_type ne SEQUENCE_TYPE_BOTH) {
+ return "${name}-${sequence_type}";
+ }
+ return $name;
+}
+
+sub as_rules_target_command {
+ my ($this) = shift;
+ my $rules_name = $this->rules_target_name(@_);
+ return "debian/rules ${rules_name}";
+}
+
+sub flatten_sequence {
+ my ($this, $sequence_type) = @_;
+ die("Invalid sequence type $sequence_type") if $sequence_type eq SEQUENCE_NO_SUBSEQUENCES;
+ my @cmds;
+ for my $cmd_desc (@{$this->{'_cmds'}}) {
+ my $seq_limitation = $cmd_desc->{'sequence-limitation'};
+ if ($seq_limitation eq $sequence_type or $sequence_type eq SEQUENCE_TYPE_BOTH or $seq_limitation eq SEQUENCE_TYPE_BOTH) {
+ my $cmd = $cmd_desc->{'command'};
+ my @cmd_options = $cmd_desc->{'command-options'};
+ push(@cmds, [$cmd, @cmd_options]);
+ next;
+ }
+ }
+ return @cmds;
+}
+
+1;
diff --git a/lib/Debian/Debhelper/SequencerUtil.pm b/lib/Debian/Debhelper/SequencerUtil.pm
index 9a9ce2bf..a943357d 100644
--- a/lib/Debian/Debhelper/SequencerUtil.pm
+++ b/lib/Debian/Debhelper/SequencerUtil.pm
@@ -5,17 +5,30 @@
package Debian::Debhelper::SequencerUtil;
use strict;
use warnings;
-use constant DUMMY_TARGET => 'debhelper-fail-me';
+use constant {
+ 'DUMMY_TARGET' => 'debhelper-fail-me',
+ 'SEQUENCE_NO_SUBSEQUENCES' => 'none',
+ 'SEQUENCE_ARCH_INDEP_SUBSEQUENCES' => 'both',
+ 'SEQUENCE_TYPE_ARCH_ONLY' => 'arch',
+ 'SEQUENCE_TYPE_INDEP_ONLY' => 'indep',
+ 'SEQUENCE_TYPE_BOTH' => 'both',
+};
use Exporter qw(import);
our @EXPORT = qw(
extract_rules_target_name
to_rules_target
+ sequence_type
unpack_sequence
rules_explicit_target
extract_skipinfo
DUMMY_TARGET
+ SEQUENCE_NO_SUBSEQUENCES
+ SEQUENCE_ARCH_INDEP_SUBSEQUENCES
+ SEQUENCE_TYPE_ARCH_ONLY
+ SEQUENCE_TYPE_INDEP_ONLY
+ SEQUENCE_TYPE_BOTH
);
our (%EXPLICIT_TARGETS, $RULES_PARSED);
@@ -32,39 +45,135 @@ sub to_rules_target {
return 'debian/rules '.join(' ', @_);
}
+sub sequence_type {
+ my ($sequence_name) = @_;
+ if ($sequence_name =~ m/-indep$/) {
+ return 'indep';
+ } elsif ($sequence_name =~ m/-arch/) {
+ return 'arch';
+ }
+ return 'both';
+}
+
+sub _agg_subseq {
+ my ($current_subseq, $outer_subseq) = @_;
+ if ($current_subseq eq $outer_subseq) {
+ return $current_subseq;
+ }
+ if ($current_subseq eq 'both') {
+ return $outer_subseq;
+ }
+ return $current_subseq;
+}
+
sub unpack_sequence {
my ($sequences, $sequence_name, $always_inline, $completed_sequences) = @_;
my (@sequence, @targets, %seen, %non_inlineable_targets, @stack);
+ my $sequence_type = sequence_type($sequence_name);
# Walk through the sequence effectively doing a DFS of the rules targets
# (when we are allowed to inline them).
- push(@stack, [@{$sequences->{$sequence_name}}]);
+ my $seq = $sequences->{$sequence_name};
+ push(@stack, [$seq->flatten_sequence($sequence_type)]);
while (@stack) {
my $current_sequence = pop(@stack);
COMMAND:
while (@{$current_sequence}) {
my $command = shift(@{$current_sequence});
+ if (ref($command) eq 'ARRAY') {
+ $command = $command->[0];
+ }
my $rules_target=extract_rules_target_name($command);
next if (defined($rules_target) and exists($completed_sequences->{$rules_target}));
- if (defined($rules_target) && ($always_inline ||
- ! exists($non_inlineable_targets{$rules_target}) &&
- ! defined(rules_explicit_target($rules_target)))) {
-
- # inline the sequence for this implicit target.
+ if (defined($rules_target) and $always_inline) {
+ my $subsequence = $sequences->{$rules_target};
+ my $subseq_type = _agg_subseq(sequence_type($rules_target), $sequence_type);
push(@stack, $current_sequence);
- $current_sequence = [@{$sequences->{$rules_target}}];
+ $current_sequence = [$subsequence->flatten_sequence($subseq_type)];
+ } elsif (defined($rules_target)) {
+ my $subsequence = $sequences->{$rules_target};
+ my $subseq_type = _agg_subseq(sequence_type($rules_target), $sequence_type);
+ my @subseq_types = ($subseq_type);
+ my %subtarget_status;
+ my ($transparent_subseq, $opaque_subseq, $subtarget_decided_both);
+ if ($subseq_type eq SEQUENCE_TYPE_BOTH) {
+ push(@subseq_types, SEQUENCE_TYPE_ARCH_ONLY, SEQUENCE_TYPE_INDEP_ONLY);
+ }
+ for my $ss_type (@subseq_types) {
+ my $full_rule_target = ($ss_type eq SEQUENCE_TYPE_BOTH) ? $rules_target : "${rules_target}-${ss_type}";
+ if (exists($completed_sequences->{$full_rule_target})) {
+ $subtarget_status{$ss_type} = 'complete';
+ last if $ss_type eq $subseq_type;
+ }
+ elsif (defined(rules_explicit_target($full_rule_target))) {
+ $subtarget_status{$ss_type} = 'opaque';
+ last if $ss_type eq $subseq_type;
+ }
+ else {
+ $subtarget_status{$ss_type} = 'transparent';
+ }
+ }
+ # At this point, %subtarget_status has 1 or 3 kv-pairs.
+ # - If it has 1, then just check that and be done
+ # - If it has 3, then "both" must be "transparent".
+
+ if (scalar(keys(%subtarget_status)) == 3) {
+ if ($subtarget_status{${\SEQUENCE_TYPE_ARCH_ONLY}} eq $subtarget_status{${\SEQUENCE_TYPE_INDEP_ONLY}}) {
+ # The "both" target is transparent and the subtargets agree. This is the common case
+ # of "everything is transparent" (or both subtargets are opaque) and we reduce that by
+ # reducing it to only have one key.
+ %subtarget_status = ( $subseq_type => $subtarget_status{${\SEQUENCE_TYPE_ARCH_ONLY}} );
+ # There is one special-case for this flow if both targets are opaque.
+ $subtarget_decided_both = 1;
+ } else {
+ # The subtargets have different status but we know that the "both" key must be irrelevant
+ # then. Remove it to simplify matters below.
+ delete($subtarget_status{${\SEQUENCE_TYPE_BOTH}});
+ }
+ }
+
+ if (scalar(keys(%subtarget_status)) == 1) {
+ # "Simple" case where we only have to check exactly one result
+ if ($subtarget_status{$subseq_type} eq 'opaque') {
+ $opaque_subseq = $subseq_type;
+ }
+ elsif ($subtarget_status{$subseq_type} eq 'transparent') {
+ $transparent_subseq = $subseq_type;
+ }
+ } else {
+ # Either can be transparent, opaque or complete at this point.
+ if ($subtarget_status{${\SEQUENCE_TYPE_ARCH_ONLY}} eq 'transparent') {
+ $transparent_subseq = SEQUENCE_TYPE_ARCH_ONLY
+ } elsif ($subtarget_status{${\SEQUENCE_TYPE_INDEP_ONLY}} eq 'transparent') {
+ $transparent_subseq = SEQUENCE_TYPE_INDEP_ONLY
+ }
+ if ($subtarget_status{${\SEQUENCE_TYPE_ARCH_ONLY}} eq 'opaque') {
+ $opaque_subseq = SEQUENCE_TYPE_ARCH_ONLY
+ } elsif ($subtarget_status{${\SEQUENCE_TYPE_INDEP_ONLY}} eq 'opaque') {
+ $opaque_subseq = SEQUENCE_TYPE_INDEP_ONLY
+ }
+ }
+ if ($opaque_subseq) {
+ if ($subtarget_decided_both) {
+ # Final special-case - we are here because the rules file define X-arch AND X-indep but
+ # not X. In this case, we want two d/rules X-{arch,indep} calls rather than a single
+ # d/rules X call.
+ for my $ss_type ((SEQUENCE_TYPE_ARCH_ONLY, SEQUENCE_TYPE_INDEP_ONLY)) {
+ my $rules_target_cmd = $subsequence->as_rules_target_command($ss_type);
+ push(@targets, $rules_target_cmd) if not $seen{$rules_target_cmd}++;
+ }
+ } else {
+ my $rules_target_cmd = $subsequence->as_rules_target_command($opaque_subseq);
+ push(@targets, $rules_target_cmd) if not $seen{$rules_target_cmd}++;
+ }
+ }
+ if ($transparent_subseq) {
+ push(@stack, $current_sequence);
+ $current_sequence = [$subsequence->flatten_sequence($transparent_subseq)];
+ }
next COMMAND;
} else {
if (defined($rules_target) and not $always_inline) {
next COMMAND if exists($non_inlineable_targets{$rules_target});
- my @opaque_targets = ($rules_target);
- while (my $opaque_target = pop(@opaque_targets)) {
- for my $c (@{$sequences->{$opaque_target}}) {
- my $subtarget = extract_rules_target_name($c);
- next if not defined($subtarget);
- next if exists($non_inlineable_targets{$subtarget});
- $non_inlineable_targets{$subtarget} = $rules_target;
- }
- }
push(@targets, $command) if not $seen{$command}++;
} elsif (! $seen{$command}) {
$seen{$command} = 1;
diff --git a/t/dh-sequencer.t b/t/dh-sequencer.t
index dd5c264a..6c38eae2 100755
--- a/t/dh-sequencer.t
+++ b/t/dh-sequencer.t
@@ -4,6 +4,7 @@ use strict;
use warnings;
use Test::More;
+use Debian::Debhelper::Sequence;
use Debian::Debhelper::SequencerUtil;
# Shorten variants of the sequences.
@@ -21,46 +22,85 @@ my @i = (qw{
dh_install
dh_missing
});
-my @ba=qw{
- dh_strip
- dh_makeshlibs
- dh_shlibdeps
-};
+my @ba = (
+ {
+ 'command' => 'dh_strip',
+ 'command-options' => [],
+ 'sequence-limitation' => SEQUENCE_TYPE_ARCH_ONLY,
+ },
+ {
+ 'command' => 'dh_makeshlibs',
+ 'command-options' => [],
+ 'sequence-limitation' => SEQUENCE_TYPE_ARCH_ONLY,
+ },
+ {
+ 'command' => 'dh_shlibdeps',
+ 'command-options' => [],
+ 'sequence-limitation' => SEQUENCE_TYPE_ARCH_ONLY,
+ }
+);
my @b=qw{
dh_installdeb
dh_gencontrol
dh_builddeb
};
+my @c=qw{
+ dh_testdir
+ dh_auto_clean
+ dh_clean
+};
-my %sequences = (
- 'build-indep' => [@bd],
- 'build-arch' => [@bd],
- 'build' => [to_rules_target("build-arch"), to_rules_target("build-indep")],
-
- 'install-indep' => [to_rules_target("build-indep"), @i],
- 'install-arch' => [to_rules_target("build-arch"), @i],
- 'install' => [to_rules_target("build"), to_rules_target("install-arch"), to_rules_target("install-indep")],
+my %sequences;
+
+sub _add_sequence {
+ my @args = @_;
+ my $seq = Debian::Debhelper::Sequence->new(@args);
+ my $name = $seq->name;
+ $sequences{$name} = $seq;
+ if ($seq->allowed_subsequences eq SEQUENCE_ARCH_INDEP_SUBSEQUENCES) {
+ for my $subseq ((SEQUENCE_TYPE_ARCH_ONLY, SEQUENCE_TYPE_INDEP_ONLY)) {
+ my $subname = "${name}-${subseq}";
+ $sequences{$subname} = $seq;
+ }
+ }
+ return;
+}
- 'binary-indep' => [to_rules_target("install-indep"), @b],
- 'binary-arch' => [to_rules_target("install-arch"), @ba, @b],
- 'binary' => [to_rules_target("install"), to_rules_target("binary-arch"), to_rules_target("binary-indep")],
-);
+_add_sequence('build', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, @bd);
+_add_sequence('install', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, to_rules_target("build"), @i);
+_add_sequence('binary', SEQUENCE_ARCH_INDEP_SUBSEQUENCES, to_rules_target("install"), @ba, @b);
+_add_sequence('clean', SEQUENCE_NO_SUBSEQUENCES, @c);
+
+sub _cmd_names {
+ my (@input) = @_;
+ my @cmds;
+ for my $cmd (@input) {
+ if (ref($cmd) eq 'HASH') {
+ push(@cmds, $cmd->{'command'});
+ } else {
+ push(@cmds, $cmd);
+ }
+ }
+ return \@cmds;
+}
my %sequences_unpacked = (
- 'build-indep' => [@bd],
- 'build-arch' => [@bd],
- 'build' => [@bd],
+ 'build-indep' => _cmd_names(@bd),
+ 'build-arch' => _cmd_names(@bd),
+ 'build' => _cmd_names(@bd),
+
+ 'install-indep' => _cmd_names(@bd, @i),
+ 'install-arch' => _cmd_names(@bd, @i),
+ 'install' => _cmd_names(@bd, @i),
- 'install-indep' => [@bd, @i],
- 'install-arch' => [@bd, @i],
- 'install' => [@bd, @i],
+ 'binary-indep' => _cmd_names(@bd, @i, @b),
+ 'binary-arch' => _cmd_names(@bd, @i, @ba, @b),
+ 'binary' => _cmd_names(@bd, @i, @ba, @b),
- 'binary-indep' => [@bd, @i, @b],
- 'binary-arch' => [@bd, @i, @ba, @b],
- 'binary' => [@bd, @i, @ba, @b],
+ 'clean' => _cmd_names(@c),
);
-plan tests => 11 + 3 * scalar(keys(%sequences));
+plan tests => 18 + 3 * scalar(keys(%sequences));
# We will horse around with %EXPLICIT_TARGETS in this test; it should
# definitely not attempt to read d/rules or the test will be break.
@@ -95,20 +135,73 @@ is_deeply(
is_deeply(
[unpack_sequence(\%sequences, 'binary', 0, { 'build' => 1, 'build-arch' => 1, 'build-indep' => 1})],
- [[], [@i, @ba, @b]],
+ [[], _cmd_names(@i, @ba, @b)],
+ 'Inlined binary sequence with build-* done has @i, @ba and @b');
+
+
+is_deeply(
+ [unpack_sequence(\%sequences, 'binary', 0, { 'build-arch' => 1, 'build-indep' => 1})],
+ [[], _cmd_names(@i, @ba, @b)],
'Inlined binary sequence with build-* done has @i, @ba and @b');
{
+ local $Debian::Debhelper::SequencerUtil::EXPLICIT_TARGETS{'build-arch'} = 1;
+ local $Debian::Debhelper::SequencerUtil::EXPLICIT_TARGETS{'build-indep'} = 1;
+
+ is_deeply(
+ [unpack_sequence(\%sequences, 'binary', 0, { 'build-arch' => 1, 'build-indep' => 1})],
+ [[], _cmd_names(@i, @ba, @b)],
+ 'Inlined binary sequence with build-* done has @i, @ba and @b');
+ my $actual = [unpack_sequence(\%sequences, 'binary')];
+ # @i should be "-i"-only, @ba + @b should be both.
+ # Unfortunately, unpack_sequence cannot show that.
+ my $expected = [[to_rules_target('build-arch'), to_rules_target('build-indep')], _cmd_names(@i, @ba, @b)];
+ # Permit some fuzz on the order between build-arch and build-arch
+ if ($actual->[0][0] eq to_rules_target('build-indep')) {
+ $expected->[0][0] = to_rules_target('build-indep');
+ $expected->[0][1] = to_rules_target('build-arch');
+ }
+ is_deeply(
+ $actual,
+ $expected,
+ 'Inlined binary sequence with explicit build-* has explicit d/rules build-{arch,indep} + @i, @ba, @b');
+
+ is_deeply(
+ [unpack_sequence(\%sequences, 'binary', 0, { 'build' => 1})],
+ [[], _cmd_names(@i, @ba, @b)],
+ 'Inlined binary sequence with explicit build-* but done build has only @i, @ba and @b');
+}
+
+{
+ local $Debian::Debhelper::SequencerUtil::EXPLICIT_TARGETS{'build-indep'} = 1;
+ is_deeply(
+ [ unpack_sequence(\%sequences, 'binary', 0, { 'build-arch' => 1 }) ],
+ [ [to_rules_target('build-indep')], _cmd_names(@i, @ba, @b) ],
+ 'Inlined binary sequence with build-arch done and build-indep explicit has d/rules build-indep + @i, @ba and @b');
+
+ is_deeply(
+ [ unpack_sequence(\%sequences, 'binary-arch', 0, { 'build-arch' => 1 }) ],
+ [ [], _cmd_names(@i, @ba, @b) ],
+ 'Inlined binary-arch sequence with build-arch done and build-indep explicit has @i, @ba and @b');
+
+
+ is_deeply(
+ [ unpack_sequence(\%sequences, 'binary-indep', 0, { 'build-arch' => 1 }) ],
+ [ [to_rules_target('build-indep')], _cmd_names(@i, @b) ],
+ 'Inlined binary-indep sequence with build-arch done and build-indep explicit has d/rules build-indep + @i and @b');
+}
+
+{
local $Debian::Debhelper::SequencerUtil::EXPLICIT_TARGETS{'build'} = 1;
is_deeply(
[unpack_sequence(\%sequences, 'binary')],
- [[to_rules_target('build')], [@i, @ba, @b]],
+ [[to_rules_target('build')], _cmd_names(@i, @ba, @b)],
'Inlined binary sequence has all the commands but build target is opaque');
is_deeply(
[unpack_sequence(\%sequences, 'binary', 0, { 'build' => 1, 'build-arch' => 1, 'build-indep' => 1})],
- [[], [@i, @ba, @b]],
+ [[], _cmd_names(@i, @ba, @b)],
'Inlined binary sequence has all the commands with build-* done and not build-target');
is_deeply(
@@ -133,7 +226,7 @@ is_deeply(
[unpack_sequence(\%sequences, 'binary')],
# @bd_minimal, @bd and @i should be "-i"-only, @ba + @b should be both.
# Unfortunately, unpack_sequence cannot show that.
- [[to_rules_target('install-arch')], [@bd, @i, @ba, @b]],
+ [[to_rules_target('install-arch')], _cmd_names(@bd, @i, @ba, @b)],
'Inlined binary sequence has all the commands');
# Compat <= 8 ignores explicit targets!
@@ -152,7 +245,7 @@ is_deeply(
my $actual = [unpack_sequence(\%sequences, 'binary')];
# @i should be "-i"-only, @ba + @b should be both.
# Unfortunately, unpack_sequence cannot show that.
- my $expected = [[to_rules_target('build'), to_rules_target('install-arch')], [@i, @ba, @b]];
+ my $expected = [[to_rules_target('build'), to_rules_target('install-arch')], _cmd_names(@i, @ba, @b)];
# Permit some fuzz on the order between build and install-arch
if ($actual->[0][0] eq to_rules_target('install-arch')) {
$expected->[0][0] = to_rules_target('install-arch');