| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package App::GHGen::PerlCustomizer; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
13
|
use v5.36; |
|
|
1
|
|
|
|
|
6
|
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
26
|
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
49
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
1094
|
use Path::Tiny; |
|
|
1
|
|
|
|
|
18027
|
|
|
|
1
|
|
|
|
|
90
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
11
|
use Exporter 'import'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1996
|
|
|
10
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
|
11
|
|
|
|
|
|
|
detect_perl_requirements |
|
12
|
|
|
|
|
|
|
generate_custom_perl_workflow |
|
13
|
|
|
|
|
|
|
); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = '0.05'; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
App::GHGen::PerlCustomizer - Customize Perl workflows based on project requirements |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use App::GHGen::PerlCustomizer qw(detect_perl_requirements); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $requirements = detect_perl_requirements(); |
|
26
|
|
|
|
|
|
|
# Returns: { min_version => '5.036', has_cpanfile => 1, ... } |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head2 detect_perl_requirements() |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Detect Perl version requirements from cpanfile, Makefile.PL, or dist.ini. |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=cut |
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
|
|
1
|
1
|
2
|
sub detect_perl_requirements() { |
|
|
1
|
|
|
|
|
2
|
|
|
37
|
1
|
|
|
|
|
7
|
my %reqs = ( |
|
38
|
|
|
|
|
|
|
min_version => undef, |
|
39
|
|
|
|
|
|
|
has_cpanfile => 0, |
|
40
|
|
|
|
|
|
|
has_makefile_pl => 0, |
|
41
|
|
|
|
|
|
|
has_dist_ini => 0, |
|
42
|
|
|
|
|
|
|
has_build_pl => 0, |
|
43
|
|
|
|
|
|
|
); |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# Check for dependency files |
|
46
|
1
|
|
|
|
|
5
|
$reqs{has_cpanfile} = path('cpanfile')->exists; |
|
47
|
1
|
|
|
|
|
136
|
$reqs{has_makefile_pl} = path('Makefile.PL')->exists; |
|
48
|
1
|
|
|
|
|
57
|
$reqs{has_dist_ini} = path('dist.ini')->exists; |
|
49
|
1
|
|
|
|
|
107
|
$reqs{has_build_pl} = path('Build.PL')->exists; |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Try to detect minimum Perl version |
|
52
|
1
|
50
|
|
|
|
52
|
if ($reqs{has_cpanfile}) { |
|
53
|
1
|
|
|
|
|
9
|
my $content = path('cpanfile')->slurp_utf8; |
|
54
|
1
|
50
|
|
|
|
2025
|
if ($content =~ /requires\s+['"]perl['"],?\s+['"]([0-9.]+)['"]/) { |
|
55
|
1
|
|
|
|
|
15
|
$reqs{min_version} = $1; |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
1
|
0
|
33
|
|
|
5
|
if (!$reqs{min_version} && $reqs{has_makefile_pl}) { |
|
60
|
0
|
|
|
|
|
0
|
my $content = path('Makefile.PL')->slurp_utf8; |
|
61
|
0
|
0
|
|
|
|
0
|
if ($content =~ /MIN_PERL_VERSION\s*=>\s*['"]([0-9.]+)['"]/) { |
|
62
|
0
|
|
|
|
|
0
|
$reqs{min_version} = $1; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
1
|
|
|
|
|
4
|
return \%reqs; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head2 generate_custom_perl_workflow($options) |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Generate a customized Perl workflow based on options hash. |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Options: |
|
74
|
|
|
|
|
|
|
- perl_versions: Array ref of explicit Perl versions (e.g., ['5.40', '5.38']) |
|
75
|
|
|
|
|
|
|
- min_perl_version: Minimum Perl version (e.g., '5.036') |
|
76
|
|
|
|
|
|
|
- max_perl_version: Maximum Perl version to test (e.g., '5.40') |
|
77
|
|
|
|
|
|
|
- os: Array ref of operating systems ['ubuntu', 'macos', 'windows'] |
|
78
|
|
|
|
|
|
|
- enable_critic: Boolean |
|
79
|
|
|
|
|
|
|
- enable_coverage: Boolean |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
If perl_versions is provided, it takes precedence over min/max versions. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=cut |
|
84
|
|
|
|
|
|
|
|
|
85
|
1
|
|
|
1
|
1
|
3
|
sub generate_custom_perl_workflow($opts = {}) { |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
31
|
|
|
86
|
1
|
|
50
|
|
|
5
|
my $min_version = $opts->{min_perl_version} // '5.36'; |
|
87
|
1
|
|
50
|
|
|
3
|
my $max_version = $opts->{max_perl_version} // '5.40'; |
|
88
|
1
|
|
50
|
|
|
5
|
my $timeout = $opts->{timeout} // 30; |
|
89
|
1
|
|
50
|
|
|
2
|
my @os = @{$opts->{os} // ['ubuntu-latest', 'macos-latest', 'windows-latest']}; |
|
|
1
|
|
|
|
|
6
|
|
|
90
|
1
|
|
50
|
|
|
3
|
my $enable_critic = $opts->{enable_critic} // 1; |
|
91
|
1
|
|
50
|
|
|
6
|
my $enable_coverage = $opts->{enable_coverage} // 1; |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Generate Perl version list - use explicit list if provided, otherwise min/max |
|
94
|
1
|
|
|
|
|
3
|
my @perl_versions; |
|
95
|
1
|
50
|
33
|
|
|
6
|
if ($opts->{perl_versions} && @{$opts->{perl_versions}}) { |
|
|
0
|
|
|
|
|
0
|
|
|
96
|
0
|
|
|
|
|
0
|
@perl_versions = @{$opts->{perl_versions}}; |
|
|
0
|
|
|
|
|
0
|
|
|
97
|
|
|
|
|
|
|
} else { |
|
98
|
1
|
|
|
|
|
19
|
@perl_versions = _get_perl_versions($min_version, $max_version); |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
1
|
|
|
|
|
4
|
my $yaml = "---\n"; |
|
102
|
1
|
|
|
|
|
3
|
$yaml .= '# Created by ' . __PACKAGE__ . "\n"; |
|
103
|
|
|
|
|
|
|
|
|
104
|
1
|
|
|
|
|
2
|
$yaml .= "name: Perl CI\n\n"; |
|
105
|
1
|
|
|
|
|
3
|
$yaml .= "'on':\n"; |
|
106
|
1
|
|
|
|
|
13
|
$yaml .= " push:\n"; |
|
107
|
1
|
|
|
|
|
3
|
$yaml .= " branches:\n"; |
|
108
|
1
|
|
|
|
|
1
|
$yaml .= " - main\n"; |
|
109
|
1
|
|
|
|
|
3
|
$yaml .= " - master\n"; |
|
110
|
1
|
|
|
|
|
3
|
$yaml .= " pull_request:\n"; |
|
111
|
1
|
|
|
|
|
3
|
$yaml .= " branches:\n"; |
|
112
|
1
|
|
|
|
|
28
|
$yaml .= " - main\n"; |
|
113
|
1
|
|
|
|
|
3
|
$yaml .= " - master\n\n"; |
|
114
|
|
|
|
|
|
|
|
|
115
|
1
|
|
|
|
|
2
|
$yaml .= "concurrency:\n"; |
|
116
|
1
|
|
|
|
|
3
|
$yaml .= " group: \${{ github.workflow }}-\${{ github.ref }}\n"; |
|
117
|
1
|
|
|
|
|
2
|
$yaml .= " cancel-in-progress: true\n\n"; |
|
118
|
|
|
|
|
|
|
|
|
119
|
1
|
|
|
|
|
2
|
$yaml .= "permissions:\n"; |
|
120
|
1
|
|
|
|
|
2
|
$yaml .= " contents: read\n\n"; |
|
121
|
|
|
|
|
|
|
|
|
122
|
1
|
|
|
|
|
2
|
$yaml .= "jobs:\n"; |
|
123
|
1
|
|
|
|
|
2
|
$yaml .= " test:\n"; |
|
124
|
1
|
|
|
|
|
2
|
$yaml .= " runs-on: \${{ matrix.os }}\n"; |
|
125
|
1
|
|
|
|
|
3
|
$yaml .= " timeout-minutes: $timeout\n"; |
|
126
|
1
|
|
|
|
|
2
|
$yaml .= " strategy:\n"; |
|
127
|
1
|
|
|
|
|
2
|
$yaml .= " fail-fast: false\n"; |
|
128
|
1
|
|
|
|
|
3
|
$yaml .= " matrix:\n"; |
|
129
|
1
|
|
|
|
|
2
|
$yaml .= " os:\n"; |
|
130
|
1
|
|
|
|
|
3
|
for my $os (@os) { |
|
131
|
3
|
|
|
|
|
6
|
$yaml .= " - $os\n"; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
1
|
|
|
|
|
2
|
$yaml .= " perl:\n"; |
|
134
|
1
|
|
|
|
|
2
|
for my $version (@perl_versions) { |
|
135
|
3
|
|
|
|
|
7
|
$yaml .= " - '$version'\n"; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
1
|
|
|
|
|
3
|
$yaml .= " name: Perl \${{ matrix.perl }} on \${{ matrix.os }}\n"; |
|
138
|
1
|
|
|
|
|
2
|
$yaml .= " env:\n"; |
|
139
|
1
|
|
|
|
|
2
|
$yaml .= " AUTOMATED_TESTING: 1\n"; |
|
140
|
1
|
|
|
|
|
2
|
$yaml .= " NO_NETWORK_TESTING: 1\n"; |
|
141
|
1
|
|
|
|
|
3
|
$yaml .= " NONINTERACTIVE_TESTING: 1\n"; |
|
142
|
1
|
|
|
|
|
2
|
$yaml .= " steps:\n"; |
|
143
|
1
|
|
|
|
|
10
|
$yaml .= " - uses: actions/checkout\@v6\n\n"; |
|
144
|
|
|
|
|
|
|
|
|
145
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Setup Perl\n"; |
|
146
|
1
|
|
|
|
|
7
|
$yaml .= " uses: shogo82148/actions-setup-perl\@v1\n"; |
|
147
|
1
|
|
|
|
|
3
|
$yaml .= " with:\n"; |
|
148
|
1
|
|
|
|
|
1
|
$yaml .= " perl-version: \${{ matrix.perl }}\n\n"; |
|
149
|
|
|
|
|
|
|
|
|
150
|
1
|
|
|
|
|
3
|
$yaml .= " - name: Cache CPAN modules\n"; |
|
151
|
1
|
|
|
|
|
2
|
$yaml .= " uses: actions/cache\@v5\n"; |
|
152
|
1
|
|
|
|
|
2
|
$yaml .= " with:\n"; |
|
153
|
1
|
|
|
|
|
3
|
$yaml .= " path: ~/perl5\n"; |
|
154
|
1
|
|
|
|
|
2
|
$yaml .= " key: \${{ runner.os }}-\${{ matrix.perl }}-\${{ hashFiles('cpanfile') }}\n"; |
|
155
|
1
|
|
|
|
|
2
|
$yaml .= " restore-keys: |\n"; |
|
156
|
1
|
|
|
|
|
2
|
$yaml .= " \${{ runner.os }}-\${{ matrix.perl }}-\n\n"; |
|
157
|
|
|
|
|
|
|
|
|
158
|
1
|
|
|
|
|
15
|
$yaml .= " - name: Install cpanm and local::lib\n"; |
|
159
|
1
|
|
|
|
|
3
|
$yaml .= " if: runner.os != 'Windows'\n"; |
|
160
|
1
|
|
|
|
|
2
|
$yaml .= " run: cpanm --notest --local-lib=~/perl5 local::lib\n\n"; |
|
161
|
|
|
|
|
|
|
|
|
162
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Install cpanm and local::lib (Windows)\n"; |
|
163
|
1
|
|
|
|
|
10
|
$yaml .= " if: runner.os == 'Windows'\n"; |
|
164
|
1
|
|
|
|
|
2
|
$yaml .= " run: cpanm --notest App::cpanminus local::lib\n\n"; |
|
165
|
|
|
|
|
|
|
|
|
166
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Install dependencies\n"; |
|
167
|
1
|
|
|
|
|
2
|
$yaml .= " if: runner.os != 'Windows'\n"; |
|
168
|
1
|
|
|
|
|
2
|
$yaml .= " shell: bash\n"; |
|
169
|
1
|
|
|
|
|
2
|
$yaml .= " run: |\n"; |
|
170
|
1
|
|
|
|
|
9
|
$yaml .= " eval \$(perl -I ~/perl5/lib/perl5 -Mlocal::lib)\n"; |
|
171
|
1
|
|
|
|
|
3
|
$yaml .= " cpanm --notest --installdeps .\n\n"; |
|
172
|
|
|
|
|
|
|
|
|
173
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Install dependencies (Windows)\n"; |
|
174
|
1
|
|
|
|
|
2
|
$yaml .= " if: runner.os == 'Windows'\n"; |
|
175
|
1
|
|
|
|
|
1
|
$yaml .= " shell: cmd\n"; |
|
176
|
1
|
|
|
|
|
2
|
$yaml .= " run: |\n"; |
|
177
|
1
|
|
|
|
|
2
|
$yaml .= " \@echo off\n"; |
|
178
|
1
|
|
|
|
|
2
|
$yaml .= " set \"PATH=%USERPROFILE%\\perl5\\bin;%PATH%\"\n"; |
|
179
|
1
|
|
|
|
|
3
|
$yaml .= " set \"PERL5LIB=%USERPROFILE%\\perl5\\lib\\perl5\"\n"; |
|
180
|
1
|
|
|
|
|
1
|
$yaml .= " cpanm --notest --installdeps .\n\n"; |
|
181
|
|
|
|
|
|
|
|
|
182
|
1
|
|
|
|
|
3
|
$yaml .= " - name: Run tests\n"; |
|
183
|
1
|
|
|
|
|
2
|
$yaml .= " if: runner.os != 'Windows'\n"; |
|
184
|
1
|
|
|
|
|
1
|
$yaml .= " shell: bash\n"; |
|
185
|
1
|
|
|
|
|
2
|
$yaml .= " run: |\n"; |
|
186
|
1
|
|
|
|
|
2
|
$yaml .= " eval \$(perl -I ~/perl5/lib/perl5 -Mlocal::lib)\n"; |
|
187
|
1
|
|
|
|
|
2
|
$yaml .= " prove -lr t/\n\n"; |
|
188
|
|
|
|
|
|
|
|
|
189
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Run tests (Windows)\n"; |
|
190
|
1
|
|
|
|
|
2
|
$yaml .= " if: runner.os == 'Windows'\n"; |
|
191
|
1
|
|
|
|
|
2
|
$yaml .= " shell: cmd\n"; |
|
192
|
1
|
|
|
|
|
2
|
$yaml .= " run: |\n"; |
|
193
|
1
|
|
|
|
|
2
|
$yaml .= " \@echo off\n"; |
|
194
|
1
|
|
|
|
|
1
|
$yaml .= " set \"PATH=%USERPROFILE%\\perl5\\bin;%PATH%\"\n"; |
|
195
|
1
|
|
|
|
|
3
|
$yaml .= " set \"PERL5LIB=%USERPROFILE%\\perl5\\lib\\perl5\"\n"; |
|
196
|
1
|
|
|
|
|
1
|
$yaml .= " prove -lr t/\n\n"; |
|
197
|
|
|
|
|
|
|
|
|
198
|
1
|
50
|
|
|
|
4
|
if ($enable_critic) { |
|
199
|
1
|
|
|
|
|
3
|
my $latest = $perl_versions[-1]; |
|
200
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Run Perl::Critic\n"; |
|
201
|
1
|
|
|
|
|
8
|
$yaml .= " if: matrix.perl == '$latest' && matrix.os == 'ubuntu-latest'\n"; |
|
202
|
1
|
|
|
|
|
3
|
$yaml .= " continue-on-error: true\n"; |
|
203
|
1
|
|
|
|
|
2
|
$yaml .= " run: |\n"; |
|
204
|
1
|
|
|
|
|
1
|
$yaml .= " eval \$(perl -I ~/perl5/lib/perl5 -Mlocal::lib)\n"; |
|
205
|
1
|
|
|
|
|
3
|
$yaml .= " cpanm --notest Perl::Critic\n"; |
|
206
|
1
|
|
|
|
|
1
|
$yaml .= " perlcritic --severity 3 lib/ || true\n"; |
|
207
|
1
|
|
|
|
|
3
|
$yaml .= " shell: bash\n\n"; |
|
208
|
|
|
|
|
|
|
} |
|
209
|
|
|
|
|
|
|
|
|
210
|
1
|
50
|
|
|
|
3
|
if ($enable_coverage) { |
|
211
|
1
|
|
|
|
|
3
|
my $latest = $perl_versions[-1]; |
|
212
|
1
|
|
|
|
|
2
|
$yaml .= " - name: Test coverage\n"; |
|
213
|
1
|
|
|
|
|
2
|
$yaml .= " if: matrix.perl == '$latest' && matrix.os == 'ubuntu-latest'\n"; |
|
214
|
1
|
|
|
|
|
3
|
$yaml .= " run: |\n"; |
|
215
|
1
|
|
|
|
|
2
|
$yaml .= " eval \$(perl -I ~/perl5/lib/perl5 -Mlocal::lib)\n"; |
|
216
|
1
|
|
|
|
|
2
|
$yaml .= " cpanm --notest Devel::Cover\n"; |
|
217
|
1
|
|
|
|
|
2
|
$yaml .= " cover -delete\n"; |
|
218
|
1
|
|
|
|
|
1
|
$yaml .= " HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr t/\n"; |
|
219
|
1
|
|
|
|
|
2
|
$yaml .= " cover\n"; |
|
220
|
1
|
|
|
|
|
2
|
$yaml .= " shell: bash\n"; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
|
|
223
|
1
|
|
|
|
|
3
|
$yaml .= <<'YAML'; |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
- name: Show cpanm build log on failure (Windows) |
|
226
|
|
|
|
|
|
|
if: runner.os == 'Windows' && failure() |
|
227
|
|
|
|
|
|
|
shell: pwsh |
|
228
|
|
|
|
|
|
|
run: Get-Content "$env:USERPROFILE\.cpanm\work\*\build.log" -Tail 100 |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
- name: Show cpanm build log on failure (non-Windows) |
|
231
|
|
|
|
|
|
|
if: runner.os != 'Windows' && failure() |
|
232
|
|
|
|
|
|
|
run: tail -100 "$HOME/.cpanm/work/*/build.log" |
|
233
|
|
|
|
|
|
|
YAML |
|
234
|
|
|
|
|
|
|
|
|
235
|
1
|
|
|
|
|
21
|
return $yaml; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
|
|
238
|
1
|
|
|
1
|
|
2
|
sub _get_perl_versions($min, $max) { |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
2
|
|
|
239
|
|
|
|
|
|
|
# All available Perl versions in descending order |
|
240
|
1
|
|
|
|
|
13
|
my @all_versions = qw(5.42 5.40 5.38 5.36 5.34 5.32 5.30 5.28 5.26 5.24 5.22); |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# Normalize version strings for comparison |
|
243
|
1
|
|
|
|
|
24
|
my $min_normalized = _normalize_version($min); |
|
244
|
1
|
|
|
|
|
3
|
my $max_normalized = _normalize_version($max); |
|
245
|
|
|
|
|
|
|
|
|
246
|
1
|
|
|
|
|
2
|
my @selected; |
|
247
|
1
|
|
|
|
|
4
|
for my $version (@all_versions) { |
|
248
|
11
|
|
|
|
|
18
|
my $v_normalized = _normalize_version($version); |
|
249
|
11
|
100
|
100
|
|
|
56
|
if ($v_normalized >= $min_normalized && $v_normalized <= $max_normalized) { |
|
250
|
3
|
|
|
|
|
8
|
push @selected, $version; |
|
251
|
|
|
|
|
|
|
} |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
|
|
254
|
1
|
|
|
|
|
5
|
return reverse @selected; # Return in ascending order |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
|
|
257
|
13
|
|
|
13
|
|
20
|
sub _normalize_version($version) { |
|
|
13
|
|
|
|
|
21
|
|
|
|
13
|
|
|
|
|
20
|
|
|
258
|
|
|
|
|
|
|
# Convert "5.036" or "5.36" to comparable number |
|
259
|
13
|
|
|
|
|
41
|
$version =~ s/^v?//; |
|
260
|
13
|
|
|
|
|
34
|
my @parts = split /\./, $version; |
|
261
|
13
|
|
50
|
|
|
63
|
return sprintf("%d.%03d", $parts[0] // 5, $parts[1] // 0); |
|
|
|
|
50
|
|
|
|
|
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head1 AUTHOR |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Nigel Horne Enjh@nigelhorne.comE |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
L |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=head1 LICENSE |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
273
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=cut |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
1; |