зеркало из https://github.com/microsoft/git.git
perl: generalize the Git::LoadCPAN facility
Change the two wrappers that load from CPAN (local OS) or our own copy to do so via the same codepath. I added the Error.pm wrapper in20d2a30f8f
("Makefile: replace perl/Makefile.PL with simple make rules", 2017-12-10), and shortly afterwards Matthieu Moy added a wrapper for Mail::Address inbd869f67b9
("send-email: add and use a local copy of Mail::Address", 2018-01-05). His loader was simpler since Mail::Address doesn't have an "import" method, but didn't do the same sanity checking; For example, a missing FromCPAN directory (which OS packages are likely not to have) wouldn't be explicitly warned about as a "BUG: ...". Update both to use a common implementation based on the previous Error.pm loader. Which has been amended to take the module to load as parameter, as well as whether or not that module has an import method. This loader should be generic enough to handle almost all CPAN modules out there, some use some crazy loading magic and wouldn't like being wrapped like this, but that would be immediately obvious, and we'd find out right away since the module wouldn't work at all. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
28654678cf
Коммит
edfb7b92a1
|
@ -0,0 +1,74 @@
|
|||
package Git::LoadCPAN;
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Git::LoadCPAN - Wrapper for loading modules from the CPAN (OS) or Git's own copy
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The Perl code in Git depends on some modules from the CPAN, but we
|
||||
don't want to make those a hard requirement for anyone building from
|
||||
source.
|
||||
|
||||
Therefore the L<Git::LoadCPAN> namespace shipped with Git contains
|
||||
wrapper modules like C<Git::LoadCPAN::Module::Name> that will first
|
||||
attempt to load C<Module::Name> from the OS, and if that doesn't work
|
||||
will fall back on C<Git::FromCPAN::Module::Name> shipped with Git
|
||||
itself.
|
||||
|
||||
Usually distributors will not ship with Git's Git::FromCPAN tree at
|
||||
all, preferring to use their own packaging of CPAN modules instead.
|
||||
|
||||
This module is only intended to be used for code shipping in the
|
||||
C<git.git> repository. Use it for anything else at your peril!
|
||||
|
||||
=cut
|
||||
|
||||
sub import {
|
||||
shift;
|
||||
my $caller = caller;
|
||||
my %args = @_;
|
||||
my $module = exists $args{module} ? delete $args{module} : die "BUG: Expected 'module' parameter!";
|
||||
my $import = exists $args{import} ? delete $args{import} : die "BUG: Expected 'import' parameter!";
|
||||
die "BUG: Too many arguments!" if keys %args;
|
||||
|
||||
# Foo::Bar to Foo/Bar.pm
|
||||
my $package_pm = $module;
|
||||
$package_pm =~ s[::][/]g;
|
||||
$package_pm .= '.pm';
|
||||
|
||||
eval {
|
||||
require $package_pm;
|
||||
1;
|
||||
} or do {
|
||||
my $error = $@ || "Zombie Error";
|
||||
|
||||
my $Git_LoadCPAN_pm_path = $INC{"Git/LoadCPAN.pm"} || die "BUG: Should have our own path from %INC!";
|
||||
|
||||
require File::Basename;
|
||||
my $Git_LoadCPAN_pm_root = File::Basename::dirname($Git_LoadCPAN_pm_path) || die "BUG: Can't figure out lib/Git dirname from '$Git_LoadCPAN_pm_path'!";
|
||||
|
||||
require File::Spec;
|
||||
my $Git_pm_FromCPAN_root = File::Spec->catdir($Git_LoadCPAN_pm_root, 'FromCPAN');
|
||||
die "BUG: '$Git_pm_FromCPAN_root' should be a directory!" unless -d $Git_pm_FromCPAN_root;
|
||||
|
||||
local @INC = ($Git_pm_FromCPAN_root, @INC);
|
||||
require $package_pm;
|
||||
};
|
||||
|
||||
if ($import) {
|
||||
no strict 'refs';
|
||||
*{"${caller}::import"} = sub {
|
||||
shift;
|
||||
use strict 'refs';
|
||||
unshift @_, $module;
|
||||
goto &{"${module}::import"};
|
||||
};
|
||||
use strict 'refs';
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -2,45 +2,9 @@ package Git::LoadCPAN::Error;
|
|||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Git::LoadCPAN::Error - Wrapper for the L<Error> module, in case it's not installed
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Wraps the import function for the L<Error> module.
|
||||
|
||||
This module is only intended to be used for code shipping in the
|
||||
C<git.git> repository. Use it for anything else at your peril!
|
||||
|
||||
=cut
|
||||
|
||||
sub import {
|
||||
shift;
|
||||
my $caller = caller;
|
||||
|
||||
eval {
|
||||
require Error;
|
||||
1;
|
||||
} or do {
|
||||
my $error = $@ || "Zombie Error";
|
||||
|
||||
my $Git_Error_pm_path = $INC{"Git/LoadCPAN/Error.pm"} || die "BUG: Should have our own path from %INC!";
|
||||
|
||||
require File::Basename;
|
||||
my $Git_Error_pm_root = File::Basename::dirname($Git_Error_pm_path) || die "BUG: Can't figure out lib/Git dirname from '$Git_Error_pm_path'!";
|
||||
|
||||
require File::Spec;
|
||||
my $Git_pm_FromCPAN_root = File::Spec->catdir($Git_Error_pm_root, '..', 'FromCPAN');
|
||||
die "BUG: '$Git_pm_FromCPAN_root' should be a directory!" unless -d $Git_pm_FromCPAN_root;
|
||||
|
||||
local @INC = ($Git_pm_FromCPAN_root, @INC);
|
||||
require Error;
|
||||
};
|
||||
|
||||
unshift @_, $caller;
|
||||
goto &Error::import;
|
||||
}
|
||||
use Git::LoadCPAN (
|
||||
module => 'Error',
|
||||
import => 1,
|
||||
);
|
||||
|
||||
1;
|
||||
|
|
|
@ -2,23 +2,9 @@ package Git::LoadCPAN::Mail::Address;
|
|||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Git::LoadCPAN::Mail::Address - Wrapper for the L<Mail::Address> module, in case it's not installed
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is only intended to be used for code shipping in the
|
||||
C<git.git> repository. Use it for anything else at your peril!
|
||||
|
||||
=cut
|
||||
|
||||
eval {
|
||||
require Mail::Address;
|
||||
1;
|
||||
} or do {
|
||||
require Git::FromCPAN::Mail::Address;
|
||||
};
|
||||
use Git::LoadCPAN (
|
||||
module => 'Mail::Address',
|
||||
import => 0,
|
||||
);
|
||||
|
||||
1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче