| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Config::Model::Dpkg::Dependency ; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
307312
|
use 5.10.1; |
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
57
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
1213
|
use Mouse; |
|
|
1
|
|
|
|
|
35115
|
|
|
|
1
|
|
|
|
|
5
|
|
|
6
|
1
|
|
|
1
|
|
105613
|
use namespace::autoclean; |
|
|
1
|
|
|
|
|
26557
|
|
|
|
1
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# Debian only module |
|
9
|
1
|
|
|
1
|
|
77
|
use lib '/usr/share/lintian/lib' ; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
10
|
1
|
|
|
1
|
|
705
|
use Lintian::Relation ; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use DB_File ; |
|
13
|
|
|
|
|
|
|
use Log::Log4perl qw(get_logger :levels); |
|
14
|
|
|
|
|
|
|
use Module::CoreList; |
|
15
|
|
|
|
|
|
|
use version ; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use Parse::RecDescent ; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
use AnyEvent::HTTP ; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# available only in debian. Black magic snatched from |
|
22
|
|
|
|
|
|
|
# /usr/share/doc/libapt-pkg-perl/examples/apt-version |
|
23
|
|
|
|
|
|
|
use AptPkg::Config '$_config'; |
|
24
|
|
|
|
|
|
|
use AptPkg::System '$_system'; |
|
25
|
|
|
|
|
|
|
use AptPkg::Version; |
|
26
|
|
|
|
|
|
|
use AptPkg::Cache ; |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use vars qw/$test_filter/ ; |
|
29
|
|
|
|
|
|
|
$test_filter = ''; # reserved for tests |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $logger = get_logger("Tree::Element::Value::Dependency") ; |
|
32
|
|
|
|
|
|
|
my $async_log = get_logger("Async::Value::Dependency") ; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# initialise the global config object with the default values |
|
35
|
|
|
|
|
|
|
$_config->init; |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# determine the appropriate system type |
|
38
|
|
|
|
|
|
|
$_system = $_config->system; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# fetch a versioning system |
|
41
|
|
|
|
|
|
|
my $vs = $_system->versioning; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $apt_cache = AptPkg::Cache->new ; |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# end black magic |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
extends qw/Config::Model::Value/ ; |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# when apply_fix is used ($arg[1]), this grammer will modify inline |
|
50
|
|
|
|
|
|
|
# the dependency value through the value ref ($arg[2]) |
|
51
|
|
|
|
|
|
|
my $grammar = << 'EOG' ; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
{ |
|
54
|
|
|
|
|
|
|
my @dep_errors ; |
|
55
|
|
|
|
|
|
|
my $add_error = sub { |
|
56
|
|
|
|
|
|
|
my ($err, $txt) = @_ ; |
|
57
|
|
|
|
|
|
|
push @dep_errors, "$err: '$txt'" ; |
|
58
|
|
|
|
|
|
|
return ; # to ensure production error |
|
59
|
|
|
|
|
|
|
} ; |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# comment this out when modifying the grammar |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
dependency: { @dep_errors = (); } |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
dependency: depend(s /\|/) eofile { |
|
68
|
|
|
|
|
|
|
$return = [ 1 , @{$item[1]} ] ; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
| { |
|
71
|
|
|
|
|
|
|
push( @dep_errors, "Cannot parse: '$text'" ) unless @dep_errors ; |
|
72
|
|
|
|
|
|
|
$return = [ 0, @dep_errors ]; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
depend: pkg_dep | variable |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# For the allowed stuff after ${foo}, see #702792 |
|
78
|
|
|
|
|
|
|
variable: /\${[\w:\-]+}[\w\.\-~+]*/ |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
pkg_dep: pkg_name dep_version(?) arch_restriction(?) { |
|
81
|
|
|
|
|
|
|
my $dv = $item[2] ; |
|
82
|
|
|
|
|
|
|
my $ar = $item[3] ; |
|
83
|
|
|
|
|
|
|
my @ret = ( $item{pkg_name} ) ; |
|
84
|
|
|
|
|
|
|
if (@$dv and @$ar) { push @ret, @{$dv->[0]}, @{$ar->[0]} ;} |
|
85
|
|
|
|
|
|
|
elsif (@$dv) { push @ret, @{$dv->[0]} ;} |
|
86
|
|
|
|
|
|
|
elsif (@$ar) { push @ret, undef, undef, @{$ar->[0]} ;} |
|
87
|
|
|
|
|
|
|
$return = \@ret ; ; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
arch_restriction: '[' osarch(s) ']' |
|
91
|
|
|
|
|
|
|
{ |
|
92
|
|
|
|
|
|
|
my $mismatch = 0; |
|
93
|
|
|
|
|
|
|
my $ref = $item[2] ; |
|
94
|
|
|
|
|
|
|
for (my $i = 0; $i < $#$ref -1 ; $i++ ) { |
|
95
|
|
|
|
|
|
|
$mismatch ||= ($ref->[$i][0] xor $ref->[$i+1][0]) ; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
my @a = map { ($_->[0] || '') . ($_->[1] || '') . $_->[2] } @$ref ; |
|
98
|
|
|
|
|
|
|
if ($mismatch) { |
|
99
|
|
|
|
|
|
|
$add_error->("some names are prepended with '!' while others aren't.", "@a") ; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
else { |
|
102
|
|
|
|
|
|
|
$return = \@a ; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
dep_version: '(' oper version ')' { $return = [ $item{oper}, $item{version} ] ;} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
pkg_name: /[a-z0-9][a-z0-9\+\-\.]+(?=\s|\Z|\(|\[)/ |
|
109
|
|
|
|
|
|
|
| /\S+/ { $add_error->("bad package name", $item[1]) ;} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
oper: '<<' | '<=' | '=' | '>=' | '>>' |
|
112
|
|
|
|
|
|
|
| /\S+/ { $add_error->("bad dependency version operator", $item[1]) ;} |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
version: variable | /[\w\.\-~:+]+(?=\s|\)|\Z)/ |
|
115
|
|
|
|
|
|
|
| /\S+/ { $add_error->("bad dependency version", $item[1]) ;} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# valid arch are listed by dpkg-architecture -L |
|
118
|
|
|
|
|
|
|
osarch: not(?) os(?) arch |
|
119
|
|
|
|
|
|
|
{ |
|
120
|
|
|
|
|
|
|
$return = [ $item[1][0], $item[2][0], $item[3] ]; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
not: '!' |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
os: /(any|uclibc-linux|linux|kfreebsd|knetbsd|kopensolaris|hurd|darwin|freebsd|netbsd|openbsd|solaris|uclinux) |
|
126
|
|
|
|
|
|
|
-/x |
|
127
|
|
|
|
|
|
|
| /\w+/ '-' { $add_error->("bad os in architecture specification", $item[1]) ;} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
arch: / (any |alpha|amd64 |arm\b |arm64 |armeb |armel |armhf |avr32 |
|
130
|
|
|
|
|
|
|
|hppa |i386 |ia64 |lpia |m32r |m68k |mips\b |mipsel |powerpc |
|
131
|
|
|
|
|
|
|
|powerpcspe |ppc64 |s390 |s390x |sh3\b |sh3eb |sh4\b |sh4eb |sparc\b |sparc64 |x32 ) |
|
132
|
|
|
|
|
|
|
(?=(\]| )) |
|
133
|
|
|
|
|
|
|
/x |
|
134
|
|
|
|
|
|
|
| /\w+/ { $add_error->("bad arch in architecture specification", $item[1]) ;} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
eofile: /^\Z/ |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
EOG |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
my $parser ; |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub dep_parser { |
|
144
|
|
|
|
|
|
|
$parser ||= Parse::RecDescent->new($grammar) ; |
|
145
|
|
|
|
|
|
|
return $parser ; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# this method may recurse bad: |
|
149
|
|
|
|
|
|
|
# check_dep -> meta filter -> control maintainer -> create control class |
|
150
|
|
|
|
|
|
|
# autoread started -> read all fileds -> read dependency -> check_dep ... |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub check_value { |
|
153
|
|
|
|
|
|
|
my $self = shift ; |
|
154
|
|
|
|
|
|
|
my %args = @_ > 1 ? @_ : (value => $_[0]) ; |
|
155
|
|
|
|
|
|
|
my $cb = delete $args{callback} || sub {} ; |
|
156
|
|
|
|
|
|
|
my $my_cb = sub { |
|
157
|
|
|
|
|
|
|
$self->check_dependency(@_, callback => $cb) ; |
|
158
|
|
|
|
|
|
|
} ; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
$args{fix} //= 0; |
|
161
|
|
|
|
|
|
|
$self->SUPER::check_value(%args, callback => $my_cb) ; |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub check_dependency { |
|
166
|
|
|
|
|
|
|
my $self = shift; |
|
167
|
|
|
|
|
|
|
my %args = @_ ; |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my ($value, $check, $silent, $notify_change, $ok, $callback,$apply_fix) |
|
170
|
|
|
|
|
|
|
= @args{qw/value check silent notify_change ok callback fix/} ; |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# value is one dependency, something like "perl ( >= 1.508 )" |
|
173
|
|
|
|
|
|
|
# or exim | mail-transport-agent or gnumach-dev [hurd-i386] |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# see http://www.debian.org/doc/debian-policy/ch-relationships.html |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# to get package list |
|
178
|
|
|
|
|
|
|
# wget -q -O - 'http://qa.debian.org/cgi-bin/madison.cgi?package=perl-doc&text=on' |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
my @dep_chain ; |
|
181
|
|
|
|
|
|
|
if (defined $value) { |
|
182
|
|
|
|
|
|
|
$logger->debug("calling check_depend with Parse::RecDescent with '$value'"); |
|
183
|
|
|
|
|
|
|
my $ret = dep_parser->dependency ( $value ) ; |
|
184
|
|
|
|
|
|
|
my $ok = shift @$ret ; |
|
185
|
|
|
|
|
|
|
if ($ok) { |
|
186
|
|
|
|
|
|
|
@dep_chain = @$ret ; |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
else { |
|
189
|
|
|
|
|
|
|
$self->add_error(@$ret) ; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# check_dependency is always called with a callback. This callback must |
|
194
|
|
|
|
|
|
|
# must called *after* all asynchronous calls are done (which depends on the |
|
195
|
|
|
|
|
|
|
# packages listed in the dependency). So use begin and end on this condvar and |
|
196
|
|
|
|
|
|
|
# nothing else, not send/recv |
|
197
|
|
|
|
|
|
|
my $pending_check = AnyEvent->condvar ; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
my $old = $value ; |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
my $check_depend_chain_cb = sub { |
|
202
|
|
|
|
|
|
|
# blocking with inner async calls |
|
203
|
|
|
|
|
|
|
$self->check_depend_chain($apply_fix, \@dep_chain, $old ) ; |
|
204
|
|
|
|
|
|
|
$self->on_check_all_done($apply_fix,\@dep_chain,$old, sub { $callback->(%args) if $callback; }); |
|
205
|
|
|
|
|
|
|
} ; |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
$async_log->debug("begin for ",$self->composite_name, " fix is $apply_fix") if $async_log->is_debug; |
|
208
|
|
|
|
|
|
|
$pending_check->begin($check_depend_chain_cb) ; |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
foreach my $dep (@dep_chain) { |
|
211
|
|
|
|
|
|
|
next unless ref($dep) ; # no need to check variables |
|
212
|
|
|
|
|
|
|
$pending_check->begin ; |
|
213
|
|
|
|
|
|
|
my $cb = sub { |
|
214
|
|
|
|
|
|
|
$self->check_or_fix_essential_package($apply_fix, $dep, $old) ; # sync |
|
215
|
|
|
|
|
|
|
$self->check_or_fix_dep($apply_fix, $dep, $old, sub { $pending_check -> end}) ; # async |
|
216
|
|
|
|
|
|
|
}; |
|
217
|
|
|
|
|
|
|
$self->check_or_fix_pkg_name($apply_fix, $dep, $old, $cb) ; # async |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
$async_log->debug("end for ",$self->composite_name) if $async_log->is_debug; |
|
222
|
|
|
|
|
|
|
$pending_check->end; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# this callback will be launched when all checks are done. this can be at |
|
226
|
|
|
|
|
|
|
# the 'end' call at this end of this sub if all calls of check_depend are |
|
227
|
|
|
|
|
|
|
# synchronous (which may be the case if all dependency informations are in cache) |
|
228
|
|
|
|
|
|
|
# or it can be in one of the call backs |
|
229
|
|
|
|
|
|
|
sub on_check_all_done { |
|
230
|
|
|
|
|
|
|
my ($self, $apply_fix, $dep_chain, $old, $next) = @_ ; |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# "ideal" dependency is always computed, but it does not always change |
|
233
|
|
|
|
|
|
|
my $new = $self->struct_to_dep(@$dep_chain); |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
if ( $logger->is_debug ) { |
|
236
|
|
|
|
|
|
|
my $new //= ''; |
|
237
|
|
|
|
|
|
|
$async_log->debug( "in on_check_all_done callback for ", |
|
238
|
|
|
|
|
|
|
$self->composite_name, " ($new) fix is $apply_fix" ) |
|
239
|
|
|
|
|
|
|
if $async_log->is_debug; |
|
240
|
|
|
|
|
|
|
no warnings 'uninitialized'; |
|
241
|
|
|
|
|
|
|
$logger->debug( "'$old' done" . ( $apply_fix ? " changed to '$new'" : '' ) ); |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
{ |
|
245
|
|
|
|
|
|
|
no warnings 'uninitialized'; |
|
246
|
|
|
|
|
|
|
$self->_store_fix( $old, $new ) if $apply_fix and $new ne $old; |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
$next->(); |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub check_debhelper_version { |
|
252
|
|
|
|
|
|
|
my ($self, $apply_fix, $depend) = @_ ; |
|
253
|
|
|
|
|
|
|
my ( $dep_name, $oper, $dep_v, @archs ) = @$depend ; |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
my $dep_string = $self->struct_to_dep($depend) ; |
|
256
|
|
|
|
|
|
|
my $lintian_dep = Lintian::Relation->new( $dep_string ) ; |
|
257
|
|
|
|
|
|
|
$logger->debug("checking '$dep_string' with lintian"); |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# using mode loose because debian-control model can be used alone |
|
260
|
|
|
|
|
|
|
# and compat is outside of debian-control |
|
261
|
|
|
|
|
|
|
my $compat = $self->grab_value(mode => 'loose', step => "!Dpkg compat") ; |
|
262
|
|
|
|
|
|
|
return unless defined $compat ; |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
my $min_dep = Lintian::Relation->new("debhelper ( >= $compat)") ; |
|
265
|
|
|
|
|
|
|
$logger->debug("checking if ".$lintian_dep->unparse." implies ". $min_dep->unparse); |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
return if $lintian_dep->implies ($min_dep) ; |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
$logger->debug("'$dep_string' does not imply debhelper >= $compat"); |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# $show_rel avoids undef warnings |
|
272
|
|
|
|
|
|
|
my $show_rel = join(' ', map { $_ || ''} ($oper, $dep_v)); |
|
273
|
|
|
|
|
|
|
if ($apply_fix) { |
|
274
|
|
|
|
|
|
|
@$depend = ( 'debhelper', '>=', $compat ) ; # notify_change called in check_value |
|
275
|
|
|
|
|
|
|
$logger->info("fixed debhelper dependency from " |
|
276
|
|
|
|
|
|
|
."$dep_name $show_rel -> ".$min_dep->unparse." (for compat $compat)"); |
|
277
|
|
|
|
|
|
|
} |
|
278
|
|
|
|
|
|
|
else { |
|
279
|
|
|
|
|
|
|
$self->{nb_of_fixes}++ ; |
|
280
|
|
|
|
|
|
|
my $msg = "should be (>= $compat) not ($show_rel) because compat is $compat" ; |
|
281
|
|
|
|
|
|
|
$self->add_warning( $msg ); |
|
282
|
|
|
|
|
|
|
$logger->info("will warn: $msg (fix++)"); |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
my @deb_releases = qw/etch lenny squeeze wheezy/; |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
my %deb_release_h ; |
|
289
|
|
|
|
|
|
|
while (@deb_releases) { |
|
290
|
|
|
|
|
|
|
my $k = pop @deb_releases ; |
|
291
|
|
|
|
|
|
|
my $regexp = join('|',@deb_releases,$k); |
|
292
|
|
|
|
|
|
|
$deb_release_h{$k} = qr/$regexp/; |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# called in check_versioned_dep and in Parse::RecDescent grammar |
|
296
|
|
|
|
|
|
|
sub xxget_pkg_versions { |
|
297
|
|
|
|
|
|
|
my ($self,$cb,$pkg) = @_ ; |
|
298
|
|
|
|
|
|
|
$logger->debug("get_pkg_versions: called with $pkg"); |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# check if Debian has version older than required version |
|
301
|
|
|
|
|
|
|
my ($has_info, @dist_version) = $self->get_available_version($pkg) ; |
|
302
|
|
|
|
|
|
|
# print "\t'$pkg' => '@dist_version',\n"; |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
return () unless $has_info ; |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
return @dist_version ; |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# |
|
310
|
|
|
|
|
|
|
# New subroutine "struct_to_dep" extracted - Mon Aug 27 13:45:02 2012. |
|
311
|
|
|
|
|
|
|
# |
|
312
|
|
|
|
|
|
|
sub struct_to_dep { |
|
313
|
|
|
|
|
|
|
my $self = shift ; |
|
314
|
|
|
|
|
|
|
my @input = @_ ; |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
my $skip = 0 ; |
|
317
|
|
|
|
|
|
|
my @alternatives ; |
|
318
|
|
|
|
|
|
|
foreach my $d (@input) { |
|
319
|
|
|
|
|
|
|
my $line = ''; |
|
320
|
|
|
|
|
|
|
# empty str or ref to empty array are skipped |
|
321
|
|
|
|
|
|
|
if( ref ($d) and @$d) { |
|
322
|
|
|
|
|
|
|
$line .= "$d->[0]"; |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# skip test for relations like << or < |
|
325
|
|
|
|
|
|
|
$skip ++ if defined $d->[1] and $d->[1] =~ / ; |
|
326
|
|
|
|
|
|
|
$line .= " ($d->[1] $d->[2])" if defined $d->[2]; |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
if (@$d > 3) { |
|
329
|
|
|
|
|
|
|
$line .= ' ['. join(' ',@$d[3..$#$d]) .']' ; |
|
330
|
|
|
|
|
|
|
} |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
elsif (not ref($d) and $d) { |
|
334
|
|
|
|
|
|
|
$line .= $d ; |
|
335
|
|
|
|
|
|
|
} ; |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
push @alternatives, $line if $line ; |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
my $actual_dep = @alternatives ? join (' | ',@alternatives) : undef ; |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
return wantarray ? ($actual_dep, $skip) : $actual_dep ; |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# @input contains the alternates dependencies (without '|') of one dependency values |
|
346
|
|
|
|
|
|
|
# a bit like @input = split /|/, $dependency |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# will modify @input (array of ref) when applying fix |
|
349
|
|
|
|
|
|
|
sub check_depend_chain { |
|
350
|
|
|
|
|
|
|
my ($self, $apply_fix, $input, $old) = @_ ; |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
my ($actual_dep, $skip) = $self->struct_to_dep (@$input); |
|
353
|
|
|
|
|
|
|
my $ret = 1 ; |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
return 1 unless defined $actual_dep; # may have been cleaned during fix |
|
356
|
|
|
|
|
|
|
$logger->debug("called with $actual_dep with apply_fix $apply_fix"); |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
if ($skip) { |
|
359
|
|
|
|
|
|
|
$logger->debug("skipping '$actual_dep': has a < relation ship") ; |
|
360
|
|
|
|
|
|
|
return $ret ; |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
$async_log->debug("begin check alternate deps for $actual_dep") ; |
|
364
|
|
|
|
|
|
|
foreach my $depend (@$input) { |
|
365
|
|
|
|
|
|
|
if (ref ($depend)) { |
|
366
|
|
|
|
|
|
|
# is a dependency (not a variable a la ${perl-Depends}) |
|
367
|
|
|
|
|
|
|
my ($dep_name, $oper, $dep_v) = @$depend ; |
|
368
|
|
|
|
|
|
|
$logger->debug("scanning dependency $dep_name" |
|
369
|
|
|
|
|
|
|
.(defined $dep_v ? " $dep_v" : '')); |
|
370
|
|
|
|
|
|
|
if ($dep_name =~ /lib([\w+\-]+)-perl/) { |
|
371
|
|
|
|
|
|
|
my $pname = $1 ; |
|
372
|
|
|
|
|
|
|
# AnyEvent condvar is involved in this method, blocks while inner async call are in progress |
|
373
|
|
|
|
|
|
|
$ret &&= $self->check_perl_lib_dep ($apply_fix, $pname, $actual_dep, $depend,$input); |
|
374
|
|
|
|
|
|
|
last; |
|
375
|
|
|
|
|
|
|
} |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
$async_log->debug("end check alternate deps for $actual_dep") ; |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
if ($logger->is_debug and $apply_fix) { |
|
381
|
|
|
|
|
|
|
my $str = $self->struct_to_dep(@$input) ; |
|
382
|
|
|
|
|
|
|
$str //= '' ; |
|
383
|
|
|
|
|
|
|
$logger->debug("new dependency is $str"); |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
return $ret ; |
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# called through check_depend_chain |
|
390
|
|
|
|
|
|
|
# does modify $input when applying fix |
|
391
|
|
|
|
|
|
|
sub check_perl_lib_dep { |
|
392
|
|
|
|
|
|
|
my ($self, $apply_fix, $pname, $actual_dep, $depend, $input) = @_; |
|
393
|
|
|
|
|
|
|
$logger->debug("called with $actual_dep with apply_fix $apply_fix"); |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
my ( $dep_name, $oper, $dep_v ) = @$depend; |
|
396
|
|
|
|
|
|
|
my $ret = 1; |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
$pname =~ s/-/::/g; |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# The dependency should be in the form perl (>= 5.10.1) | libtest-simple-perl (>= 0.88)". |
|
401
|
|
|
|
|
|
|
# cf http://pkg-perl.alioth.debian.org/policy.html#debian_control_handling |
|
402
|
|
|
|
|
|
|
# If the Perl version is not available in sid, the order of the dependency should be reversed |
|
403
|
|
|
|
|
|
|
# libcpan-meta-perl | perl (>= 5.13.10) |
|
404
|
|
|
|
|
|
|
# because buildd will use the first available alternative |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
# check for dual life module, module name follows debian convention... |
|
407
|
|
|
|
|
|
|
my @dep_name_as_perl = Module::CoreList->find_modules(qr/^$pname$/i) ; |
|
408
|
|
|
|
|
|
|
return $ret unless @dep_name_as_perl; |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
return $ret if defined $dep_v && $dep_v =~ m/^\$/ ; |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# here we have async consecutive calls to get_available_version, check_versioned_dep |
|
413
|
|
|
|
|
|
|
# and get_available_version. Must block and return once they are done |
|
414
|
|
|
|
|
|
|
# hence the condvar |
|
415
|
|
|
|
|
|
|
my $perl_dep_cv = AnyEvent->condvar ; |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
my @ideal_perl_dep = qw/perl/ ; |
|
418
|
|
|
|
|
|
|
my @ideal_lib_dep ; |
|
419
|
|
|
|
|
|
|
my @ideal_dep_chain = (\@ideal_perl_dep); |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
my ($on_get_lib_version, $on_perl_check_done, $check_perl_lib, $get_perl_versions, $on_get_perl_versions) ; |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
my ($v_normal) ; |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# check version for the first available version in Debian: debian |
|
426
|
|
|
|
|
|
|
# dep may have no version specified but older versions can be found |
|
427
|
|
|
|
|
|
|
# in CPAN that were never packaged in Debian |
|
428
|
|
|
|
|
|
|
$on_get_lib_version = sub { |
|
429
|
|
|
|
|
|
|
$async_log->debug("on_get_lib_version called with @_") ; |
|
430
|
|
|
|
|
|
|
# get_available_version returns oldest first, like (etch,1.2,...) |
|
431
|
|
|
|
|
|
|
my $oldest_lib_version_in_debian = $_[1] ; |
|
432
|
|
|
|
|
|
|
# lob off debian release number |
|
433
|
|
|
|
|
|
|
$oldest_lib_version_in_debian =~ s/-.*//; |
|
434
|
|
|
|
|
|
|
my $check_v = $dep_v || $oldest_lib_version_in_debian ; |
|
435
|
|
|
|
|
|
|
$logger->debug("dual life $dep_name has oldest debian $oldest_lib_version_in_debian, using $check_v"); |
|
436
|
|
|
|
|
|
|
my ($cpan_dep_v, $epoch_dep_v) ; |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
($cpan_dep_v, $epoch_dep_v) = reverse split /:/ ,$check_v if defined $check_v ; |
|
439
|
|
|
|
|
|
|
my $v_decimal = Module::CoreList->first_release( |
|
440
|
|
|
|
|
|
|
$dep_name_as_perl[0], |
|
441
|
|
|
|
|
|
|
version->parse( $cpan_dep_v ) |
|
442
|
|
|
|
|
|
|
); |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
if (defined $v_decimal) { |
|
445
|
|
|
|
|
|
|
$v_normal = version->new($v_decimal)->normal; |
|
446
|
|
|
|
|
|
|
$v_normal =~ s/^v//; # loose the v prefix |
|
447
|
|
|
|
|
|
|
if ( $logger->is_debug ) { |
|
448
|
|
|
|
|
|
|
my $dep_str = $dep_name . ( defined $check_v ? ' ' . $check_v : '' ); |
|
449
|
|
|
|
|
|
|
$logger->debug("dual life $dep_str aka $dep_name_as_perl[0] found in Perl core $v_normal"); |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
$self->check_versioned_dep( $on_perl_check_done , ['perl', '>=', $v_normal] ); |
|
452
|
|
|
|
|
|
|
} |
|
453
|
|
|
|
|
|
|
else { |
|
454
|
|
|
|
|
|
|
# no need to check further. Call send to unblock wait done with recv |
|
455
|
|
|
|
|
|
|
AnyEvent::postpone { $perl_dep_cv->send }; |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
}; |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
$on_perl_check_done = sub { |
|
461
|
|
|
|
|
|
|
my $has_older_perl = shift ; |
|
462
|
|
|
|
|
|
|
$async_log->debug("on_perl_check_done called") ; |
|
463
|
|
|
|
|
|
|
push @ideal_perl_dep, '>=', $v_normal if $has_older_perl; |
|
464
|
|
|
|
|
|
|
$check_perl_lib->($has_older_perl) ; |
|
465
|
|
|
|
|
|
|
} ; |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
$check_perl_lib = sub { |
|
468
|
|
|
|
|
|
|
my $has_older_perl = shift; |
|
469
|
|
|
|
|
|
|
$async_log->debug( "check_perl_lib called with dep_v " . ( $dep_v // 'undef' ) ); |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
my $on_perl_lib_check_done = sub { |
|
472
|
|
|
|
|
|
|
my $has_older_lib = shift; |
|
473
|
|
|
|
|
|
|
$async_log->debug("on_perl_lib_check_done called"); |
|
474
|
|
|
|
|
|
|
if ($has_older_perl) { |
|
475
|
|
|
|
|
|
|
push @ideal_lib_dep, $dep_name; |
|
476
|
|
|
|
|
|
|
push @ideal_lib_dep, '>=', $dep_v if $has_older_lib; |
|
477
|
|
|
|
|
|
|
} |
|
478
|
|
|
|
|
|
|
$get_perl_versions->(); |
|
479
|
|
|
|
|
|
|
}; |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
if ( defined $dep_v ) { |
|
482
|
|
|
|
|
|
|
$self->check_versioned_dep( $on_perl_lib_check_done, $depend ); |
|
483
|
|
|
|
|
|
|
} |
|
484
|
|
|
|
|
|
|
else { |
|
485
|
|
|
|
|
|
|
$on_perl_lib_check_done->(0); |
|
486
|
|
|
|
|
|
|
} |
|
487
|
|
|
|
|
|
|
}; |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
$get_perl_versions = sub { |
|
490
|
|
|
|
|
|
|
$self->get_available_version($on_get_perl_versions, 'perl'); |
|
491
|
|
|
|
|
|
|
} ; |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
$on_get_perl_versions = sub { |
|
494
|
|
|
|
|
|
|
my %perl_version = @_ ; |
|
495
|
|
|
|
|
|
|
$async_log->debug("running on_get_perl_versions for $actual_dep") ; |
|
496
|
|
|
|
|
|
|
my $has_older_perl_in_sid = ( $vs->compare( $v_normal, $perl_version{sid} ) < 0 ) ? 1 : 0; |
|
497
|
|
|
|
|
|
|
$logger->debug( |
|
498
|
|
|
|
|
|
|
"perl $v_normal is", |
|
499
|
|
|
|
|
|
|
$has_older_perl_in_sid ? ' ' : ' not ', |
|
500
|
|
|
|
|
|
|
"older than perl in sid ($perl_version{sid})" |
|
501
|
|
|
|
|
|
|
); |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
my @ordered_ideal_dep = $has_older_perl_in_sid ? |
|
504
|
|
|
|
|
|
|
( \@ideal_perl_dep, \@ideal_lib_dep ) : |
|
505
|
|
|
|
|
|
|
( \@ideal_lib_dep, \@ideal_perl_dep ) ; |
|
506
|
|
|
|
|
|
|
my $ideal_dep = $self->struct_to_dep( @ordered_ideal_dep ); |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
if ( $actual_dep ne $ideal_dep ) { |
|
509
|
|
|
|
|
|
|
if ($apply_fix) { |
|
510
|
|
|
|
|
|
|
@$input = @ordered_ideal_dep ; # notify_change called in check_value |
|
511
|
|
|
|
|
|
|
$logger->info("fixed dependency with: $ideal_dep, was @$depend"); |
|
512
|
|
|
|
|
|
|
} |
|
513
|
|
|
|
|
|
|
else { |
|
514
|
|
|
|
|
|
|
$self->{nb_of_fixes}++; |
|
515
|
|
|
|
|
|
|
my $msg = "Dependency of dual life package should be '$ideal_dep' not '$actual_dep'"; |
|
516
|
|
|
|
|
|
|
$self->add_warning ($msg); |
|
517
|
|
|
|
|
|
|
$logger->info("will warn: $msg (fix++)"); |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
$ret = 0; |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
$perl_dep_cv->send ; |
|
522
|
|
|
|
|
|
|
} ; |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
# start the whole async stuff |
|
525
|
|
|
|
|
|
|
$self->get_available_version($on_get_lib_version, $dep_name); |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
$async_log->debug("waiting for $actual_dep") ; |
|
529
|
|
|
|
|
|
|
$perl_dep_cv->recv ; |
|
530
|
|
|
|
|
|
|
$async_log->debug("waiting done for $actual_dep") ; |
|
531
|
|
|
|
|
|
|
return $ret ; |
|
532
|
|
|
|
|
|
|
} |
|
533
|
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub check_versioned_dep { |
|
535
|
|
|
|
|
|
|
my ($self, $callback ,$dep_info) = @_ ; |
|
536
|
|
|
|
|
|
|
my ( $pkg, $oper, $vers ) = @$dep_info; |
|
537
|
|
|
|
|
|
|
$logger->debug("called with '" . $self->struct_to_dep($dep_info) ."'") if $logger->is_debug; |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
# special case to keep lintian happy |
|
540
|
|
|
|
|
|
|
$callback->(1) if $pkg eq 'debhelper' ; |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
my $cb = sub { |
|
543
|
|
|
|
|
|
|
my @dist_version = @_ ; |
|
544
|
|
|
|
|
|
|
$async_log->debug("in check_versioned_dep callback with ". $self->struct_to_dep($dep_info) |
|
545
|
|
|
|
|
|
|
." -> @dist_version") if $async_log->is_debug; |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
if ( @dist_version # no older for unknow packages |
|
548
|
|
|
|
|
|
|
and defined $oper |
|
549
|
|
|
|
|
|
|
and $oper =~ />/ |
|
550
|
|
|
|
|
|
|
and $vers !~ /^\$/ # a dpkg variable |
|
551
|
|
|
|
|
|
|
) { |
|
552
|
|
|
|
|
|
|
my $src_pkg_name = $self->grab_value("!Dpkg::Control source Source") ; |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
my $filter = $test_filter || $self->grab_value( |
|
555
|
|
|
|
|
|
|
step => qq{!Dpkg my_config package-dependency-filter:"$src_pkg_name"}, |
|
556
|
|
|
|
|
|
|
mode => 'loose', |
|
557
|
|
|
|
|
|
|
) || ''; |
|
558
|
|
|
|
|
|
|
$callback->($self->has_older_version_than ($pkg, $vers, $filter, \@dist_version )); |
|
559
|
|
|
|
|
|
|
} |
|
560
|
|
|
|
|
|
|
else { |
|
561
|
|
|
|
|
|
|
$callback->(1) ; |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
}; |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
# check if Debian has version older than required version |
|
566
|
|
|
|
|
|
|
$self->get_available_version($cb, $pkg) ; |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
} |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
sub has_older_version_than { |
|
571
|
|
|
|
|
|
|
my ($self, $pkg, $vers, $filter, $dist_version ) = @_; |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
$logger->debug("using filter $filter") if $filter; |
|
574
|
|
|
|
|
|
|
my $regexp = $deb_release_h{$filter} ; |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
$logger->debug("using regexp $regexp") if defined $regexp; |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
my @list ; |
|
579
|
|
|
|
|
|
|
my $has_older = 0; |
|
580
|
|
|
|
|
|
|
while (@$dist_version) { |
|
581
|
|
|
|
|
|
|
my ($d,$v) = splice @$dist_version,0,2 ; |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
next if defined $regexp and $d =~ $regexp ; |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
push @list, "$d -> $v;" ; |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
if ($vs->compare($vers,$v) > 0 ) { |
|
588
|
|
|
|
|
|
|
$has_older = 1 ; |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
} |
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
$logger->debug("$pkg $vers has_older is $has_older (@list)"); |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
return 1 if $has_older ; |
|
595
|
|
|
|
|
|
|
return wantarray ? (0,@list) : 0 ; |
|
596
|
|
|
|
|
|
|
} |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
# |
|
599
|
|
|
|
|
|
|
# New subroutine "check_essential_package" extracted - Thu Aug 30 14:14:32 2012. |
|
600
|
|
|
|
|
|
|
# |
|
601
|
|
|
|
|
|
|
sub check_or_fix_essential_package { |
|
602
|
|
|
|
|
|
|
my ( $self, $apply_fix, $dep_info ) = @_; |
|
603
|
|
|
|
|
|
|
my ( $pkg, $oper, $vers ) = @$dep_info; |
|
604
|
|
|
|
|
|
|
$logger->debug("called with '", scalar $self->struct_to_dep($dep_info), "' and fix $apply_fix") if $logger->is_debug; |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
# Remove unversioned dependency on essential package (Debian bug 684208) |
|
607
|
|
|
|
|
|
|
# see /usr/share/doc/libapt-pkg-perl/examples/apt-cache |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
my $cache_item = $apt_cache->get($pkg); |
|
610
|
|
|
|
|
|
|
my $is_essential = 0; |
|
611
|
|
|
|
|
|
|
$is_essential++ if (defined $cache_item and $cache_item->get('Flags') =~ /essential/i); |
|
612
|
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
if ($is_essential and not defined $oper) { |
|
614
|
|
|
|
|
|
|
$logger->debug( "found unversioned dependency on essential package: $pkg"); |
|
615
|
|
|
|
|
|
|
if ($apply_fix) { |
|
616
|
|
|
|
|
|
|
@$dep_info = (); |
|
617
|
|
|
|
|
|
|
$logger->info("fix: removed unversioned essential dependency on $pkg"); |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
else { |
|
620
|
|
|
|
|
|
|
my $msg = "unnecessary unversioned dependency on essential package: $pkg"; |
|
621
|
|
|
|
|
|
|
$self->add_warning($msg); |
|
622
|
|
|
|
|
|
|
$self->{nb_of_fixes}++; |
|
623
|
|
|
|
|
|
|
$logger->info("will warn: $msg (fix++)"); |
|
624
|
|
|
|
|
|
|
} |
|
625
|
|
|
|
|
|
|
} |
|
626
|
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
my %pkg_replace = ( |
|
630
|
|
|
|
|
|
|
'perl-module' => 'perl' , |
|
631
|
|
|
|
|
|
|
) ; |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
sub check_or_fix_pkg_name { |
|
634
|
|
|
|
|
|
|
my ( $self, $apply_fix, $dep_info, $old, $next ) = @_; |
|
635
|
|
|
|
|
|
|
my ( $pkg, $oper, $vers ) = @$dep_info; |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
$logger->debug("called with '", scalar $self->struct_to_dep($dep_info), "' and fix $apply_fix") |
|
638
|
|
|
|
|
|
|
if $logger->is_debug; |
|
639
|
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
my $new = $pkg_replace{$pkg} ; |
|
641
|
|
|
|
|
|
|
if ( $new ) { |
|
642
|
|
|
|
|
|
|
if ($apply_fix) { |
|
643
|
|
|
|
|
|
|
$logger->info("fix: changed package name from $pkg to $new"); |
|
644
|
|
|
|
|
|
|
$dep_info->[0] = $pkg = $new; |
|
645
|
|
|
|
|
|
|
} |
|
646
|
|
|
|
|
|
|
else { |
|
647
|
|
|
|
|
|
|
my $msg = "dubious package name: $pkg. Preferred package is $new"; |
|
648
|
|
|
|
|
|
|
$self-> add_warning ($msg); |
|
649
|
|
|
|
|
|
|
$self->{nb_of_fixes}++; |
|
650
|
|
|
|
|
|
|
$logger->info("will warn: $msg (fix++)"); |
|
651
|
|
|
|
|
|
|
} |
|
652
|
|
|
|
|
|
|
} |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
# check if this package is defined in current control file |
|
655
|
|
|
|
|
|
|
if ($self->grab(step => "- - binary:$pkg", qw/mode loose autoadd 0/)) { |
|
656
|
|
|
|
|
|
|
$logger->debug("dependency $pkg provided in control file") ; |
|
657
|
|
|
|
|
|
|
$next->() ; |
|
658
|
|
|
|
|
|
|
} |
|
659
|
|
|
|
|
|
|
else { |
|
660
|
|
|
|
|
|
|
my $cb = sub { |
|
661
|
|
|
|
|
|
|
if ( @_ == 0 ) { |
|
662
|
|
|
|
|
|
|
# no version found for $pkg |
|
663
|
|
|
|
|
|
|
# don't know how to distinguish virtual package from source package |
|
664
|
|
|
|
|
|
|
$logger->debug("unknown package $pkg"); |
|
665
|
|
|
|
|
|
|
$self->add_warning( |
|
666
|
|
|
|
|
|
|
"package $pkg is unknown. Check for typos if not a virtual package."); |
|
667
|
|
|
|
|
|
|
} |
|
668
|
|
|
|
|
|
|
$async_log->debug("callback for check_or_fix_pkg_name -> end for $pkg"); |
|
669
|
|
|
|
|
|
|
$next->( ); |
|
670
|
|
|
|
|
|
|
}; |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# is asynchronous |
|
673
|
|
|
|
|
|
|
$async_log->debug("begin on $pkg"); |
|
674
|
|
|
|
|
|
|
$self->get_available_version( $cb, $pkg ); |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
# if no pkg was found |
|
677
|
|
|
|
|
|
|
} |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
# all subs but one there are synchronous |
|
681
|
|
|
|
|
|
|
sub check_or_fix_dep { |
|
682
|
|
|
|
|
|
|
my ( $self, $apply_fix, $dep_info, $old, $next ) = @_; |
|
683
|
|
|
|
|
|
|
my ( $pkg, $oper, $vers, @archs ) = @$dep_info; |
|
684
|
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
$logger->debug("called with '", scalar $self->struct_to_dep($dep_info), "' and fix $apply_fix") |
|
686
|
|
|
|
|
|
|
if $logger->is_debug; |
|
687
|
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
if(not defined $pkg) { |
|
689
|
|
|
|
|
|
|
# pkg may be cleaned up during fix |
|
690
|
|
|
|
|
|
|
$next->() ; |
|
691
|
|
|
|
|
|
|
} |
|
692
|
|
|
|
|
|
|
elsif ( $pkg eq 'debhelper' ) { |
|
693
|
|
|
|
|
|
|
$self->check_debhelper_version( $apply_fix, $dep_info ); |
|
694
|
|
|
|
|
|
|
$next->() ; |
|
695
|
|
|
|
|
|
|
} |
|
696
|
|
|
|
|
|
|
else { |
|
697
|
|
|
|
|
|
|
my $cb = sub { |
|
698
|
|
|
|
|
|
|
my ( $vers_dep_ok, @list ) = @_ ; |
|
699
|
|
|
|
|
|
|
$async_log->debug("callback for check_or_fix_dep with @_") ; |
|
700
|
|
|
|
|
|
|
$self->warn_or_remove_vers_dep ($apply_fix, $dep_info, \@list) unless $vers_dep_ok ; |
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
$async_log->debug("callback for check_or_fix_dep -> end") ; |
|
703
|
|
|
|
|
|
|
$next->() ; |
|
704
|
|
|
|
|
|
|
} ; |
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
$async_log->debug("begin") ; |
|
707
|
|
|
|
|
|
|
$self->check_versioned_dep($cb, $dep_info ); |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
} |
|
710
|
|
|
|
|
|
|
} |
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
sub warn_or_remove_vers_dep { |
|
713
|
|
|
|
|
|
|
my ( $self, $apply_fix, $dep_info, $list ) = @_; |
|
714
|
|
|
|
|
|
|
my ( $pkg, $oper, $vers ) = @$dep_info; |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
if ($apply_fix) { |
|
717
|
|
|
|
|
|
|
splice @$dep_info, 1, 2; # remove versioned dep, notify_change called in check_value |
|
718
|
|
|
|
|
|
|
$logger->info("fix: removed versioned dependency from @$dep_info -> $pkg"); |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
else { |
|
721
|
|
|
|
|
|
|
$self->{nb_of_fixes}++; |
|
722
|
|
|
|
|
|
|
my $msg = "unnecessary versioned dependency: @$dep_info. Debian has @$list"; |
|
723
|
|
|
|
|
|
|
$self->add_warning( $msg); |
|
724
|
|
|
|
|
|
|
$logger->info("will warn: $msg (fix++)"); |
|
725
|
|
|
|
|
|
|
} |
|
726
|
|
|
|
|
|
|
} |
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
use vars qw/%cache/ ; |
|
729
|
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
# Set up persistence |
|
731
|
|
|
|
|
|
|
my $cache_file_name = $ENV{HOME}.'/.config_model_depend_cache' ; |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
# this condition is used during tests |
|
734
|
|
|
|
|
|
|
if (not %cache) { |
|
735
|
|
|
|
|
|
|
tie %cache => 'DB_File', $cache_file_name, |
|
736
|
|
|
|
|
|
|
} |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
# required to write data back to DB_File |
|
739
|
|
|
|
|
|
|
END { |
|
740
|
|
|
|
|
|
|
untie %cache ; |
|
741
|
|
|
|
|
|
|
} |
|
742
|
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
my %requested ; |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
sub push_cb { |
|
746
|
|
|
|
|
|
|
my $pkg = shift; |
|
747
|
|
|
|
|
|
|
my $ref = $requested{$pkg} ||= [] ; |
|
748
|
|
|
|
|
|
|
push @$ref, @_ ; |
|
749
|
|
|
|
|
|
|
} |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
sub call_cbs { |
|
752
|
|
|
|
|
|
|
my $pkg = shift; |
|
753
|
|
|
|
|
|
|
return unless $requested{$pkg} ; |
|
754
|
|
|
|
|
|
|
my $ref = delete $requested{$pkg} ; |
|
755
|
|
|
|
|
|
|
map { $_->(@_) } @$ref ; |
|
756
|
|
|
|
|
|
|
} |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
# asynchronous method |
|
760
|
|
|
|
|
|
|
sub get_available_version { |
|
761
|
|
|
|
|
|
|
my ($self, $callback,$pkg_name) = @_ ; |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
$async_log->debug("called on $pkg_name"); |
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
my ($time,@res) = split / /, ($cache{$pkg_name} || ''); |
|
766
|
|
|
|
|
|
|
if (defined $time and $time =~ /^\d+$/ and $time + 24 * 60 * 60 * 7 > time) { |
|
767
|
|
|
|
|
|
|
$async_log->debug("using cached info for $pkg_name"); |
|
768
|
|
|
|
|
|
|
$callback->(@res) ; |
|
769
|
|
|
|
|
|
|
return; |
|
770
|
|
|
|
|
|
|
} |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# package info was requested but info is still not there |
|
773
|
|
|
|
|
|
|
# this may be called twice for the same package: one for source, one |
|
774
|
|
|
|
|
|
|
# for binary package |
|
775
|
|
|
|
|
|
|
if ($requested{$pkg_name}){ |
|
776
|
|
|
|
|
|
|
push_cb($pkg_name,$callback) ; |
|
777
|
|
|
|
|
|
|
return ; |
|
778
|
|
|
|
|
|
|
} ; |
|
779
|
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
my $url = "http://qa.debian.org/cgi-bin/madison.cgi?package=$pkg_name&text=on" ; |
|
781
|
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
push_cb($pkg_name,$callback); |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
say "Connecting to qa.debian.org to check $pkg_name versions. Please wait..." ; |
|
785
|
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
my $request; |
|
787
|
|
|
|
|
|
|
$request = http_request( |
|
788
|
|
|
|
|
|
|
GET => $url, |
|
789
|
|
|
|
|
|
|
timeout => 20, # seconds |
|
790
|
|
|
|
|
|
|
sub { |
|
791
|
|
|
|
|
|
|
my ($body, $hdr) = @_; |
|
792
|
|
|
|
|
|
|
$async_log->debug("callback of get_available_version called on $pkg_name"); |
|
793
|
|
|
|
|
|
|
if ($hdr->{Status} =~ /^2/) { |
|
794
|
|
|
|
|
|
|
my @res ; |
|
795
|
|
|
|
|
|
|
foreach my $line (split /\n/, $body) { |
|
796
|
|
|
|
|
|
|
my ($name,$available_v,$dist,$type) = split /\s*\|\s*/, $line ; |
|
797
|
|
|
|
|
|
|
$type =~ s/\s//g ; |
|
798
|
|
|
|
|
|
|
push @res , $dist, $available_v unless $type eq 'source'; |
|
799
|
|
|
|
|
|
|
} |
|
800
|
|
|
|
|
|
|
say "got info for $pkg_name" ; |
|
801
|
|
|
|
|
|
|
$cache{$pkg_name} = time ." @res" ; |
|
802
|
|
|
|
|
|
|
call_cbs($pkg_name,@res) ; |
|
803
|
|
|
|
|
|
|
} |
|
804
|
|
|
|
|
|
|
else { |
|
805
|
|
|
|
|
|
|
say "Error for $url: ($hdr->{Status}) $hdr->{Reason}"; |
|
806
|
|
|
|
|
|
|
delete $requested{$pkg_name} ; # trash the callbacks |
|
807
|
|
|
|
|
|
|
} |
|
808
|
|
|
|
|
|
|
undef $request; |
|
809
|
|
|
|
|
|
|
} |
|
810
|
|
|
|
|
|
|
); |
|
811
|
|
|
|
|
|
|
} |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
1; |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=head1 NAME |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
Config::Model::Dpkg::Dependency - Checks Debian dependency declarations |
|
820
|
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
822
|
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
use Config::Model ; |
|
824
|
|
|
|
|
|
|
use Log::Log4perl qw(:easy) ; |
|
825
|
|
|
|
|
|
|
use Data::Dumper ; |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
Log::Log4perl->easy_init($WARN); |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
# define configuration tree object |
|
830
|
|
|
|
|
|
|
my $model = Config::Model->new ; |
|
831
|
|
|
|
|
|
|
$model ->create_config_class ( |
|
832
|
|
|
|
|
|
|
name => "MyClass", |
|
833
|
|
|
|
|
|
|
element => [ |
|
834
|
|
|
|
|
|
|
Depends => { |
|
835
|
|
|
|
|
|
|
'type' => 'leaf', |
|
836
|
|
|
|
|
|
|
'value_type' => 'uniline', |
|
837
|
|
|
|
|
|
|
class => 'Config::Model::Dpkg::Dependency', |
|
838
|
|
|
|
|
|
|
}, |
|
839
|
|
|
|
|
|
|
], |
|
840
|
|
|
|
|
|
|
) ; |
|
841
|
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
my $inst = $model->instance(root_class_name => 'MyClass' ); |
|
843
|
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
my $root = $inst->config_root ; |
|
845
|
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
$root->load( 'Depends="libc6 ( >= 1.0 )"') ; |
|
847
|
|
|
|
|
|
|
# Connecting to qa.debian.org to check libc6 versions. Please wait ... |
|
848
|
|
|
|
|
|
|
# Warning in 'Depends' value 'libc6 ( >= 1.0 )': unnecessary |
|
849
|
|
|
|
|
|
|
# versioned dependency: >= 1.0. Debian has lenny-security -> |
|
850
|
|
|
|
|
|
|
# 2.7-18lenny6; lenny -> 2.7-18lenny7; squeeze-security -> |
|
851
|
|
|
|
|
|
|
# 2.11.2-6+squeeze1; squeeze -> 2.11.2-10; wheezy -> 2.11.2-10; sid |
|
852
|
|
|
|
|
|
|
# -> 2.11.2-10; sid -> 2.11.2-11; |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
855
|
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
This class is derived from L. Its purpose is to |
|
857
|
|
|
|
|
|
|
check the value of a Debian package dependency for the following: |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
=over |
|
860
|
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
=item * |
|
862
|
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
syntax as described in http://www.debian.org/doc/debian-policy/ch-relationships.html |
|
864
|
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
=item * |
|
866
|
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
Whether the version specified with C<< > >> or C<< >= >> is necessary. |
|
868
|
|
|
|
|
|
|
This module will check with Debian server whether older versions can be |
|
869
|
|
|
|
|
|
|
found in Debian old-stable or not. If no older version can be found, a |
|
870
|
|
|
|
|
|
|
warning will be issued. Note a warning will also be sent if the package |
|
871
|
|
|
|
|
|
|
is not found on madison and if the package is not virtual. |
|
872
|
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=item * |
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
Whether a Perl library is dual life. In this case the dependency is checked according to |
|
876
|
|
|
|
|
|
|
L. |
|
877
|
|
|
|
|
|
|
Because Debian auto-build systems (buildd) will use the first available alternative, |
|
878
|
|
|
|
|
|
|
the dependency should be in the form : |
|
879
|
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
=over |
|
881
|
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
=item * |
|
883
|
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
C<< perl (>= 5.10.1) | libtest-simple-perl (>= 0.88) >> when |
|
885
|
|
|
|
|
|
|
the required perl version is available in sid. ". |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
=item * |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
C<< libcpan-meta-perl | perl (>= 5.13.10) >> when the Perl version is not available in sid |
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
=back |
|
892
|
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
=back |
|
894
|
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
=head1 Cache |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
Queries to Debian server are cached in C<~/.config_model_depend_cache> |
|
898
|
|
|
|
|
|
|
for about one month. |
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=head1 BUGS |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=over |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=item * |
|
905
|
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
Virtual package names are found scanning local apt cache. Hence an unknown package |
|
907
|
|
|
|
|
|
|
on your system may a virtual package on another system. |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=item * |
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
More advanced checks can probably be implemented. The author is open to |
|
912
|
|
|
|
|
|
|
new ideas. He's even more open to patches (with tests). |
|
913
|
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=back |
|
915
|
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=head1 AUTHOR |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
Dominique Dumont, ddumont [AT] cpan [DOT] org |
|
919
|
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
921
|
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
L, |
|
923
|
|
|
|
|
|
|
L, |
|
924
|
|
|
|
|
|
|
L, |
|
925
|
|
|
|
|
|
|
L |