Template-Resolver
view release on metacpan or search on metacpan
151617181920212223242526272829303132333435363738394041424344454647484950515253541.12 2016-07-23
- Added option
for
supplying additional transforms to the resolver constructor
1.11 2016-07-01
- Removed double slash from path in destination file
1.10 2016-07-01
- Added the ability to supply a resolver to the overlay method to
augment
the
default
behavior
1.09 2016-03-31
- Remove file
if
it
exists
before
processing template to ensure proper
permissions are propagated.
1.08 2016-03-31
- Added O_TRUNC to
sysopen
to ensure file is truncated
if
it already
exists
during template resolution.
1.07 2016-03-31
files, both base and template, augmented by the current
umask
.
1.06 2016-03-23
- Fixed: Overlay fails
if
template is in a directory that does not exist in base
1.05 2016-01-25
- Added overlays
1.04 2016-01-23
- Add support
for
any blessed entity to be treated as
if
it were a hashref
1.03 2016-01-22
- Added support
for
multi-line placeholder
1.02 2015-12-05
- Fixed deprecated regex syntax
12131415161718192021222324lib/Template/Resolver.pm
lib/Template/Transformer.pm
t/Overlay.t
t/Resolver.t
t/author-critic.t
t/author-pod-coverage.t
t/author-pod-syntax.t
t/base/a.txt
t/base/c.txt
t/base/subdir/b.txt
t/overlay1/subdir/b.txt
t/overlay2/a.txt
weaver.ini
lib/Template/Overlay.pm view on Meta::CPAN
212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
return
bless
( {},
shift
)->_init(
@_
);
}
sub
_init {
my
(
$self
,
$base
,
$resolver
,
%options
) =
@_
;
$self
->{base} = File::Spec->rel2abs(
$base
);
$self
->{resolver} =
$resolver
;
$self
->{key} =
$options
{key};
$logger
->debug(
'new overlay ['
,
$self
->{base},
']'
);
return
$self
;
}
sub
_overlay_files {
my
(
$self
,
$overlays
) =
@_
;
my
%overlay_files
= ();
foreach
my
$overlay
(
ref
(
$overlays
) eq
'ARRAY'
?
@$overlays
: (
$overlays
) ) {
$overlay
= File::Spec->rel2abs(
$overlay
);
my
$base_path_length
=
length
(
$overlay
);
find(
sub
{
if
( -f
$File::Find::name
&&
$_
!~ /~$/ &&
$_
!~ /^\..+\.swp$/ ) {
my
$relative
= _relative_path(
$File::Find::name
,
$base_path_length
);
$overlay_files
{
$relative
} =
$File::Find::name
;
}
},
$overlay
);
}
return
%overlay_files
;
}
sub
overlay {
my
(
$self
,
$overlays
,
%options
) =
@_
;
my
%overlay_files
=
$self
->_overlay_files(
$overlays
);
my
$destination
=
$self
->{base};
if
(
$options
{to} &&
$options
{to} ne
$self
->{base} ) {
$destination
= File::Spec->rel2abs(
$options
{to} );
my
$base_path_length
=
length
( File::Spec->rel2abs(
$self
->{base} ) );
find(
sub
{
my
$relative
= _relative_path(
$File::Find::name
,
$base_path_length
);
if
( -d
$File::Find::name
) {
make_path( File::Spec->catdir(
$destination
,
$relative
) );
}
if
( -f
$File::Find::name
) {
my
$template
=
delete
(
$overlay_files
{
$relative
} );
my
$file
= File::Spec->catfile(
$destination
,
$relative
);
if
(
$template
) {
$self
->_resolve(
$template
,
$file
,
$options
{resolver} );
}
else
{
copy(
$_
,
$file
);
}
}
},
$self
->{base}
);
}
foreach
my
$relative
(
keys
(
%overlay_files
) ) {
my
$file
= File::Spec->catfile(
$destination
,
$relative
);
make_path( ( File::Spec->splitpath(
$file
) )[1] );
$self
->_resolve(
$overlay_files
{
$relative
},
$file
,
$options
{resolver} );
}
}
sub
_relative_path {
my
(
$path
,
$base_path_length
) =
@_
;
return
length
(
$path
) ==
$base_path_length
?
''
:
substr
(
$File::Find::name
,
$base_path_length
+ 1 );
}
lib/Template/Overlay.pm view on Meta::CPAN
136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206=head1 VERSION
version 1.16
=head1 SYNOPSIS
use Template::Overlay;
use Template::Resolver;
my $overlay_me = Template::Overlay->new(
'/path/to/base/folder',
Template->Resolver->new($entity),
key => 'REPLACEME');
$overlay_me->overlay(
['/path/to/template/base','/path/to/another/template/base'],
to => '/path/to/processed');
=head1 DESCRIPTION
This provides the ability ot overlay a set of files with a set of resolved templates.
It uses L<Template::Resolver> to resolve each file.
=head1 CONSTRUCTORS
=head2 new($base, $resolver, [%options])
Creates a new overlay processor for the files in C<$base> using C<$resolver> to process
the template files. The available options are:
=over 4
=item key
The template key used by C<Template::Resolver-E<lt>resolve>.
=back
=head1 METHODS
=head2 overlay($overlays, [%options])
Overlays the C<$base> directory (specified in the constructor) with the resolved
templates from the directories in C<$overlays>. C<$overlays> can be either a path,
or an array reference containing paths. If multiple C<$overlays> contain the same
template, the last one in the array will take precedence. The available options are:
=over 4
=item resolver
A callback, that if specified, will be called for each template file found. It will
be called with two arguments: the first is the path to the template file, the second
is the path to the destination file. If the callback returns a I<falsey> value,
then it is assumed that the supplied callbac decided not to process this file and
processing will proceed as normal. Otherwise, it is assumed that the callback
handled processing of the file, so the default processing will be skipped.
=item to
If specified, the files in C<$base> will not be not be modified. Rather, they will
be copied to the path specified by C<$to> and the overlays will be processed on top
of that directory.
=back
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
t/Overlay.t view on Meta::CPAN
1516171819202122232425262728293031323334353637383940414243my
$test_dir
= dirname( File::Spec->rel2abs($0) );
sub
test_dir {
return
File::Spec->catdir(
$test_dir
,
@_
);
}
sub
test_file {
return
File::Spec->catfile(
$test_dir
,
@_
);
}
sub
overlay {
my
(
$config
,
$overlays
,
$no_base
,
%options
) =
@_
;
my
$dir
= File::Temp->newdir();
#returns object
Template::Overlay->new(
$no_base
?
$dir
->dirname() : test_dir(
'base'
),
Template::Resolver->new(
$config
),
key
=>
'T'
)->overlay(
$overlays
,
to
=>
$dir
->dirname(),
%options
);
my
%results
= ();
find(
sub
{
if
( -f
$File::Find::name
&&
$File::Find::name
=~ /^\Q
$dir
\E\/(.*)$/ ) {
$results
{$1} =
do
{
local
(
@ARGV
, $/ ) =
$_
; <> };
}
},
$dir
);
return
\
%results
;
t/Overlay.t view on Meta::CPAN
54555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191sub
slurp {
my
(
$file
) =
@_
;
return
do
{
local
(
@ARGV
, $/ ) =
$file
; <> };
}
my
$config
= {
what
=> {
this
=> {
'is'
=>
'im not sure'
} },
todays
=> {
random
=> {
thought
=>
'something awesome'
} }
};
my
$results
= overlay(
$config
, test_dir(
'overlay1'
) );
like(
$results
->{
'a.txt'
},
qr/This is a test\.(?:\r|\n|\r\n)/
,
'overlay1 a.txt'
);
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: something awesome(?:\r|\n|\r\n)/
,
'overlay1 subdir/b.txt'
);
like(
$results
->{
'c.txt'
},
qr/Another file full of nonsense\.(?:\r|\n|\r\n)/
,
'overlay1 c.txt'
);
$config
= {
what
=> {
this
=> {
'is'
=>
'im not sure'
} },
todays
=> {
random
=> {
thought
=>
'something awesome'
} }
};
$results
= overlay(
$config
, test_dir(
'overlay2'
) );
like(
$results
->{
'a.txt'
},
qr/This is a im not sure\.(?:\r|\n|\r\n)/
,
'overlay2 a.txt'
);
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: fumanchu\.(?:\r|\n|\r\n)/
,
'overlay2 subdir/b.txt'
);
like(
$results
->{
'c.txt'
},
qr/Another file full of nonsense\.(?:\r|\n|\r\n)/
,
'overlay2 c.txt'
);
$config
= {
what
=> {
this
=> {
'is'
=>
'im not sure'
} },
todays
=> {
random
=> {
thought
=>
'something awesome'
} }
};
$results
= overlay(
$config
, [ test_dir(
'overlay1'
), test_dir(
'overlay2'
) ] );
like(
$results
->{
'a.txt'
},
qr/This is a im not sure\.(?:\r|\n|\r\n)/
,
'overlay1,overlay2 a.txt'
);
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: something awesome(?:\r|\n|\r\n)/
,
'overlay1,overlay2 subdir/b.txt'
);
like(
$results
->{
'c.txt'
},
qr/Another file full of nonsense\.(?:\r|\n|\r\n)/
,
'overlay1,overlay2 c.txt'
);
$config
= {
what
=> {
this
=> {
'is'
=>
'im not sure'
} },
todays
=> {
random
=> {
thought
=>
'something awesome'
} }
};
$results
= overlay(
$config
, [ test_dir(
'overlay2'
), test_dir(
'overlay1'
) ] );
like(
$results
->{
'a.txt'
},
qr/This is a im not sure\.(?:\r|\n|\r\n)/
,
'overlay2,overlay1 a.txt'
);
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: something awesome(?:\r|\n|\r\n)/
,
'overlay2,overlay1 subdir/b.txt'
);
like(
$results
->{
'c.txt'
},
qr/Another file full of nonsense\.(?:\r|\n|\r\n)/
,
'overlay2,overlay1 c.txt'
);
$results
= overlay(
$config
, test_dir(
'overlay1'
), 1 );
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: something awesome(?:\r|\n|\r\n)/
,
'overlay1 subdir/b.txt no base'
);
{
my
$callback_called
;
$results
= overlay(
$config
,
test_dir(
'overlay1'
),
1,
resolver
=>
sub
{
my
(
$template
,
$file
) =
@_
;
$callback_called
= 1;
spurt(
"foo"
,
$file
);
return
1;
}
);
ok(
$callback_called
,
'callback called, processing stopped'
);
is(
$results
->{
'subdir/b.txt'
},
'foo'
,
'callback overlay1 subdir/b.txt no base'
);
$callback_called
= 0;
$results
= overlay(
$config
,
test_dir(
'overlay1'
),
1,
resolver
=>
sub
{
my
(
$template
,
$file
) =
@_
;
$callback_called
= 1;
return
0;
}
);
ok(
$callback_called
,
'callback called, processing proceeded'
);
like(
$results
->{
'subdir/b.txt'
},
qr/Random thought for today is: something awesome(?:\r|\n|\r\n)/
,
'callback override overlay1 subdir/b.txt no base'
);
}
{
my
$temp_dir
= File::Temp->newdir();
my
$base_dir
= File::Spec->catdir(
$temp_dir
,
'base'
);
mkdir
(
$base_dir
);
my
$template_dir
= File::Spec->catdir(
$temp_dir
,
'template'
);
mkdir
(
$template_dir
);
my
$overlay_dir
= File::Spec->catdir(
$temp_dir
,
'overlay'
);
mkdir
(
$overlay_dir
);
my
$base_file
= File::Spec->catfile(
$base_dir
,
'file.txt'
);
spurt(
"foo"
,
$base_file
);
chmod
( 0644,
$base_file
);
my
$template_file
= File::Spec->catfile(
$template_dir
,
'file.txt'
);
spurt(
"bar"
,
$template_file
);
chmod
( 0755,
$template_file
);
my
$old_umask
=
umask
(0027);
eval
{
Template::Overlay->new(
$base_dir
, Template::Resolver->new( {} ) )
->overlay(
$template_dir
,
to
=>
$overlay_dir
);
};
my
$error
= $@;
umask
(
$old_umask
);
ok( !
$error
,
'permission overlay'
);
my
$overlay_file
= File::Spec->catfile(
$overlay_dir
,
'file.txt'
);
is(
"100750"
,
sprintf
(
'%04o'
, (
stat
(
$overlay_file
) )[2] ),
'mode set correctly when found in both base and template'
);
}
( run in 0.291 second using v1.01-cache-2.11-cpan-55f5a4728d2 )