File Coverage

blib/lib/App/Rakubrew/Build.pm
Criterion Covered Total %
statement 26 172 15.1
branch 0 58 0.0
condition 0 28 0.0
subroutine 9 21 42.8
pod 0 5 0.0
total 35 284 12.3


line stmt bran cond sub pod time code
1             package App::Rakubrew::Build;
2             require Exporter;
3             our @ISA = qw(Exporter);
4             our @EXPORT = qw();
5              
6 15     15   98 use strict;
  15         29  
  15         623  
7 15     15   79 use warnings;
  15         28  
  15         891  
8 15     15   321 use 5.010;
  15         55  
9 15     15   91 use File::Spec::Functions qw(catdir catfile updir);
  15         84  
  15         1255  
10 15     15   10991 use IPC::Cmd qw(can_run);
  15         1171934  
  15         1328  
11 15     15   150 use Cwd qw(cwd);
  15         45  
  15         868  
12 15     15   11633 use App::Rakubrew::Variables;
  15         69  
  15         2677  
13 15     15   6969 use App::Rakubrew::Tools;
  15         46  
  15         1304  
14 15     15   7709 use App::Rakubrew::VersionHandling;
  15         51  
  15         33884  
15              
16             sub _version_is_at_least {
17 0     0     my $min_ver = shift;
18 0           my $rakudo_dir = shift;
19 0           my $ver = slurp(catfile($rakudo_dir, 'VERSION'));
20 0           my ($min_year, $min_month, $min_sub);
21 0           my ($year, $month, $sub);
22 0 0         if ($ver =~ /(\d\d\d\d)\.(\d\d)(?:\.(\d+))?/ ) {
23 0           $year = $1;
24 0           $month = $2;
25 0   0       $sub = $3 // 0;
26             }
27 0 0         if ($min_ver =~ /(\d\d\d\d)\.(\d\d)(?:\.(\d+))?/ ) {
28 0           $min_year = $1;
29 0           $min_month = $2;
30 0   0       $min_sub = $3 // 0;
31             }
32              
33             # If it's not a release by date, it's older.
34 0 0 0       return 1 if !$min_year && $year;
35 0 0 0       return 0 if $min_year && !$year;
36              
37             # If both are really old not by date releases, we are conservative and say
38             # the release is older hopefully backwards compatibility will save us.
39 0 0 0       return 0 if !$min_year && !$year;
40              
41 0 0         return 1 if $min_year < $year;
42 0 0         return 0 if $min_year > $year;
43 0 0         return 1 if $min_month < $month;
44 0 0         return 0 if $min_month > $month;
45 0 0         return 1 if $min_sub < $sub;
46 0 0         return 0 if $min_sub > $sub;
47              
48 0           return 1; # $min_sub == $sub;
49             }
50              
51             sub _get_git_cache_option {
52 0     0     my $rakudo_dir = shift;
53 0 0         if ( _version_is_at_least('2020.02', $rakudo_dir) ) {
54 0           return "--git-cache-dir=\"$git_reference\"";
55             }
56             else {
57 0           return "--git-reference=\"$git_reference\"";
58             }
59             }
60              
61             sub available_rakudos {
62 0     0 0   _check_git();
63              
64 0           my @output = qx|$GIT ls-remote --tags $git_repos{rakudo}|;
65 0           my @tags = grep(m{refs/tags/([^\^]+)\^\{\}}, @output);
66 0           @tags = map(m{tags/([^\^]+)\^}, @tags);
67 0           @tags = grep(/^\d/, @tags);
68 0           return sort(@tags), 'main';
69             }
70              
71             sub build_impl {
72 0     0 0   my ($impl, $ver, $configure_opts) = @_;
73              
74 0           _check_build_dependencies();
75              
76 0           my $name = "$impl-$ver";
77 0 0 0       $name = $impl if $impl eq 'moar-blead' && $ver eq 'main';
78              
79 0 0 0       if (version_exists($name) && is_registered_version($name)) {
80 0           say STDERR "$name is a registered version. I'm not going to touch it.";
81 0           exit 1;
82             }
83              
84 0           chdir $versions_dir;
85 0 0         unless (version_exists($name)) {
86 0           for(@{$impls{$impl}{need_repo}}) {
  0            
87 0           _update_git_reference($_);
88             }
89 0           run "$GIT clone --reference \"$git_reference/rakudo\" $git_repos{rakudo} $name";
90             }
91 0           chdir $name;
92 0           run "$GIT fetch";
93             # when people say 'build somebranch', they usually mean 'build origin/somebranch'
94 0           my $ver_to_checkout = $ver;
95 0           eval {
96 0           run "$GIT rev-parse -q --verify origin/$ver";
97 0           $ver_to_checkout = "origin/$ver";
98             };
99 0           run "$GIT checkout -q $ver_to_checkout";
100              
101 0           $configure_opts .= ' ' . _get_git_cache_option(cwd());
102 0           run $impls{$impl}{configure} . " $configure_opts";
103              
104 0 0         if (is_version_broken($name)) {
105 0           say STDERR "ERROR: The build does not look usable. There is no raku executable to be";
106 0           say STDERR "found in $versions_dir/$name/bin";
107 0           say STDERR "or in $versions_dir/$name/install/bin";
108 0           exit 1;
109             }
110             }
111              
112             sub determine_make {
113 0     0 0   my $version = shift;
114              
115 0           my $cmd = get_raku($version) . ' --show-config';
116 0           my $config = qx{$cmd};
117              
118 0           my $make;
119 0 0         $make = $1 if $config =~ m/::make=(.*)$/m;
120              
121 0 0         if (!$make) {
122 0           say STDERR "Couldn't determine correct make program. Aborting.";
123 0           exit 1;
124             }
125              
126 0           return $make;
127             }
128              
129             sub build_triple {
130 0     0 0   my ($rakudo_ver, $nqp_ver, $moar_ver) = @_;
131              
132 0           _check_build_dependencies();
133              
134 0           my $impl = "moar";
135 0   0       $rakudo_ver //= 'HEAD';
136 0   0       $nqp_ver //= 'HEAD';
137 0   0       $moar_ver //= 'HEAD';
138              
139 0           my $name = "$impl-$rakudo_ver-$nqp_ver-$moar_ver";
140              
141 0           chdir $versions_dir;
142              
143 0 0         unless (-d $name) {
144 0           _update_git_reference('rakudo');
145 0           run "$GIT clone --reference \"$git_reference/rakudo\" $git_repos{rakudo} $name";
146             }
147 0           chdir $name;
148 0           run "$GIT pull";
149 0           run "$GIT checkout $rakudo_ver";
150              
151 0           my $configure_opts = '--make-install'
152             . ' --prefix=' . catdir($versions_dir, $name, 'install')
153             . ' ' . _get_git_cache_option(cwd());
154              
155 0 0         unless (-d "nqp") {
156 0           _update_git_reference('nqp');
157 0           run "$GIT clone --reference \"$git_reference/nqp\" $git_repos{nqp}";
158             }
159 0           chdir "nqp";
160 0           run "$GIT pull";
161 0           run "$GIT checkout $nqp_ver";
162              
163 0 0         unless (-d "MoarVM") {
164 0           _update_git_reference('MoarVM');
165 0           run "$GIT clone --reference \"$git_reference/MoarVM\" $git_repos{MoarVM}";
166             }
167              
168 0           chdir "MoarVM";
169 0           run "$GIT pull";
170 0           run "$GIT checkout $moar_ver";
171              
172 0           run "$PERL5 Configure.pl " . $configure_opts;
173              
174 0           chdir updir();
175 0           run "$PERL5 Configure.pl --backend=moar " . $configure_opts;
176              
177 0           chdir updir();
178 0           run "$PERL5 Configure.pl --backend=moar " . $configure_opts;
179              
180 0 0         if (-d 'zef') {
181 0           say "Updating zef as well";
182 0           build_zef($name);
183             }
184              
185 0           return $name;
186             }
187              
188             sub _verify_git_branch_exists {
189 0     0     my $branch = shift;
190 0           return system("$GIT show-ref --verify -q refs/heads/" . $branch) == 0;
191             }
192              
193             sub build_zef {
194 0     0 0   my $version = shift;
195 0           my $zef_version = shift;
196              
197 0           _check_git();
198              
199 0 0         if (-d $zef_dir) {
200 0           chdir $zef_dir;
201 0 0         if (!_verify_git_branch_exists('main')) {
202 0           run "$GIT fetch -q origin main";
203             }
204 0           run "$GIT checkout -f -q main";
205 0           run "$GIT reset --hard HEAD";
206 0           run "$GIT pull -q";
207             } else {
208 0           run "$GIT clone $git_repos{zef} $zef_dir";
209 0           chdir $zef_dir;
210             }
211              
212 0           my %tags = map { chomp($_); $_ => 1 } `$GIT tag`;
  0            
  0            
213 0 0 0       if ( $zef_version && !$tags{$zef_version} ) {
214 0           die "Couldn't find version $zef_version, aborting\n";
215             }
216              
217 0 0         if ( $zef_version ) {
218 0           run "$GIT checkout tags/$zef_version";
219             } else {
220 0           run "$GIT checkout main";
221             }
222 0           run get_raku($version) . " -I. bin/zef test .";
223 0           run get_raku($version) . " -I. bin/zef --/test --force install .";
224             }
225              
226             sub _update_git_reference {
227 0     0     my $repo = shift;
228 0           my $back = cwd();
229 0           print "Update git reference: $repo\n";
230 0           chdir $git_reference;
231 0 0         unless (-d $repo) {
232 0           run "$GIT clone --bare $git_repos{$repo} $repo";
233             }
234 0           chdir $repo;
235 0           run "$GIT fetch";
236 0           chdir $back;
237             }
238              
239             sub _check_build_dependencies() {
240 0     0     _check_git();
241 0           _check_perl();
242             }
243              
244             sub _check_git {
245 0 0   0     if (!can_run($GIT)) {
246 0           say STDERR "Did not find `$GIT` program. That's a requirement for using some rakubrew commmands. Aborting.";
247 0           exit 1;
248             }
249             }
250              
251             sub _check_perl {
252 0 0   0     if (!can_run($PERL5)) {
253 0           say STDERR "Did not find `$PERL5` program. That's a requirement for using some rakubrew commands. Aborting.";
254 0           exit 1;
255             }
256             }
257              
258             1;
259