$VERSION
=
substr
q$Revision: 1.15 $
, 10;
use
vars
qw(@ISA @EXPORT $VERSION)
;
@ISA
= (
'Exporter'
);
@EXPORT
= (
'install'
,
'uninstall'
,
'pm_to_blib'
);
$Is_VMS
= $^O eq
'VMS'
;
my
$splitchar
= $^O eq
'VMS'
?
'|'
: $^O eq
'os2'
?
';'
:
':'
;
my
@PERL_ENV_LIB
=
split
$splitchar
,
defined
$ENV
{
'PERL5LIB'
} ?
$ENV
{
'PERL5LIB'
} :
$ENV
{
'PERLLIB'
};
my
$Inc_uninstall_warn_handler
;
sub
forceunlink {
chmod
0666,
$_
[0];
unlink
$_
[0] or Carp::croak(
"Cannot forceunlink $_[0]: $!"
)
}
sub
install {
my
(
$hash
,
$verbose
,
$nonono
,
$inc_uninstall
) =
@_
;
$verbose
||= 0;
$nonono
||= 0;
my
(
%hash
) =
%$hash
;
my
(
%pack
,
%write
,
$dir
,
$warn_permissions
);
local
(
*DIR
,
*P
);
for
(
qw/read write/
) {
$pack
{
$_
}=
$hash
{
$_
};
delete
$hash
{
$_
};
}
my
(
$source_dir_or_file
);
foreach
$source_dir_or_file
(
sort
keys
%hash
) {
opendir
DIR,
$source_dir_or_file
or
next
;
for
(
readdir
DIR) {
next
if
$_
eq
"."
||
$_
eq
".."
||
$_
eq
".exists"
;
if
(-w
$hash
{
$source_dir_or_file
} || mkpath(
$hash
{
$source_dir_or_file
})) {
last
;
}
else
{
warn
"Warning: You do not have permissions to install into $hash{$source_dir_or_file}"
unless
$warn_permissions
++;
}
}
closedir
DIR;
}
if
(-f
$pack
{
"read"
}) {
open
P,
$pack
{
"read"
} or Carp::croak(
"Couldn't read $pack{'read'}"
);
while
(<P>) {
chomp
;
$write
{
$_
}++;
}
close
P;
}
my
$cwd
= cwd();
my
$umask
=
umask
0
unless
$Is_VMS
;
my
$MY
= {};
bless
$MY
,
'MY'
;
my
(
$source
);
MOD_INSTALL:
foreach
$source
(
sort
keys
%hash
) {
chdir
(
$source
) or
next
;
find(
sub
{
my
(
$dev
,
$ino
,
$mode
,
$nlink
,
$uid
,
$gid
,
$rdev
,
$size
,
$atime
,
$mtime
,
$ctime
,
$blksize
,
$blocks
) =
stat
;
return
unless
-f _;
return
if
$_
eq
".exists"
;
my
$targetdir
=
$MY
->catdir(
$hash
{
$source
},
$File::Find::dir
);
my
$targetfile
=
$MY
->catfile(
$targetdir
,
$_
);
my
$diff
= 0;
if
( -f
$targetfile
&& -s _ ==
$size
) {
$diff
= my_cmp(
$_
,
$targetfile
);
}
else
{
print
"$_ differs\n"
if
$verbose
>1;
$diff
++;
}
if
(
$diff
){
if
(-f
$targetfile
){
forceunlink(
$targetfile
)
unless
$nonono
;
}
else
{
mkpath(
$targetdir
,0,0755)
unless
$nonono
;
print
"mkpath($targetdir,0,0755)\n"
if
$verbose
>1;
}
copy(
$_
,
$targetfile
)
unless
$nonono
;
print
"Installing $targetfile\n"
;
utime
(
$atime
,
$mtime
+
$Is_VMS
,
$targetfile
)
unless
$nonono
>1;
print
"utime($atime,$mtime,$targetfile)\n"
if
$verbose
>1;
$mode
= 0444 | (
$mode
& 0111 ? 0111 : 0 );
chmod
$mode
,
$targetfile
;
print
"chmod($mode, $targetfile)\n"
if
$verbose
>1;
}
else
{
print
"Skipping $targetfile (unchanged)\n"
if
$verbose
;
}
if
(!
defined
$inc_uninstall
) {
}
elsif
(
$inc_uninstall
== 0){
inc_uninstall(
$_
,
$File::Find::dir
,
$verbose
,1);
}
else
{
inc_uninstall(
$_
,
$File::Find::dir
,
$verbose
,0);
}
$write
{
$targetfile
}++;
},
"."
);
chdir
(
$cwd
) or Carp::croak(
"Couldn't chdir to $cwd: $!"
);
}
umask
$umask
unless
$Is_VMS
;
if
(
$pack
{
'write'
}) {
$dir
= dirname(
$pack
{
'write'
});
mkpath(
$dir
,0,0755);
print
"Writing $pack{'write'}\n"
;
open
P,
">$pack{'write'}"
or Carp::croak(
"Couldn't write $pack{'write'}: $!"
);
for
(
sort
keys
%write
) {
print
P
"$_\n"
;
}
close
P;
}
}
sub
my_cmp {
my
(
$one
,
$two
) =
@_
;
local
(
*F
,
*T
);
my
$diff
= 0;
open
T,
$two
or
return
1;
open
F,
$one
or Carp::croak(
"Couldn't open $one: $!"
);
my
(
$fr
,
$tr
,
$fbuf
,
$tbuf
,
$size
);
$size
= 1024;
while
(
$fr
=
read
(F,
$fbuf
,
$size
)) {
unless
(
$tr
=
read
(T,
$tbuf
,
$size
) and
$tbuf
eq
$fbuf
){
$diff
++;
last
;
}
}
close
F;
close
T;
$diff
;
}
sub
uninstall {
my
(
$fil
,
$verbose
,
$nonono
) =
@_
;
die
"no packlist file found: $fil"
unless
-f
$fil
;
local
*P
;
open
P,
$fil
or Carp::croak(
"uninstall: Could not read packlist file $fil: $!"
);
while
(<P>) {
chomp
;
print
"unlink $_\n"
if
$verbose
;
forceunlink(
$_
)
unless
$nonono
;
}
print
"unlink $fil\n"
if
$verbose
;
forceunlink(
$fil
)
unless
$nonono
;
}
sub
inc_uninstall {
my
(
$file
,
$libdir
,
$verbose
,
$nonono
) =
@_
;
my
(
$dir
);
my
$MY
= {};
bless
$MY
,
'MY'
;
my
%seen_dir
= ();
foreach
$dir
(
@INC
,
@PERL_ENV_LIB
,
@Config::Config
{
qw/archlibexp privlibexp sitearchexp sitelibexp/
}) {
next
if
$dir
eq
"."
;
next
if
$seen_dir
{
$dir
}++;
my
(
$targetfile
) =
$MY
->catfile(
$dir
,
$libdir
,
$file
);
next
unless
-f
$targetfile
;
my
$diff
= 0;
if
( -f
$targetfile
&& -s _ == -s
$file
) {
$diff
= my_cmp(
$file
,
$targetfile
);
}
else
{
print
"#$file and $targetfile differ\n"
if
$verbose
>1;
$diff
++;
}
next
unless
$diff
;
if
(
$nonono
) {
if
(
$verbose
) {
$Inc_uninstall_warn_handler
||= new ExtUtils::Install::Warn;
$libdir
=~ s|^\./|| ;
$Inc_uninstall_warn_handler
->add(
"$libdir/$file"
,
$targetfile
);
}
}
else
{
print
"Unlinking $targetfile (shadowing?)\n"
;
forceunlink(
$targetfile
);
}
}
}
sub
pm_to_blib {
my
(
$fromto
,
$autodir
) =
@_
;
my
$umask
=
umask
0022
unless
$Is_VMS
;
mkpath(
$autodir
,0,0755);
foreach
(
keys
%$fromto
) {
next
if
-f
$fromto
->{
$_
} && -M
$fromto
->{
$_
} < -M
$_
;
unless
(my_cmp(
$_
,
$fromto
->{
$_
})){
print
"Skip $fromto->{$_} (unchanged)\n"
;
next
;
}
if
(-f
$fromto
->{
$_
}){
forceunlink(
$fromto
->{
$_
});
}
else
{
mkpath(dirname(
$fromto
->{
$_
}),0,0755);
}
copy(
$_
,
$fromto
->{
$_
});
my
(
$mode
,
$atime
,
$mtime
) = (
stat
)[2,8,9];
utime
(
$atime
,
$mtime
+
$Is_VMS
,
$fromto
->{
$_
});
chmod
(0444 | (
$mode
& 0111 ? 0111 : 0 ),
$fromto
->{
$_
});
print
"cp $_ $fromto->{$_}\n"
;
next
unless
/\.pm$/;
autosplit(
$fromto
->{
$_
},
$autodir
);
}
umask
$umask
unless
$Is_VMS
;
}
sub
new {
bless
{},
shift
}
sub
add {
my
(
$self
,
$file
,
$targetfile
) =
@_
;
push
@{
$self
->{
$file
}},
$targetfile
;
}
sub
DESTROY {
my
$self
=
shift
;
my
(
$file
,
$i
,
$plural
);
foreach
$file
(
sort
keys
%$self
) {
$plural
= @{
$self
->{
$file
}} > 1 ?
"s"
:
""
;
print
"## Differing version$plural of $file found. You might like to\n"
;
for
(0..$
print
"rm "
,
$self
->{
$file
}[
$_
],
"\n"
;
$i
++;
}
}
$plural
=
$i
>1 ?
"all those files"
:
"this file"
;
print
"## Running 'make install UNINST=1' will unlink $plural for you.\n"
;
}
1;