@ -19,10 +19,13 @@
# See http://www.koha.org/wiki/?page=KohaInstaller
#
u s e s t r i c t ;
u s e w a r n i n g s ;
use ExtUtils :: MakeMaker ;
u s e P O S I X ;
use File :: Spec ;
m y $DEBUG = 0;
d i e "perl 5.6.1 or later required" u n l e s s ( $ ] > = 5 . 0 0 6 0 0 1 ) ;
# Hash up directory structure & files beginning with the directory we were called from (should be the base of koha)...
@ -121,7 +124,7 @@ current organization of the source tree, but (FIXME) it
w o u l d b e b e t t e r t o r e o r g a n i z e t h e s o u r c e t r e e t o b e t t e r
m a t c h t h e i n s t a l l a t i o n s y s t e m , t o a l l o w a d d i n g n e w d i r e c t o r i e s
w i t h o u t h a v i n g t o a d j u s t M a k e f i l e . P L e a c h t i m e . T h e i d e a
i s t o m a k e t h e C < % t a r g e t _ m a p > h a s h a s m i n i m a l a s p o s s i b l e .
i s t o m a k e t h e C < $ t a r g e t _ m a p > h a s h a s m i n i m a l a s p o s s i b l e .
= b a c k
@ -168,6 +171,43 @@ Directory for Koha configuration files.
D i r e c t o r y f o r Z e b r a c o n f i g u r a t i o n f i l e s .
= i t e m Z E B R A _ L O C K _ D I R
D i r e c t o r y f o r Z e b r a ' s l o c k f i l e s .
= i t e m Z E B R A _ D A T A _ D I R
D i r e c t o r y f o r Z e b r a ' s d a t a f i l e s .
= i t e m Z E B R A _ R U N _ D I R
D i r e c t o r y f o r Z e b r a ' s U N I X - d o m a i n s o c k e t s .
= i t e m E X A M P L E _ D I R
D i r e c t o r y f o r e x a m p l e c o n f i g u r a t i o n f i l e s . T h i s d i r e c t o r y
e x i s t s p r i m a r i l y t o m a k e i t e a s i e r t o c h a n g e t h e
M A R C f o r m a t o r l a n g u a g e o f t h e a c t i v e Z e b r a
i n d e x e s .
= i t e m S C R I P T _ D I R
D i r e c t o r y f o r c o m m a n d - l i n e s c r i p t s a n d d a e m o n s .
= i t e m M A N _ D I R
D i r e c t o r y f o r m a n p a g e s c r e a t e d f r o m P O D - - w i l l m o s t l y
c o n t a i n i n f o r m a t i o n o f i n t e r e s t t o K o h a d e v e l o p e r s .
= i t e m D O C _ D I R
D i r e c t o r y f o r K o h a d o c u m e n t a t i o n a c c e s s e d f r o m t h e
c o m m a n d - l i n e , e . g . , R E A D M E s .
= i t e m L O G _ D I R
D i r e c t o r y f o r A p a c h e a n d Z e b r a l o g s p r o d u c e d b y K o h a .
= i t e m N O N E
T h i s i s a d u m m y t a r g e t u s e d t o e x p l i c i t l y s t a t e
@ -180,49 +220,59 @@ production installation.
= c u t
m y % target_map = (
'about.pl' = > 'INTRANET_CGI_DIR' ,
'acqui' = > 'INTRANET_CGI_DIR' ,
'admin' = > 'INTRANET_CGI_DIR' ,
'authorities' = > 'INTRANET_CGI_DIR' ,
'C4' = > 'PERL_MODULE_DIR' ,
'catalogue' = > 'INTRANET_CGI_DIR' ,
'cataloguing' = > 'INTRANET_CGI_DIR' ,
'changelanguage.pl' = > [ 'INTRANET_CGI_DIR' , 'OPAC_CGI_DIR' ] ,
'check_sysprefs.pl' = > 'NONE' ,
'circ' = > 'INTRANET_CGI_DIR' ,
'edithelp.pl' = > 'INTRANET_CGI_DIR' ,
'etc' = > 'KOHA_CONF_DIR' ,
'etc/zebradb' = > 'ZEBRA_CONF_DIR' ,
'installer-CPAN.pl' = > 'NONE' ,
'installer' = > 'INTRANET_CGI_DIR' ,
'koha-tmpl' = > 'NONE' ,
'koha-tmpl/intranet-tmpl' = > 'INTRANET_TMPL_DIR' ,
'koha-tmpl/opac-tmpl' = > 'OPAC_TMPL_DIR' ,
'koha-version.pl' = > 'INTRANET_CGI_DIR' , # FIXME this may need to be in OPAC_CGI_DIR as well, with an update to C4::Context
'labels' = > 'INTRANET_CGI_DIR' ,
'mainpage.pl' = > 'INTRANET_CGI_DIR' ,
'Makefile.PL' = > 'NONE' ,
'MANIFEST.SKIP' = > 'NONE' ,
'members' = > 'INTRANET_CGI_DIR' ,
'misc' = > 'NONE' , # FIXME deal with a little later
'opac' = > 'OPAC_CGI_DIR' ,
'README.txt' = > 'NONE' ,
'reports' = > 'INTRANET_CGI_DIR' ,
'reserve' = > 'INTRANET_CGI_DIR' ,
'reviews' = > 'INTRANET_CGI_DIR' ,
'rewrite-config.PL' = > 'NONE' ,
'reviews' = > 'INTRANET_CGI_DIR' ,
'rss' = > 'NONE' , # FIXME deal with a little later
'serials' = > 'INTRANET_CGI_DIR' ,
'sms' = > 'INTRANET_CGI_DIR' ,
'suggestion' = > 'INTRANET_CGI_DIR' ,
'svc' = > 'INTRANET_CGI_DIR' ,
't' = > 'NONE' ,
'tmp' = > 'NONE' , # FIXME deal with later
'tools' = > 'INTRANET_CGI_DIR' ,
'virtualshelves' = > 'INTRANET_CGI_DIR' ,
) ;
m y $target_map = {
'./about.pl' = > 'INTRANET_CGI_DIR' ,
'./acqui' = > 'INTRANET_CGI_DIR' ,
'./admin' = > 'INTRANET_CGI_DIR' ,
'./authorities' = > 'INTRANET_CGI_DIR' ,
'./C4' = > 'PERL_MODULE_DIR' ,
'./C4/SIP/t' = > 'NONE' ,
'./C4/SIP/koha_test' = > 'NONE' ,
'./C4/tests' = > 'NONE' ,
'./catalogue' = > 'INTRANET_CGI_DIR' ,
'./cataloguing' = > 'INTRANET_CGI_DIR' ,
'./changelanguage.pl' = > [ 'INTRANET_CGI_DIR' , 'OPAC_CGI_DIR' ] ,
'./check_sysprefs.pl' = > 'NONE' ,
'./circ' = > 'INTRANET_CGI_DIR' ,
'./edithelp.pl' = > 'INTRANET_CGI_DIR' ,
'./etc' = > { target = > 'KOHA_CONF_DIR' , trimdir = > -1 } ,
'./etc/zebradb' = > { target = > 'ZEBRA_CONF_DIR' , trimdir = > -1 } ,
'./installer-CPAN.pl' = > 'NONE' ,
'./installer' = > 'INTRANET_CGI_DIR' ,
'./koha-tmpl' = > 'NONE' ,
'./koha-tmpl/intranet-tmpl' = > { target = > 'INTRANET_TMPL_DIR' , trimdir = > -1} ,
'./koha-tmpl/opac-tmpl' = > { target = > 'OPAC_TMPL_DIR' , trimdir = > -11} ,
'./koha-version.pl' = > 'INTRANET_CGI_DIR' , # FIXME this may need to be in OPAC_CGI_DIR as well, with an update to C4::Context
'./labels' = > 'INTRANET_CGI_DIR' ,
'./mainpage.pl' = > 'INTRANET_CGI_DIR' ,
'./Makefile.PL' = > 'NONE' ,
'./MANIFEST.SKIP' = > 'NONE' ,
'./members' = > 'INTRANET_CGI_DIR' ,
'./misc' = > { target = > 'SCRIPT_DIR' , trimdir = > -1 } ,
'./misc/info' = > { target = > 'DOC_DIR' , trimdir = > 2 } ,
'./misc/release notes' = > { target = > 'DOC_DIR' , trimdir = > 2 } ,
'./misc/translator' = > { target = > 'EXAMPLE_DIR' , trimdir = > 2 } ,
'./misc/installer_devel_notes' = > 'NONE' ,
'./opac' = > 'OPAC_CGI_DIR' ,
'./README.txt' = > 'NONE' ,
'./reports' = > 'INTRANET_CGI_DIR' ,
'./reserve' = > 'INTRANET_CGI_DIR' ,
'./reviews' = > 'INTRANET_CGI_DIR' ,
'./rewrite-config.PL' = > 'NONE' ,
'./reviews' = > 'INTRANET_CGI_DIR' ,
'./rss' = > 'NONE' , # FIXME deal with a little later
'./serials' = > 'INTRANET_CGI_DIR' ,
'./sms' = > 'INTRANET_CGI_DIR' ,
'./suggestion' = > 'INTRANET_CGI_DIR' ,
'./svc' = > 'INTRANET_CGI_DIR' ,
'./t' = > 'NONE' ,
'./tmp' = > 'NONE' , # FIXME deal with later
'./tools' = > 'INTRANET_CGI_DIR' ,
'./virtualshelves' = > 'INTRANET_CGI_DIR' ,
# ignore files and directories created by the install itself
'./pm_to_blib' = > 'NONE' ,
'./blib' = > 'NONE' ,
} ;
= h e a d 1 C O N F I G U R A T I O N O P T I O N S
@ -281,6 +331,8 @@ my %valid_config_values = (
m y % config = get_configuration( \% config_defaults, \% valid_config_values) ;
m y % target_directories = get_target_directories( \% config) ;
m y $file_map = { } ;
g e t _ f i l e _ m a p ( $ t a r g e t _ m a p , $ d i r t r e e , $ f i l e _ m a p ) ;
W r i t e M a k e f i l e (
NAME = > 'koha' ,
@ -346,8 +398,11 @@ WriteMakefile(
} ,
# File tree mapping
# PM => map_tree(),
PM = > unhashdir( $dirtree ) ,
PM = > $file_map ,
# Man pages generated from POD
INSTALLMAN1DIR = > File::Spec->catdir( $target_directories { 'MAN_DIR' } , 'man1' ) ,
INSTALLMAN3DIR = > File::Spec->catdir( $target_directories { 'MAN_DIR' } , 'man3' ) ,
# disable tests
'test' = > { TESTS = > 't/dummy.t' } ,
@ -359,11 +414,11 @@ WriteMakefile(
PL_FILES = > { # generator => target(s)
'rewrite-config.PL' = > [
'$(PREFIX)/share/koha/etc /koha-conf.xml' ,
'$(PREFIX)/share/koha/etc /koha-httpd.conf' ,
'$(PREFIX)/share/koha/etc/zebradb /etc/passwd' ,
'$(PREFIX)/share/koha/etc/zebradb /zebra-biblios.cfg' ,
'$(PREFIX)/share/koha/etc/zebradb /zebra-authorities.cfg'
'blib/KOHA_CONF_DIR /koha-conf.xml' ,
'blib/KOHA_CONF_DIR /koha-httpd.conf' ,
'blib/ZEBRA_CONF_DIR /etc/passwd' ,
'blib/ZEBRA_CONF_DIR /zebra-biblios.cfg' ,
'blib/ZEBRA_CONF_DIR /zebra-authorities.cfg'
]
}
# 'opac/getfromintranet.PL' => ['$(INST_LIBDIR)/opac/cgi-bin/detail.pl','$(INST_LIBDIR)/opac/cgi-bin/moredetail.pl','$(INST_LIBDIR)/opac/cgi-bin/search.pl','$(INST_LIBDIR)/opac/cgi-bin/subjectsearch.pl','$(INST_LIBDIR)/opac/cgi-bin/logout.pl'],
@ -403,6 +458,122 @@ sub hashdir{
return $tree ;
}
= h e a d 2 g e t _ f i l e _ m a p
T h i s f u n c t i o n c o m b i n e s t h e t a r g e t _ m a p a n d f i l e h a s h t o
m a p e a c h s o u r c e f i l e t o i t s d e s t i n a t i o n r e l a t i v e t o
t h e s e t o f i n s t a l l a t i o n t a r g e t s .
O u t p u t w i l l b e a h a s h m a p p i n g f r o m e a c h s o u r c e f i l e
to its destination value, like this :
'mainpage.pl' = > '$(INTRANET_CGI_DIR)/mainpage.pl'
= c u t
s u b g e t _ f i l e _ m a p {
my $target_map = shift;
my $dirtree = shift;
my $file_map = shift;
my $curr_path = @_ ? shift : [ '.' ] ;
# Traverse the directory tree.
# For each file or directory, identify the
# most specific match in the target_map
foreach my $dir ( sort keys %{ $dirtree } ) {
if ( $dir eq '.' ) {
# deal with files in directory
foreach my $file ( sort @{ $dirtree ->{ $dir } } ) {
my $targetdir = undef;
my $matchlevel = undef;
# first, see if there is a match on this specific
# file in the target map
my $filepath = join( "/" , @$curr_path , $file ) ;
if ( exists $target_map ->{ $filepath } ) {
$targetdir = $target_map ->{ $filepath } ;
$matchlevel = scalar( @$curr_path ) + 1;
} else {
# no match on the specific file; look for
# a directory match
for ( my $i = scalar( @$curr_path ) - 1; $i >= 0; $i --) {
my $dirpath = join( "/" , @$curr_path [ 0..$i ] ) ;
if ( exists $target_map ->{ $dirpath } ) {
$targetdir = $target_map ->{ $dirpath } ;
$matchlevel = $i + 1;
last;
}
}
}
if ( defined $targetdir ) {
_add_to_file_map( $file_map , $targetdir , $curr_path , $file , $matchlevel ) ;
} else {
my $path = join( "/" , @$curr_path ) ;
print " failed to map: $path / $file \n " if $DEBUG ;
}
}
} else {
# dealing with subdirectory
push @$curr_path , $dir ;
get_file_map( $target_map , $dirtree ->{ $dir } , $file_map , $curr_path ) ;
pop @$curr_path ;
}
}
}
s u b _ a d d _ t o _ f i l e _ m a p {
my $file_map = shift;
my $targetdir = shift;
my $curr_path = shift;
my $file = shift;
my $matchlevel = shift;
my $dest_path = @_ ? shift : $curr_path ;
# The target can be one of the following:
# 1. scalar representing target symbol
# 2. hash ref containing target and trimdir keys
# 3. array ref containing list of #1 and #2
#
# Consequently, this routine traverses this structure,
# calling itself recursively, until it deals with
# all of the scalar target symbols.
if ( ref $targetdir eq 'ARRAY' ) {
foreach my $subtarget ( sort @$targetdir ) {
_add_to_file_map( $file_map , $subtarget , $curr_path , $file , $matchlevel ) ;
}
} elsif ( ref $targetdir eq 'HASH' ) {
my $subtarget = $targetdir ->{ target} ;
if ( exists $targetdir ->{ trimdir} ) {
# if we get here, we've specified that
# rather than installing the file to
# $(TARGET)/matching/dirs/subdirs/file,
# we want to install it to
# $(TARGET)/subdirs/file
#
# Note that this the only place where
# $matchlevel is used.
my @new_dest_path = @$dest_path ;
if ( $targetdir ->{ trimdir} = = -1) {
splice @new_dest_path, 0, $matchlevel ;
} else {
splice @new_dest_path, 0, $targetdir ->{ trimdir} ;
}
_add_to_file_map( $file_map , $subtarget , $curr_path , $file , $matchlevel , \@ new_dest_path) ;
} else {
# actually getting here means that the
# target was unnecessarily listed
# as a hash, but we'll forgive that
_add_to_file_map( $file_map , $subtarget , $curr_path , $file , $matchlevel ) ;
}
} elsif ( $targetdir ne 'NONE' and $targetdir ne '' ) {
my $source = File::Spec->catfile( @$curr_path , $file ) ;
return if $source = ~ / /; #FIXME
#my $destination = File::Spec->catfile("\$($targetdir)", @$dest_path, $file);
my $destination = File::Spec->catfile( 'blib' , $targetdir , @$dest_path , $file ) ;
#print "$source => $destination\n"; # DEBUG
$file_map ->{ $source } = $destination ;
}
}
= h e a d 2 u n h a s h d i r
T h i s f u n c t i o n u n h a s h e s t h e h a s h o f h a s h e s g e n e r a t e d b y h a s h d i r ( ) .
@ -423,7 +594,7 @@ sub unhashdir{
$dirlevel = $toplevel ;
}
elsif ( $k1 eq '.' ) {
foreach $file ( @{ $dirhash ->{ $k1 } } ) {
foreach my $file ( @{ $dirhash ->{ $k1 } } ) {
# TODO: There are some hacks here that may be able to be improved... -fbcit
if ( $file = ~ /^./ ) { next; } # skip hidden files and directories.
@ -515,6 +686,7 @@ component of the directory path, which will be used
a s t h e p a c k a g e n a m e i n t h e F H S l a y o u t . ) ;
}
$config { 'INSTALL_BASE' } = _get_value( 'INSTALL_BASE' , $msg , $install_base_default , $valid_values ) ;
$config { 'INSTALL_BASE' } = File::Spec->rel2abs( $config { 'INSTALL_BASE' } ) ;
$msg = q(
K o h a c a n u s e t h e Z e b r a s e a r c h e n g i n e f o r h i g h - p e r f o r m a n c e
@ -599,7 +771,6 @@ sub get_target_directories {
my %dirmap = ( ) ;
if ( $mode eq 'single' ) {
# mode is standard, i.e., 'fhs'
$dirmap { 'INTRANET_CGI_DIR' } = File::Spec->catdir( @basedir, $package , 'intranet' , 'cgi-bin' ) ;
$dirmap { 'INTRANET_TMPL_DIR' } = File::Spec->catdir( @basedir, $package , 'intranet' , 'templates' ) ;
$dirmap { 'INTRANET_WWW_DIR' } = File::Spec->catdir( @basedir, $package , 'intranet' , 'www' ) ;
@ -616,6 +787,7 @@ sub get_target_directories {
$dirmap { 'ZEBRA_LOCK_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'lock' , 'zebradb' ) ;
$dirmap { 'LOG_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'log' ) ;
$dirmap { 'ZEBRA_DATA_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'lib' , 'zebradb' ) ;
$dirmap { 'ZEBRA_RUN_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'run' , 'zebradb' ) ;
} elsif ( $mode eq 'dev' ) {
my $curdir = File::Spec->rel2abs( File::Spec->curdir( ) ) ;
$dirmap { 'INTRANET_CGI_DIR' } = File::Spec->catdir( $curdir ) ;
@ -634,6 +806,7 @@ sub get_target_directories {
$dirmap { 'ZEBRA_LOCK_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'lock' , 'zebradb' ) ;
$dirmap { 'LOG_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'log' ) ;
$dirmap { 'ZEBRA_DATA_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'lib' , 'zebradb' ) ;
$dirmap { 'ZEBRA_RUN_DIR' } = File::Spec->catdir( @basedir, $package , 'var' , 'run' , 'zebradb' ) ;
} else {
# mode is standard, i.e., 'fhs'
$dirmap { 'INTRANET_CGI_DIR' } = File::Spec->catdir( @basedir, $package , 'intranet' , 'cgi-bin' ) ;
@ -652,6 +825,7 @@ sub get_target_directories {
$dirmap { 'ZEBRA_LOCK_DIR' } = File::Spec->catdir( File::Spec->rootdir( ) , 'var' , 'lock' , $package , 'zebradb' ) ;
$dirmap { 'LOG_DIR' } = File::Spec->catdir( File::Spec->rootdir( ) , 'var' , 'log' , $package ) ;
$dirmap { 'ZEBRA_DATA_DIR' } = File::Spec->catdir( File::Spec->rootdir( ) , 'var' , 'lib' , $package , 'zebradb' ) ;
$dirmap { 'ZEBRA_RUN_DIR' } = File::Spec->catdir( File::Spec->rootdir( ) , 'var' , 'run' , $package , 'zebradb' ) ;
}
foreach my $key ( sort keys %dirmap) {
@ -660,11 +834,42 @@ sub get_target_directories {
return %dirmap;
}
#package MY;
#sub install {
#warn "\n\n\noverride\n\n\n";
#return "";
#}
p a c k a g e M Y ;
s u b i n s t a l l {
my $self = shift;
my $install = "" ;
# NOTE: we're *not* doing this: my $install = $self->SUPER::install(@_);
# This means that we're completely overriding EU::MM's default
# installation and uninstallation targets.
foreach my $key ( sort keys %target_directories) {
$install .= qq(
KOHA_INST_$key = blib/$key
KOHA_DEST_$key = $target_directories { $key }
) ;
}
$install .= qq(
install :: all install_koha
\ t \ $( NOECHO ) \ $( NOOP )
) ;
$install .= "install_koha ::\n" ;
$install .= "\t\$(NOECHO) umask 022; \$(MOD_INSTALL) \\\n" ;
foreach my $key ( sort keys %target_directories) {
$install .= " \t\t\$(KOHA_INST_ $key ) \$(KOHA_DEST_ $key ) \\\n " ;
}
$install .= "\t\t\$(INST_MAN1DIR) \$(DESTINSTALLMAN1DIR) \\\n" ;
$install .= "\t\t\$(INST_MAN3DIR) \$(DESTINSTALLMAN3DIR)\n" ;
return $install ;
}
s u b p o s t a m b l e {
# put directory mappings into Makefile
# so that Make will export as environment
# variables -- this is for the use of
# rewrite-confg.PL
my $env = join( "\n" , map { " export __ ${ _ } __ = $target_directories { $_ } " } keys %target_directories) ;
return " $env \n " ;
}
_ _ E N D _ _
@ -678,4 +883,6 @@ ExtUtils::MakeMaker(3)
M J R a y m j r a t p h o n e c o o p . c o o p
= c u t
FIXME : deal with files that have spaces in names
FIXME : Zebra lang /MARC mapping
FIXME : deal with .htaccess