Catalyst-Controller-AutoAssets
view release on metacpan or search on metacpan
lib/Catalyst/Controller/AutoAssets/Handler.pm view on Meta::CPAN
sub file_checksum {
my $self = shift;
my $files = ref $_[0] eq 'ARRAY' ? $_[0] : \@_;
my $Sha1 = Digest::SHA1->new;
foreach my $file ( grep { -f $_ } @$files ) {
my $fh = $file->openr or die "$! : $file\n";
binmode $fh;
$Sha1->addfile($fh);
$fh->close;
}
return substr $Sha1->hexdigest, 0, $self->sha1_string_length;
}
sub asset_name { (shift)->current_fingerprint }
sub base_path {
my $self = shift;
my $pfx = try{RapidApp->active_request_context->mount_url} || '';
return join('/',$pfx,$self->action_namespace($self->_app));
}
# this is just used for some internal optimization to avoid calling stat
# duplicate times. It is basically me being lazy, adding an internal extra param
# to asset_path() without changing its public API/arg list
has '_asset_path_skip_prepare', is => 'rw', isa => 'Bool', default => 0;
before asset_path => sub {
my $self = shift;
$self->prepare_asset(@_) unless ($self->_asset_path_skip_prepare);
};
sub asset_path {
my $self = shift;
return $self->base_path . '/' . $self->asset_name;
}
sub html_head_tags { undef }
# This locks a file or dies trying, and on success, returns a "lock object"
# which will release the lock if it goes out of scope. At the moment, this
# "object" is just a file handle.
#
# This lock is specifically *not* inherited by child processes (thanks to
# fcntl(FL_CLOEXEC), and in fact, this design principle gives it
# cross-platform compatibility that most lock module sdon't have.
#
sub _get_lock {
my ($self, $fname, $timeout)= @_;
my $fh;
sysopen($fh, $fname, O_RDWR|O_CREAT|O_EXCL, 0644)
or sysopen($fh, $fname, O_RDWR)
or croak "Unable to create or open $fname";
try { fcntl($fh, F_SETFD, FD_CLOEXEC) }
or carp "Failed to set close-on-exec for $fname (see BUGS in Catalyst::Controller::AutoAssets)";
# Try to get lock until timeout. We poll because there isn't a sensible
# way to wait for the lock. (I don't consider SIGALRM to be very sensible)
my $deadline= Time::HiRes::time() + $timeout;
my $locked= 0;
while (1) {
last if flock($fh, LOCK_EX|LOCK_NB);
croak "Can't get lock on $fname after $timeout seconds" if Time::HiRes::time() >= $deadline;
Time::HiRes::sleep(0.4);
}
# Succeeded in getting the lock, so write our pid.
my $data= "$$";
syswrite($fh, $data, length($data)) or croak "Failed to write pid to $fname";
truncate($fh, length($data)) or croak "Failed to resize $fname";
return $fh;
}
1;
__END__
=pod
=head1 NAME
Catalyst::Controller::AutoAssets::Handler - Handler type Role and default namespace
=head1 DESCRIPTION
This is the base Role for C<Catalyst::Controller::AutoAssets> Handler classes and is
where the majority of the work is done for the AutoAssets module. The Handler class is
specified in the 'type' config param and is relative to this namespace. Absolute class
names can also be specified with the '+' prefix, so the following are equivalent:
type => 'Directory'
type => '+Catalyst::Controller::AutoAssets::Handler::Directory'
Custom Handler classes can be written and used as long as they consume this Role. For examples
of how to write custom Handlers, see the existing Handlers below for reference.
=head1 TYPE HANDLERS
These are the current built in handler classes:
=over
=item L<Catalyst::Controller::AutoAssets::Handler::Directory>
=item L<Catalyst::Controller::AutoAssets::Handler::CSS>
=item L<Catalyst::Controller::AutoAssets::Handler::JS>
=item L<Catalyst::Controller::AutoAssets::Handler::ImageSet>
=item L<Catalyst::Controller::AutoAssets::Handler::IconSet>
=back
=head1 AUTHOR
Henry Van Styn <vanstyn@cpan.org>
( run in 1.531 second using v1.01-cache-2.11-cpan-13bb782fe5a )