Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Mojo::Home is now a subclass of Mojo::File
  • Loading branch information
kraih committed Jan 8, 2017
1 parent 674526e commit f67d11c
Show file tree
Hide file tree
Showing 19 changed files with 79 additions and 113 deletions.
4 changes: 2 additions & 2 deletions lib/Mojo.pm
Expand Up @@ -78,8 +78,8 @@ L<Mojo> implements the following attributes.
The home directory of your application, defaults to a L<Mojo::Home> object
which stringifies to the actual path.
# Generate portable path relative to home directory
my $path = $app->home->rel_file('data/important.txt');
# Portably generate path relative to home directory
my $path = $app->home->child('data', 'important.txt');
=head2 log
Expand Down
107 changes: 36 additions & 71 deletions lib/Mojo/Home.pm
@@ -1,61 +1,68 @@
package Mojo::Home;
use Mojo::Base -base;
use overload bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
use Mojo::Base 'Mojo::File';

use Mojo::File 'path';
use Mojo::Util qw(class_to_path deprecated);

has parts => sub { [] };

sub detect {
my ($self, $class) = @_;

# Environment variable
return $self->parts(path($ENV{MOJO_HOME})->to_abs->to_array)
if $ENV{MOJO_HOME};
my $detected;
if ($ENV{MOJO_HOME}) { $detected = Mojo::File::path($ENV{MOJO_HOME})->to_abs }

This comment has been minimized.

Copy link
@jhthorsen

jhthorsen Jan 8, 2017

Member

Why not Mojo::File->new or $self->new ? (Same a couple of lines lower down)

This comment has been minimized.

Copy link
@kraih

kraih Jan 8, 2017

Author Member

Changed it.


# Location of the application class
if ($class && (my $path = $INC{my $file = class_to_path $class})) {
elsif ($class && (my $path = $INC{my $file = class_to_path $class})) {
$path =~ s/(?:\/b?lib)?\/\Q$file\E$//;
return $self->parts(path($path)->to_abs->to_array);
$detected = Mojo::File::path($path)->to_abs;
}

# Current working directory
return $self->parts(path->to_array);
$$self = $detected->to_string if $detected;
return $self;
}

# DEPRECATED!
sub lib_dir {
deprecated 'Mojo::Home::lib_dir is DEPRECATED';
path(@{shift->parts}, 'lib')->to_string;
shift->child('lib')->to_string;
}

# DEPRECATED!
sub list_files {
deprecated
'Mojo::Home::list_files is DEPRECATED in favor of Mojo::Util::files';
my ($self, $dir, $options) = (shift, shift // '', shift);
my $base = path(@{$self->parts}, split('/', $dir));
my $base = $self->child(split('/', $dir));
$base->list_tree($options)->map(sub { join '/', @{$_->to_rel($base)} })
->to_array;
}

sub mojo_lib_dir { path(__FILE__)->dirname->child('..')->to_string }
sub mojo_lib_dir { shift->new(__FILE__)->dirname->child('..') }

sub new { @_ > 1 ? shift->SUPER::new->parse(@_) : shift->SUPER::new }
# DEPRECATED!
sub parse {
deprecated 'Mojo::Home::parse is DEPRECATED';
my $self = shift;
$$self = shift;
return $self;
}

sub parse { shift->parts(path(shift)->to_array) }
# DEPRECATED!
sub parts {
deprecated 'Mojo::Home::parts is DEPRECATED';
my $self = shift;
return $self->to_array unless @_;
$$self = Mojo::File::path(@{shift()})->to_string;
return $self;
}

# DEPRECATED!
sub rel_dir {
deprecated
'Mojo::Home::rel_dir is DEPRECATED in favor of Mojo::Home::rel_file';
path(@{shift->parts}, split('/', shift))->to_string;
Mojo::File::path(@{shift->parts}, split('/', shift))->to_string;
}

sub rel_file { path(@{shift->parts}, split('/', shift))->to_string }

sub to_string { path(@{shift->parts})->to_string }
sub rel_file { shift->child(split('/', shift)) }

1;

Expand All @@ -72,84 +79,42 @@ Mojo::Home - Home sweet home
# Find and manage the project root directory
my $home = Mojo::Home->new;
$home->detect;
say $home->rel_file('templates/layouts/default.html.ep');
say $home->child('templates', 'layouts', 'default.html.ep');
say "$home";
=head1 DESCRIPTION
L<Mojo::Home> is a container for home directories.
=head1 ATTRIBUTES
L<Mojo::Home> implements the following attributes.
=head2 parts
my $parts = $home->parts;
$home = $home->parts(['', 'home', 'sri', 'myapp']);
Home directory parts.
L<Mojo::Home> is a container for home directories based on L<Mojo::File>.
=head1 METHODS
L<Mojo::Home> inherits all methods from L<Mojo::Base> and implements the
L<Mojo::Home> inherits all methods from L<Mojo::File> and implements the
following new ones.
=head2 detect
$home = $home->detect;
$home = $home->detect('My::App');
Detect home directory from the value of the C<MOJO_HOME> environment variable,
location of the application class, or the current working directory.
Detect home directory from the value of the C<MOJO_HOME> environment variable or
the location of the application class.
=head2 mojo_lib_dir
my $path = $home->mojo_lib_dir;
Path to C<lib> directory in which L<Mojolicious> is installed.
=head2 new
my $home = Mojo::Home->new;
my $home = Mojo::Home->new('/home/sri/my_app');
Construct a new L<Mojo::Home> object and L</"parse"> home directory if
necessary.
=head2 parse
$home = $home->parse('/home/sri/my_app');
Parse home directory.
Path to C<lib> directory in which L<Mojolicious> is installed as a L<Mojo::Home>
object.
=head2 rel_file
my $path = $home->rel_file('foo/bar.html');
Portably generate an absolute path relative to the home directory.
=head2 to_string
my $str = $home->to_string;
Home directory.
Return a new L<Mojo::Home> object relative to the home directory.
=head1 OPERATORS
L<Mojo::Home> overloads the following operators.
=head2 bool
my $bool = !!$home;
Always true.
=head2 stringify
my $str = "$home";
Alias for L</"to_string">.
L<Mojo::Home> inherits all overloaded operators from L<Mojo::File>.
=head1 SEE ALSO
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojolicious.pm
Expand Up @@ -31,8 +31,8 @@ has log => sub {
my $log = Mojo::Log->new;
my $home = $self->home;
my $mode = $self->mode;
$log->path($home->rel_file("log/$mode.log"))
if -d $home->rel_file('log') && -w _;
$log->path($home->child('log', "$mode.log"))
if -d $home->child('log') && -w _;

# Reduced log output outside of development mode
return $mode eq 'development' ? $log : $log->level('info');
Expand Down Expand Up @@ -152,8 +152,8 @@ sub new {
my $self = shift->SUPER::new(@_);

my $home = $self->home;
push @{$self->renderer->paths}, $home->rel_file('templates');
push @{$self->static->paths}, $home->rel_file('public');
push @{$self->renderer->paths}, $home->child('templates');
push @{$self->static->paths}, $home->child('public');

# Default to controller and application namespace
my $r = $self->routes->namespaces(["@{[ref $self]}::Controller", ref $self]);
Expand Down
10 changes: 5 additions & 5 deletions lib/Mojolicious/Command/test.pm
@@ -1,7 +1,7 @@
package Mojolicious::Command::test;
use Mojo::Base 'Mojolicious::Command';

use Mojo::Util qw(files getopt);
use Mojo::Util 'getopt';

has description => 'Run tests';
has usage => sub { shift->extract_usage };
Expand All @@ -11,10 +11,10 @@ sub run {

getopt \@args, 'v|verbose' => \$ENV{HARNESS_VERBOSE};

if (!@args && (my $home = $self->app->home)) {
die "Can't find test directory.\n" unless -d $home->rel_file('t');
/\.t$/ and push @args, $_ for files $home->rel_file('t');
say qq{Running tests from "}, $home->rel_file('t') . '".';
if (!@args && (my $tests = $self->app->home->child('t'))) {
die "Can't find test directory.\n" unless -d $tests;
/\.t$/ and push @args, $_ for $tests->list_tree->each;
say qq{Running tests from "$tests".};
}

$ENV{HARNESS_OPTIONS} //= 'c';
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Controller.pm
Expand Up @@ -402,7 +402,7 @@ a L<Mojolicious> object.
$c->app->log->debug('Hello Mojo');
# Generate path
my $path = $c->app->home->rel_file('templates/foo/bar.html.ep');
my $path = $c->app->home->child('templates', 'foo', 'bar.html.ep');
=head2 match
Expand Down
8 changes: 6 additions & 2 deletions lib/Mojolicious/Guides.pod
Expand Up @@ -321,8 +321,6 @@ This is the class hierarchy of the L<Mojolicious> distribution.

=item * L<Mojo::Headers>

=item * L<Mojo::Home>

=item * L<Mojo::IOLoop::Subprocess>

=item * L<Mojo::JSON::Pointer>
Expand Down Expand Up @@ -463,6 +461,12 @@ This is the class hierarchy of the L<Mojolicious> distribution.

=item * L<Mojo::File>

=over 2

=item * L<Mojo::Home>

=back

=item * L<Mojo::JSON>

=item * L<Mojo::Loader>
Expand Down
7 changes: 4 additions & 3 deletions lib/Mojolicious/Guides/Cookbook.pod
Expand Up @@ -1544,6 +1544,7 @@ automatically installed with the modules.
use Mojo::Base 'Mojolicious';

use Mojo::File 'path';
use Mojo::Home;

# Every CPAN module needs a version
our $VERSION = '1.0';
Expand All @@ -1552,13 +1553,13 @@ automatically installed with the modules.
my $self = shift;

# Switch to installable home directory
$self->home->parse(path(__FILE__)->dirname->child('MyApp')->to_string);
$self->home(Mojo::Home->new(path(__FILE__)->dirname->child('MyApp')));

# Switch to installable "public" directory
$self->static->paths->[0] = $self->home->rel_file('public');
$self->static->paths->[0] = $self->home->child('public');

# Switch to installable "templates" directory
$self->renderer->paths->[0] = $self->home->rel_file('templates');
$self->renderer->paths->[0] = $self->home->child('templates');

$self->plugin('PODRenderer');

Expand Down
6 changes: 3 additions & 3 deletions lib/Mojolicious/Plugin/Config.pm
Expand Up @@ -30,8 +30,8 @@ sub register {
my $mode = $file =~ /^(.*)\.([^.]+)$/ ? join('.', $1, $app->mode, $2) : '';

my $home = $app->home;
$file = $home->rel_file($file) unless path($file)->is_abs;
$mode = $home->rel_file($mode) if $mode && !path($mode)->is_abs;
$file = $home->child($file) unless path($file)->is_abs;
$mode = $home->child($mode) if $mode && !path($mode)->is_abs;
$mode = undef unless $mode && -e $mode;

# Read config file
Expand Down Expand Up @@ -68,7 +68,7 @@ Mojolicious::Plugin::Config - Perl-ish configuration plugin
baz => ['♥'],
# You have full access to the application
music_dir => app->home->rel_file('music')
music_dir => app->home->child('music')
};
# Mojolicious
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Plugin/JSONConfig.pm
Expand Up @@ -48,7 +48,7 @@ Mojolicious::Plugin::JSONConfig - JSON configuration plugin
"baz": ["♥"],
%# You have full access to the application
"music_dir": "<%= app->home->rel_file('music') %>"
"music_dir": "<%= app->home->child('music') %>"
}
# Mojolicious
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Renderer.pm
Expand Up @@ -18,7 +18,7 @@ has paths => sub { [] };

# Bundled templates
my $TEMPLATES = Mojo::Home->new(Mojo::Home->new->mojo_lib_dir)
->rel_file('Mojolicious/resources/templates');
->child('Mojolicious', 'resources', 'templates');

sub DESTROY { Mojo::Util::_teardown($_) for @{shift->{namespaces}} }

Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Static.pm
Expand Up @@ -14,7 +14,7 @@ has paths => sub { [] };

# Bundled files
my $PUBLIC = Mojo::Home->new(Mojo::Home->new->mojo_lib_dir)
->rel_file('Mojolicious/resources/public');
->child('Mojolicious', 'resources', 'public');

sub dispatch {
my ($self, $c) = @_;
Expand Down
2 changes: 1 addition & 1 deletion t/mojo/daemon.t
Expand Up @@ -64,7 +64,7 @@ is $tx->res->body, 'Hello TestApp!', 'right content';

# Optional home detection
my @path = qw(th is mojo dir wil l never-ever exist);
my $app = Mojo->new(home => Mojo::Home->new(path(@path)));
my $app = Mojo->new(home => Mojo::Home->new(@path));
is $app->home, path(@path), 'right home directory';

# Config
Expand Down
15 changes: 5 additions & 10 deletions t/mojo/home.t
Expand Up @@ -13,41 +13,36 @@ use Mojo::Home;
my $fake = path->to_abs->child('does_not_exist');
local $ENV{MOJO_HOME} = $fake->to_string;
my $home = Mojo::Home->new->detect;
is_deeply path($home->to_string)->to_abs->to_array, $fake->to_array,
'right path detected';
is_deeply $home->to_array, $fake->to_array, 'right path detected';
}

# Specific class detection
{
my $fake = path->to_abs->child('does_not_exist_2');
local $INC{'My/Class.pm'} = $fake->child('My', 'Class.pm');
my $home = Mojo::Home->new->detect('My::Class');
is_deeply path($home->to_string)->to_abs->to_array, $fake->to_array,
'right path detected';
is_deeply $home->to_array, $fake->to_array, 'right path detected';
}

# Specific class detection (with "lib")
{
my $fake = path->to_abs->child('does_not_exist_3');
local $INC{'My/Class.pm'} = $fake->child('lib', 'My', 'Class.pm');
my $home = Mojo::Home->new->detect('My::Class');
is_deeply path($home->to_string)->to_abs->to_array, $fake->to_array,
'right path detected';
is_deeply $home->to_array, $fake->to_array, 'right path detected';
}

# Specific class detection (with "blib")
{
my $fake = path->to_abs->child('does_not_exist_3');
local $INC{'My/Class.pm'} = $fake->child('blib', 'My', 'Class.pm');
my $home = Mojo::Home->new->detect('My::Class');
is_deeply path($home->to_string)->to_abs->to_array, $fake->to_array,
'right path detected';
is_deeply $home->to_array, $fake->to_array, 'right path detected';
}

# Current working directory
my $home = Mojo::Home->new->detect;
is_deeply path($home->to_string)->to_array, path->to_abs->to_array,
'right path detected';
is_deeply $home->to_array, path->to_abs->to_array, 'right path detected';

# Path generation
$home = Mojo::Home->new($FindBin::Bin);
Expand Down

0 comments on commit f67d11c

Please sign in to comment.