line |
stmt |
code |
1
|
|
#!/usr/bin/env perl |
2
|
|
# Copyright 2020 SUSE LLC |
3
|
|
# SPDX-License-Identifier: MIT |
4
|
1
|
use strict; |
|
1
|
|
|
1
|
|
5
|
1
|
use warnings; |
|
1
|
|
|
1
|
|
6
|
1
|
use 5.010; |
|
1
|
|
7
|
|
|
8
|
1
|
use YAML::PP; |
|
1
|
|
|
1
|
|
9
|
1
|
use Data::Dumper; |
|
1
|
|
|
1
|
|
10
|
1
|
use Mojo::File qw(path); |
|
1
|
|
|
1
|
|
11
|
1
|
use Getopt::Long; |
|
1
|
|
|
1
|
|
12
|
1
|
use FindBin qw($Bin); |
|
1
|
|
|
1
|
|
13
|
|
|
14
|
1
|
GetOptions( |
15
|
|
"help|h" => \my $help, |
16
|
|
"specfile=s" => \my $specfile, |
17
|
|
"dockerfile=s" => \my $dockerfile, |
18
|
|
); |
19
|
|
|
20
|
1
|
usage(0) if $help; |
21
|
1
|
usage(1) unless $specfile; |
22
|
|
|
23
|
1
|
my $scriptname = path(__FILE__)->to_rel("$Bin/.."); |
24
|
1
|
my $yamlfile = "dependencies.yaml"; |
25
|
1
|
my $file = "$Bin/../$yamlfile"; |
26
|
1
|
my $cpanfile = "$Bin/../cpanfile"; |
27
|
|
|
28
|
1
|
my $data = YAML::PP->new->load_file($file); |
29
|
1
|
my $spec = path($specfile)->slurp; |
30
|
|
|
31
|
1
|
my $spectargets = $data->{targets}->{spec}; |
32
|
1
|
my $cpantargets = $data->{targets}->{cpanfile}; |
33
|
1
|
my $dockertargets = $data->{targets}->{docker}; |
34
|
1
|
my $cpantarget_mapping = $data->{targets}->{'cpanfile-targets'}; |
35
|
|
|
36
|
1
|
my ($modules_by_target) = get_modules($data, $cpantargets, $cpantarget_mapping); |
37
|
|
|
38
|
1
|
update_spec(); |
39
|
1
|
update_cpanfile($modules_by_target); |
40
|
1
|
update_dockerfile($dockerfile) if $dockerfile; |
41
|
|
|
42
|
|
my ($dockerfile) = @_; |
43
|
1
|
my $docker = path($dockerfile)->slurp; |
44
|
1
|
my @perl; |
45
|
1
|
my @pkg; |
46
|
|
for my $target (@$dockertargets) { |
47
|
1
|
my $name = $target . '_requires'; |
48
|
11
|
my $deps = $data->{$name}; |
49
|
11
|
for my $key (sort keys %$deps) { |
50
|
11
|
next if $key =~ m/^%/; |
51
|
130
|
my $line = ' '; |
52
|
121
|
|
53
|
|
if ($key =~ m/\(/) { |
54
|
121
|
$key = "'$key'"; |
55
|
97
|
} |
56
|
|
$line .= $key; |
57
|
121
|
$line .= " \\\n"; |
58
|
121
|
if ($key =~ m/perl\(/) { |
59
|
121
|
push @perl, $line; |
60
|
92
|
} |
61
|
|
else { |
62
|
|
push @pkg, $line; |
63
|
29
|
} |
64
|
|
} |
65
|
|
} |
66
|
|
@perl = sort @perl; |
67
|
1
|
@pkg = sort @pkg; |
68
|
1
|
my %seen; |
69
|
1
|
my $dep = join '', grep { not $seen{$_}++ } @pkg, @perl; |
70
|
1
|
my $begin = '# AUTODEPS START'; |
|
121
|
|
71
|
1
|
my $end = '# AUTODEPS END'; |
72
|
1
|
my $run = <<"EOM"; |
73
|
1
|
# This part is autogenerated by $scriptname from $yamlfile |
74
|
|
# hadolint ignore=DL3034,DL3037 |
75
|
|
RUN zypper in -y -C \\ |
76
|
|
$dep && zypper clean |
77
|
|
EOM |
78
|
|
$docker =~ s/($begin\n)(.*)($end\n)/$1$run$3/s; |
79
|
1
|
path($dockerfile)->spurt($docker); |
80
|
1
|
say "Updated $dockerfile"; |
81
|
1
|
} |
82
|
|
|
83
|
|
|
84
|
|
for my $target (@$spectargets) { |
85
|
|
my $name = $target . '_requires'; |
86
|
1
|
my $deps = $data->{$name}; |
87
|
10
|
my $prefix = "%define $name"; |
88
|
10
|
my $specline = $prefix; |
89
|
10
|
for my $key (sort keys %$deps) { |
90
|
10
|
my $version = $deps->{$key}; |
91
|
10
|
if (ref $version) { |
92
|
124
|
$version = $version->{rpm}; |
93
|
124
|
} |
94
|
0
|
$specline .= " $key"; |
95
|
|
if ($key eq 'perl(Perl::Tidy)') { |
96
|
124
|
undef $version; |
97
|
124
|
} |
98
|
1
|
if ($version) { |
99
|
|
$specline .= " $version"; |
100
|
124
|
} |
101
|
5
|
} |
102
|
|
my $comment = "# The following line is generated from $yamlfile"; |
103
|
|
if ($spec =~ s/^# .*generated.*\n^$prefix.*/$comment\n$specline/m) { |
104
|
10
|
next; |
105
|
10
|
} |
106
|
10
|
# No comment above the line yet |
107
|
|
unless ($spec =~ s/^$prefix.*/$comment\n$specline/m) { |
108
|
|
die "/^$prefix/ not found in $specfile"; |
109
|
0
|
} |
110
|
0
|
} |
111
|
|
|
112
|
|
path($specfile)->spurt($spec); |
113
|
|
say "Updated $specfile"; |
114
|
1
|
} |
115
|
1
|
|
116
|
|
my ($data, $cpantargets, $cpantarget_mapping) = @_; |
117
|
|
|
118
|
|
my %modules_by_target; |
119
|
1
|
for my $target (@$cpantargets) { |
120
|
|
my $name = $target . '_requires'; |
121
|
1
|
my $deps = $data->{$name}; |
122
|
1
|
for my $key (keys %$deps) { |
123
|
7
|
my $module = $key; |
124
|
7
|
next unless $module =~ s/^perl\((.*)\)$/$1/; |
125
|
7
|
my $version = $deps->{$key}; |
126
|
114
|
if (ref $version) { |
127
|
114
|
$version = $version->{perl}; |
128
|
93
|
} |
129
|
93
|
my $cpantarget = $cpantarget_mapping->{$target} || 'main'; |
130
|
0
|
$modules_by_target{$cpantarget}->{$module} = $version; |
131
|
|
} |
132
|
93
|
} |
133
|
93
|
return \%modules_by_target; |
134
|
|
} |
135
|
|
|
136
|
1
|
# requires 'Archive::Extract', '> 0.7'; |
137
|
|
my ($hash, $module) = @_; |
138
|
|
my $version = $hash->{$module}; |
139
|
|
my $line = "requires '$module'"; |
140
|
|
$line .= qq{, '$version'} if $version; |
141
|
93
|
$line .= ";\n"; |
142
|
93
|
return $line; |
143
|
93
|
} |
144
|
93
|
|
145
|
93
|
my ($modules_by_target) = @_; |
146
|
93
|
my $cpan = <<"EOM"; |
147
|
|
################################################## |
148
|
|
# WARNING |
149
|
|
# This file is autogenerated by $scriptname |
150
|
1
|
# from $yamlfile |
151
|
1
|
################################################## |
152
|
|
|
153
|
|
EOM |
154
|
|
for my $module (sort keys %{$modules_by_target->{main}}) { |
155
|
|
$cpan .= _requires_line($modules_by_target->{main}, $module); |
156
|
|
} |
157
|
|
my $test_requires = ''; |
158
|
|
for my $module (sort keys %{$modules_by_target->{test}}) { |
159
|
1
|
$test_requires .= ' ' . _requires_line($modules_by_target->{test}, $module); |
|
1
|
|
160
|
64
|
} |
161
|
|
my $cover_requires = ''; |
162
|
1
|
for my $module (sort keys %{$modules_by_target->{cover}}) { |
163
|
1
|
$cover_requires .= ' ' . _requires_line($modules_by_target->{cover}, $module); |
|
1
|
|
164
|
22
|
} |
165
|
|
my $devel_requires = ''; |
166
|
1
|
for my $module (sort keys %{$modules_by_target->{devel}}) { |
167
|
1
|
$devel_requires .= ' ' . _requires_line($modules_by_target->{devel}, $module); |
|
1
|
|
168
|
2
|
} |
169
|
|
$cpan .= <<"EOM"; |
170
|
1
|
|
171
|
1
|
on 'test' => sub { |
|
1
|
|
172
|
5
|
$test_requires |
173
|
|
}; |
174
|
1
|
|
175
|
|
on 'devel' => sub { |
176
|
|
$devel_requires |
177
|
|
}; |
178
|
|
|
179
|
|
feature 'coverage', 'coverage for CI' => sub { |
180
|
|
$cover_requires |
181
|
|
}; |
182
|
|
EOM |
183
|
|
|
184
|
|
path($cpanfile)->spurt($cpan); |
185
|
|
say "Updated $cpanfile"; |
186
|
|
} |
187
|
|
|
188
|
|
my ($exit) = @_; |
189
|
1
|
print <<"EOM"; |
190
|
1
|
Usage: |
191
|
|
# update cpanfile and dist/rpm/os-autoinst.spec |
192
|
|
$0 |
193
|
|
$0 --specfile dist/rpm/os-autoinst.spec |
194
|
0
|
$0 --dockerfile docker/ci/Dockerfile |
195
|
0
|
EOM |
196
|
|
exit $exit; |
197
|
|
} |