Skip to content
Merged
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
12 changes: 12 additions & 0 deletions dev/import-perl5/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -749,10 +749,12 @@ imports:
# CPAN.pm - Main CPAN client
- source: perl5/cpan/CPAN/lib/CPAN.pm
target: src/main/perl/lib/CPAN.pm
patch: CPAN.pm.patch

# App::Cpan - Command-line interface for CPAN.pm (used by jcpan)
- source: perl5/cpan/CPAN/lib/App/Cpan.pm
target: src/main/perl/lib/App/Cpan.pm
patch: App-Cpan.pm.patch

# autouse - Postpone loading of modules until a function is used
- source: perl5/dist/autouse/lib/autouse.pm
Expand Down Expand Up @@ -785,6 +787,16 @@ imports:
target: src/main/perl/lib/CPAN/HandleConfig.pm
patch: CPAN-HandleConfig.pm.patch

- source: perl5/cpan/CPAN/lib/CPAN/Index.pm
target: src/main/perl/lib/CPAN/Index.pm
patch: CPAN-Index.pm.patch
protected: true

- source: perl5/cpan/CPAN/lib/CPAN/Shell.pm
target: src/main/perl/lib/CPAN/Shell.pm
patch: CPAN-Shell.pm.patch
protected: true

# CPAN::Meta - Metadata handling for CPAN distributions
- source: perl5/cpan/CPAN-Meta/lib/CPAN/Meta.pm
target: src/main/perl/lib/CPAN/Meta.pm
Expand Down
37 changes: 37 additions & 0 deletions dev/import-perl5/patches/App-Cpan.pm.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--- perl5/cpan/CPAN/lib/App/Cpan.pm 2026-04-10 11:04:21
+++ src/main/perl/lib/App/Cpan.pm 2026-08-10 10:12:19
@@ -652,6 +652,7 @@
$action->( $arg );

my $error = _cpanpm_output_indicates_failure();
+ $error ||= _cpanpm_status_indicates_failure();
push @errors, $error if $error;
}

@@ -752,7 +753,7 @@

BEGIN {
my $epic_fail_words = join '|',
- qw( Error stop(?:ping)? problems force not unsupported
+ qw( Error stop(?:ping)? problems force unsupported
fail(?:ed)? Cannot\s+install );

sub _cpanpm_output_indicates_failure
@@ -763,6 +764,17 @@
return A_MODULE_FAILED_TO_INSTALL if $last_line =~ /\b(?:Cannot\s+install)\b/i;

$result || ();
+ }
+
+sub _cpanpm_status_indicates_failure
+ {
+ # CPAN already records structured phase status for every distribution in
+ # the current command, including recursively installed prerequisites.
+ # Prefer that state when App::Cpan's legacy last-output-line heuristic is
+ # fooled by trailing hints or report suggestions.
+ my @failed = CPAN::Shell->find_failed($CPAN::CurrentCommandId);
+ return A_MODULE_FAILED_TO_INSTALL if grep { $_->[5] } @failed;
+ return;
}
}

28 changes: 24 additions & 4 deletions dev/import-perl5/patches/CPAN-HandleConfig.pm.patch
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
--- perl5/cpan/CPAN/lib/CPAN/HandleConfig.pm
+++ src/main/perl/lib/CPAN/HandleConfig.pm
@@ -546,8 +546,11 @@
--- perl5/cpan/CPAN/lib/CPAN/HandleConfig.pm 2026-04-10 11:04:21
+++ src/main/perl/lib/CPAN/HandleConfig.pm 2026-08-10 10:13:33
@@ -137,6 +137,7 @@
"make",
"make_install_make_command",
"prefer_installer",
+ "recommends_policy",
"test_report",
);

@@ -527,6 +528,11 @@

# prioritized list of possible places for finding "CPAN/MyConfig.pm"
sub cpan_home_dir_candidates {
+ if (defined $ENV{PERLONJAVA_HOME} && length $ENV{PERLONJAVA_HOME}) {
+ my $dir = File::Spec->catdir($ENV{PERLONJAVA_HOME}, 'cpan');
+ return wantarray ? ($dir) : $dir;
+ }
+
my @dirs;
my $old_v = $CPAN::Config->{load_module_verbosity};
$CPAN::Config->{load_module_verbosity} = q[none];
@@ -546,8 +552,11 @@
push @dirs, $ENV{USERPROFILE} if $ENV{USERPROFILE};

$CPAN::Config->{load_module_verbosity} = $old_v;
- my $dotcpan = $^O eq 'VMS' ? '_cpan' : '.cpan';
- @dirs = map { File::Spec->catdir($_, $dotcpan) } grep { defined } @dirs;
+ # PerlOnJava uses ~/.perlonjava/cpan as its CPAN home to stay separate
+ # PerlOnJava uses ~/.perlonjava/cpan as its default CPAN home to stay separate
+ # from the user's system CPAN (~/.cpan), which would otherwise override
+ # our prefs_dir and other PerlOnJava-specific defaults.
+ my @suffix = $^O eq 'VMS' ? ('_cpan') : ('.perlonjava', 'cpan');
Expand Down
19 changes: 19 additions & 0 deletions dev/import-perl5/patches/CPAN-Index.pm.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--- perl5/cpan/CPAN/lib/CPAN/Index.pm 2026-04-10 11:04:21
+++ src/main/perl/lib/CPAN/Index.pm 2026-08-10 10:13:33
@@ -597,11 +597,11 @@
while(my($class,$v) = each %$cache) {
next unless $class =~ /^CPAN::/;
$CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok
- while (my($id,$ro) = each %$v) {
- $CPAN::META->{readwrite}{$class}{$id} ||=
- $class->new(ID=>$id, RO=>$ro);
- $idcnt++;
- }
+ # Mutable CPAN objects are created lazily by CPAN::instance (or in
+ # bulk by CPAN::all_objects). Eagerly blessing every cached module,
+ # distribution, and author makes a normal jcpan invocation spend
+ # minutes allocating objects it will never use.
+ $idcnt += scalar keys %$v;
$clcnt++;
}
unless ($clcnt) { # sanity check
15 changes: 15 additions & 0 deletions dev/import-perl5/patches/CPAN-Shell.pm.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- perl5/cpan/CPAN/lib/CPAN/Shell.pm 2026-04-10 11:04:21
+++ src/main/perl/lib/CPAN/Shell.pm 2026-08-10 10:13:33
@@ -1111,7 +1111,11 @@
sub find_failed {
my($self,$only_id) = @_;
my @failed;
- DIST: for my $d (sort { $a->id cmp $b->id } $CPAN::META->all_objects("CPAN::Distribution")) {
+ # Failure status is session state. Iterating the mutable objects is both
+ # sufficient and avoids inflating the complete cached distribution index
+ # merely to print the command summary.
+ DIST: for my $d (sort { $a->id cmp $b->id }
+ values %{ $CPAN::META->{readwrite}{'CPAN::Distribution'} || {} }) {
my $failed = "";
NAY: for my $nosayer ( # order matters!
"unwrapped",
39 changes: 39 additions & 0 deletions dev/import-perl5/patches/CPAN.pm.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--- perl5/cpan/CPAN/lib/CPAN.pm 2026-04-10 11:04:21
+++ src/main/perl/lib/CPAN.pm 2026-08-10 10:12:28
@@ -703,6 +703,13 @@
CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG;
CPAN::Index->reload;
+ # Metadata caches can contain hundreds of thousands of entries. Keep
+ # startup cheap by creating their mutable session wrappers only when a
+ # command really asks to enumerate the whole class.
+ for my $id (keys %{ $META->{readonly}{$class} || {} }) {
+ $META->{readwrite}{$class}{$id} ||=
+ $class->new(ID => $id, RO => $META->{readonly}{$class}{$id});
+ }
values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok
}

@@ -1320,7 +1327,9 @@
$id ||= "";
# unsafe meta access, ok?
return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id};
- $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id);
+ my $ro = $META->{readonly}{$class}{$id};
+ $META->{readwrite}{$class}{$id} ||=
+ $class->new(ID => $id, defined($ro) ? (RO => $ro) : ());
}

#-> sub CPAN::new ;
@@ -1441,7 +1450,10 @@
if ($foul) {
$CPAN::Frontend->mywarn("Lost build_dir detected ($foul), giving up all cached test results of currently running session.\n");
for my $dbd (sort keys %{$self->{is_tested}}) { # distro-build-dir
- SEARCH: for my $d (sort { $a->id cmp $b->id } $CPAN::META->all_objects("CPAN::Distribution")) {
+ # build_dir and test state exist only on mutable objects touched in
+ # this session; cached read-only distributions cannot match here.
+ SEARCH: for my $d (sort { $a->id cmp $b->id }
+ values %{ $CPAN::META->{readwrite}{'CPAN::Distribution'} || {} }) {
if ($d->{build_dir} && $d->{build_dir} eq $dbd) {
$CPAN::Frontend->mywarn(sprintf "Flushing cache for %s\n", $d->pretty_id);
$d->fforce("");
14 changes: 7 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ bouncycastle = "1.85"
commons-compress = "1.28.0"
commons-csv = "1.14.1"
icu4j = "78.3"
junit-jupiter = "6.1.2"
jsoup = "1.22.2"
snakeyaml-engine = "3.0.1"
sqlite-jdbc = "3.53.2.0"
jsoup = "1.23.1"
junit-jupiter = "6.1.3"
snakeyaml-engine = "3.1.1"
sqlite-jdbc = "3.53.2.1"
tomlj = "1.1.1"

[libraries]
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
asm-util = { module = "org.ow2.asm:asm-util", version.ref = "asm" }
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncycastle" }
bcprov = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "bouncycastle" }
bcprov = "org.bouncycastle:bcprov-jdk18on:1.85.2"
commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" }
commons-csv = { module = "org.apache.commons:commons-csv", version.ref = "commons-csv" }
icu4j = { module = "com.ibm.icu:icu4j", version.ref = "icu4j" }
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" }
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit-jupiter" }
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
snakeyaml-engine = { module = "org.snakeyaml:snakeyaml-engine", version.ref = "snakeyaml-engine" }
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite-jdbc" }
tomlj = { module = "org.tomlj:tomlj", version.ref = "tomlj" }
Expand All @@ -30,4 +30,4 @@ tomlj = { module = "org.tomlj:tomlj", version.ref = "tomlj" }
cyclonedx = "org.cyclonedx.bom:2.3.0"
ospackage = "com.netflix.nebula.ospackage:12.3.0"
shadow = "com.gradleup.shadow:9.3.1"
version-catalog-update = "nl.littlerobots.version-catalog-update:1.1.0"
version-catalog-update = "nl.littlerobots.version-catalog-update:1.1.1"
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>6.1.2</version>
<version>6.1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>6.1.2</version>
<version>6.1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>6.1.2</version>
<version>6.1.3</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -54,7 +54,7 @@
<dependency>
<groupId>org.snakeyaml</groupId>
<artifactId>snakeyaml-engine</artifactId>
<version>3.0.1</version>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.tomlj</groupId>
Expand All @@ -74,12 +74,12 @@
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.53.2.0</version>
<version>3.53.2.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.85</version>
<version>1.85.2</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
Expand All @@ -89,7 +89,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.2.16.Final</version>
<version>4.2.17.Final</version>
</dependency>
<!-- JNR-POSIX removed - using Java FFM API for native access (Java 22+) -->
</dependencies>
Expand Down
Loading
Loading