Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 70 additions & 37 deletions lib/CPAN.pm
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ sub _flock {

sub _yaml_module () {
my $yaml_module = $CPAN::Config->{yaml_module} || "YAML";
# only for testing
# $yaml_module = 'YAML::PP';
# $yaml_module = 'YAML::PP::LibYAML';
if (
$yaml_module ne "YAML"
&&
Expand Down Expand Up @@ -553,35 +556,53 @@ sub _yaml_loadfile {
return +[] unless -s $local_file;
my $yaml_module = _yaml_module;
if ($CPAN::META->has_inst($yaml_module)) {
# temporarily enable yaml code deserialisation
no strict 'refs';
# 5.6.2 could not do the local() with the reference
# so we do it manually instead
my $old_loadcode = ${"$yaml_module\::LoadCode"};
${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0;

my ($code, @yaml);
if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) {
eval { @yaml = $code->($local_file); };
if ($@) {
# this shall not be done by the frontend
die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);
}
} elsif ($code = UNIVERSAL::can($yaml_module, "Load")) {
local *FH;
unless (open FH, $local_file) {
$CPAN::Frontend->mywarn("Could not open '$local_file': $!");
return +[];
}
local $/;
my $ystream = <FH>;
eval { @yaml = $code->($ystream); };
if ($@) {
# this shall not be done by the frontend
die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);

my @yaml;
if ($yaml_module eq 'YAML::PP' or $yaml_module eq 'YAML::PP::LibYAML') {
require YAML::PP::Schema::Perl;
my $perl = YAML::PP::Schema::Perl->new(
classes => [qw/ CPAN::URL CPAN::Distribution CPAN::Distrostatus CPAN::DeferredCode /],
loadcode => $CPAN::Config->{yaml_load_code},
tags => ['!perl', '!!perl'],
);
my $yp = $yaml_module->new(
schema => ['+', $perl],
);
eval { @yaml = $yp->load_file($local_file) };
}
else {
# temporarily enable yaml code deserialisation
no strict 'refs';
# 5.6.2 could not do the local() with the reference
# so we do it manually instead
my $old_loadcode = ${"$yaml_module\::LoadCode"};
my $old_loadblessed = ${"$yaml_module\::LoadBlessed"};
${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0;
${ "$yaml_module\::LoadBlessed" } = 1;
my $code;
if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) {
eval { @yaml = $code->($local_file); };
if ($@) {
# this shall not be done by the frontend
die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);
}
} elsif ($code = UNIVERSAL::can($yaml_module, "Load")) {
local *FH;
unless (open FH, $local_file) {
$CPAN::Frontend->mywarn("Could not open '$local_file': $!");
return +[];
}
local $/;
my $ystream = <FH>;
eval { @yaml = $code->($ystream); };
if ($@) {
# this shall not be done by the frontend
die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);
}
}
${"$yaml_module\::LoadCode"} = $old_loadcode;
${"$yaml_module\::LoadBlessed"} = $old_loadblessed;
}
${"$yaml_module\::LoadCode"} = $old_loadcode;
return \@yaml;
} else {
# this shall not be done by the frontend
Expand All @@ -595,16 +616,28 @@ sub _yaml_dumpfile {
my($self,$local_file,@what) = @_;
my $yaml_module = _yaml_module;
if ($CPAN::META->has_inst($yaml_module)) {
my $code;
if (UNIVERSAL::isa($local_file, "FileHandle")) {
$code = UNIVERSAL::can($yaml_module, "Dump");
eval { print $local_file $code->(@what) };
} elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) {
eval { $code->($local_file,@what); };
} elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) {
local *FH;
open FH, ">$local_file" or die "Could not open '$local_file': $!";
print FH $code->(@what);
if ($yaml_module eq 'YAML::PP' or $yaml_module eq 'YAML::PP::LibYAML') {
my $perl = YAML::PP::Schema::Perl->new(
classes => [qw/ CPAN::URL CPAN::Distribution CPAN::Distrostatus CPAN::DeferredCode /],
tags => ['!perl', '!!perl'],
);
my $yp = $yaml_module->new(
schema => ['+', $perl],
);
eval { $yp->dump_file($local_file, @what) };
}
else {
my $code;
if (UNIVERSAL::isa($local_file, "FileHandle")) {
$code = UNIVERSAL::can($yaml_module, "Dump");
eval { print $local_file $code->(@what) };
} elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) {
eval { $code->($local_file,@what); };
} elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) {
local *FH;
open FH, ">$local_file" or die "Could not open '$local_file': $!";
print FH $code->(@what);
}
}
if ($@) {
die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"dump",$@);
Expand Down
2 changes: 2 additions & 0 deletions t/31sessions.t
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ EOF
"get CPAN::Test::Dummy::Perl5::Build::Fails" => "Has already been unwrapped",
"make CPAN::Test::Dummy::Perl5::Build::Fails" => "Has.already.been.unwrapped",
"test CPAN::Test::Dummy::Perl5::Build::Fails" => "(?i:t/00_load.+FAILED)",
"o conf dontload_list push YAML::PP" => ".",
"o conf dontload_list push YAML::PP::LibYAML" => ".",
"o conf dontload_list push YAML" => ".",
"o conf dontload_list push YAML::Syck" => ".",
"o conf dontload_list push Parse::CPAN::Meta" => ".",
Expand Down