X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FUtils.pm;h=dae3439adbc32bbabc20db027de10e9d259d2a22;hb=488736aa8f612ac5f963a9c9f4794286525a335a;hp=3a0974b2088c414aa43cdab0cdb873e3fea8efd7;hpb=a88c7ec8a3a92fdf966dce0026d06082a10c7714;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Utils.pm b/lib/Catalyst/Utils.pm index 3a0974b..dae3439 100644 --- a/lib/Catalyst/Utils.pm +++ b/lib/Catalyst/Utils.pm @@ -6,6 +6,7 @@ use File::Spec; use HTTP::Request; use Path::Class; use URI; +use Class::Inspector; =head1 NAME @@ -147,30 +148,41 @@ Returns home directory for given class. =cut sub home { - my $name = shift; - $name =~ s/\:\:/\//g; - my $home = 0; - if ( my $path = $INC{"$name.pm"} ) { - $home = file($path)->absolute->dir; - $name =~ /(\w+)$/; - my $append = $1; - my $subdir = dir($home)->subdir($append); - for ( split '/', $name ) { $home = dir($home)->parent } - if ( $home =~ /blib$/ ) { $home = dir($home)->parent } - elsif (!-f file( $home, 'Makefile.PL' ) - && !-f file( $home, 'Build.PL' ) ) + my $class = shift; + + # make an $INC{ $key } style string from the class name + (my $file = "$class.pm") =~ s{::}{/}g; + + if ( my $inc_entry = $INC{$file} ) { { - $home = $subdir; + # look for an uninstalled Catalyst app + + # find the @INC entry in which $file was found + (my $path = $inc_entry) =~ s/$file$//; + my $home = dir($path)->absolute->cleanup; + + # pop off /lib and /blib if they're there + $home = $home->parent while $home =~ /b?lib$/; + + # only return the dir if it has a Makefile.PL or Build.PL + return $home->stringify + if $home->file("Makefile.PL") or -f $home->file("Build.PL"); } - # clean up relative path: - # MyApp/script/.. -> MyApp - my ($lastdir) = $home->dir_list( -1, 1 ); - if ( $lastdir eq '..' ) { - $home = dir($home)->parent->parent; + { + # look for an installed Catalyst app + + # trim the .pm off the thing ( Foo/Bar.pm -> Foo/Bar/ ) + ( my $path = $inc_entry) =~ s/\.pm$//; + my $home = dir($path)->absolute->cleanup; + + # return if if it's a valid directory + return $home->stringify if -d $home; } } - return $home; + + # we found nothing + return 0; } =head2 prefix($class, $name); @@ -210,9 +222,65 @@ sub request { return $request; } +=head2 ensure_class_loaded($class_name) + +Loads the class unless it already has been loaded. + +=cut + +sub ensure_class_loaded { + my $class = shift; + + return if Class::Inspector->loaded( $class ); # if a symbol entry exists we don't load again + + # this hack is so we don't overwrite $@ if the load did not generate an error + my $error; + { + local $@; + eval "require $class"; + $error = $@; + } + + die $error if $error; + die "require $class was successful but the package is not defined" + unless Class::Inspector->loaded($class); + + return 1; +} + +=head2 merge_hashes($hashref, $hashref) + +Base code to recursively merge two hashes together with right-hand precedence. + +=cut + +sub merge_hashes { + my ( $lefthash, $righthash ) = @_; + + return $lefthash unless defined $righthash; + + my %merged = %$lefthash; + for my $key ( keys %$righthash ) { + my $right_ref = ( ref $righthash->{ $key } || '' ) eq 'HASH'; + my $left_ref = ( ( exists $lefthash->{ $key } && ref $lefthash->{ $key } ) || '' ) eq 'HASH'; + if( $right_ref and $left_ref ) { + $merged{ $key } = merge_hashes( + $lefthash->{ $key }, $righthash->{ $key } + ); + } + else { + $merged{ $key } = $righthash->{ $key }; + } + } + + return \%merged; +} + + =head1 AUTHOR Sebastian Riedel, C +Yuval Kogman, C =head1 COPYRIGHT