Alien-Xrepo
view release on metacpan or search on metacpan
lib/Alien/Xrepo/Build.pm view on Meta::CPAN
if ( ref $info eq 'Alien::Xrepo::PackageInfo' ) {
$runtime_prop->{packages}{$name} = $info->_data_printer(undef);
$install_type = 'share';
}
}
$self->_checkpoint;
$stage_done->{install} = 1;
$self;
}
method gather () {
return if $stage_done->{gather};
$self->run_hooks('gather');
$runtime_prop->{packages} ||= {};
my $profile = $install_prop->{profile} // {};
for my $name ( $recipe->packages ) {
next if exists $runtime_prop->{packages}{$name} || exists $runtime_prop->{errors}{$name};
if ( my $root = $self->_pkg_root($name) ) {
$runtime_prop->{packages}{$name} = $self->_root_entry($root);
next;
}
my %opts = $recipe->opts_for( $name, %$profile );
my $info;
eval { $info = $r->fetch( $name, $recipe->version_for($name), %opts ); };
if ($@) {
warn "[!] $name could not be gathered: $@\n";
$runtime_prop->{errors}{$name} //= "$@";
next;
}
if ( ref $info eq 'Alien::Xrepo::PackageInfo' ) {
$runtime_prop->{packages}{$name} = $info->_data_printer(undef);
$install_type = 'share';
}
}
$self->_checkpoint;
$stage_done->{gather} = 1;
$self;
}
method export () {
return if $stage_done->{export};
$self->run_hooks('export');
if ( my $dir = $export_dir ) {
for my $name ( $recipe->packages ) {
next if exists $runtime_prop->{errors}{$name};
say "Exporting $name into $dir..." if $verbose;
eval { $r->export( $name, $recipe->version_for($name), packagedir => path($dir)->child($name)->absolute ); };
warn "[!] $name could not be exported: $@\n" if $@;
}
}
if ($snapshot) {
my $data = {
dist_name => $recipe->name,
install_type => $install_type,
pkg_roots => $recipe->pkg_roots,
packages => $runtime_prop->{packages} // {},
errors => $runtime_prop->{errors} // {},
digest => $self->_config_digest
};
path($snapshot)->parent->mkpath if defined $snapshot;
path($snapshot)->spew_utf8( encode_json($data) . "\n" );
say "Wrote runtime snapshot $snapshot" if $verbose;
}
$self->_checkpoint;
$stage_done->{export} = 1;
$self;
}
method test () {
return if $stage_done->{test};
$self->run_hooks('test');
$stage_done->{test} = 1;
$self;
}
method _version_for_pkg ($name) { $recipe->version_for($name) }
method _opts_for_pkg ( $name, %opts ) { $recipe->opts_for( $name, %opts ) }
method _config_digest () {
require Digest::SHA;
my @parts;
for my $name ( $recipe->packages ) {
my $version = $recipe->version_for($name);
my %opts = $recipe->opts_for( $name, %{ $install_prop->{profile} // {} } );
push @parts, $name, ( defined $version ? $version : '' );
push @parts, map { $_ . '=' . ( defined $opts{$_} ? $opts{$_} : '' ) } sort keys %opts;
}
Digest::SHA::sha256_hex( join "\x1f", @parts );
}
method _probe_satisfied ( $found, $expected ) {
return 0 unless defined $found && length $found;
return 1 unless defined $expected && length $expected;
return $found eq $expected;
}
# Recipe hook modules are loaded once per engine and invited to register their own stage hooks the same way code
# can: module->register_hooks($self).
method _load_recipe_hooks () {
for my $mod ( @{ $recipe->hooks || [] } ) {
next if $loaded_hooks->{$mod};
my $file = $mod;
$file =~ s{::}{/}g;
$file .= '.pm';
require $file;
my $register = $mod->can('register_hooks');
die "Alien::Xrepo::Build: recipe hook module '$mod' must expose register_hooks(\$build), got '$mod'" unless $register;
$register->($self);
$loaded_hooks->{$mod} = 1;
}
return;
}
# pkg_roots mirror Alien::Build's: name => environment variable whose value holds the package root. When the
# variable is set and points at an existing directory the package is treated as system-provided there and xrepo is
# never consulted (probe reports it satisfied; install/gather record it directly).
method _pkg_root ($name) {
my $pr = $recipe->pkg_roots->{$name};
return () unless defined $pr && length $pr;
my $dir = $ENV{$pr};
return () unless defined $dir && length $dir && -d $dir;
return path($dir)->absolute->stringify;
}
method _root_entry ($root) {
my @inc = -d path($root)->child('include') ? ( path($root)->child('include')->stringify ) : ();
my @lib = -d path($root)->child('lib') ? ( path($root)->child('lib')->stringify ) : ();
my @bin = -d path($root)->child('bin') ? ( path($root)->child('bin')->stringify ) : ();
{ includedirs => \@inc,
libfiles => [],
license => undef,
linkdirs => \@lib,
links => [],
shared => 1,
static => 0,
version => undef,
libpath => undef,
bindirs => \@bin,
installdir => $root,
kind => 'system'
};
}
method _can_skip_install ($name) {
return 0 unless $probe_policy eq 'skip';
my $probe = $install_prop->{probed}{$name} // {};
return 0 unless $probe->{satisfied};
my %opts = $self->_opts_for_pkg( $name, %{ $install_prop->{profile} // {} } );
!$opts{force};
}
method _checkpoint () {
return unless defined $checkpoint;
path($checkpoint)->parent->mkpath;
my $data = {
install_type => $install_type,
stage_done => $stage_done,
meta_prop => $meta_prop,
install_prop => $install_prop,
runtime_prop => $runtime_prop
};
path($checkpoint)->spew_utf8( encode_json($data) . "\n" );
return;
}
#
method _load_checkpoint () {
return 0 unless defined $checkpoint && -e $checkpoint;
my $data = eval { decode_json( path($checkpoint)->slurp_utf8 ) };
return 0 unless ref $data eq 'HASH';
$install_type = $data->{install_type} // 'system';
$stage_done = $data->{stage_done} // {};
$meta_prop = $data->{meta_prop} // {};
$install_prop = $data->{install_prop} // {};
$runtime_prop = $data->{runtime_prop} // {};
return 1;
}
};
#
1;
__END__
Copyright (C) Sanko Robinson.
This library is free software; you can redistribute it and/or modify it under the terms found in
the Artistic License 2. Other copyrights, terms, and conditions may apply to data transmitted
through this module.
( run in 0.548 second using v1.01-cache-2.11-cpan-364913b4093 )