Skip to content

Commit fda5926

Browse files
authored
Merge branch 'main' into docs/doc-grant-release
2 parents 660b2dd + d372434 commit fda5926

38 files changed

+1708
-677
lines changed

Changes

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
{{$NEXT}}
22

3+
[ BUG FIXES ]
4+
* GH #1701: Split cookie values on & only (Yanick Champoux)
5+
6+
[ ENHANCEMENTS ]
7+
* GH #530: Make data censoring configurable (Yanick Champoux, David
8+
Precious)
9+
* GH #1723: Enable use of a different Template Toolkit base class
10+
(Andy Beverley)
11+
* PR #1727: Don't create CPAN package files when generating new apps
12+
(Jason A. Crome)
13+
* GH #1737: Add on_hook_exception for errors during hook processing
14+
(Andy Beverley)
15+
16+
[ DOCUMENTATION ]
17+
* GH #1342: Document skipping private methods in pod coverage tests
18+
(Jason A. Crome)
19+
20+
[ DEPRECATED ]
21+
* None
22+
23+
[ MISC ]
24+
* None
25+
326
1.1.2 2024-11-25 08:34:51-05:00 America/New_York
427

528
[ BUG FIXES ]

cpanfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ requires 'Attribute::Handlers';
33
requires 'Carp';
44
requires 'Clone';
55
requires 'Config::Any';
6+
requires 'Data::Censor' => '0.04';
67
requires 'Digest::SHA';
78
requires 'Encode';
89
requires 'Exporter', '5.57';

lib/Dancer2.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ We are also on IRC: #dancer on irc.perl.org.
379379
Michael Kröll
380380
Michał Wojciechowski
381381
Mike Katasonov
382+
Mikko Koivunalho
382383
Mohammad S Anwar
383384
mokko
384385
Nick Patch

lib/Dancer2/CLI/Gen.pm

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ option skel => (
7474
format_doc => 'directory',
7575
required => 0,
7676
default => sub{
77-
my $self = shift;
78-
path( $self->parent_command->_dist_dir, 'skel' );
77+
my $self = shift;
78+
path( $self->parent_command->_dist_dir, 'skel' );
7979
},
8080
);
8181

@@ -95,7 +95,7 @@ option git => (
9595
default => 0,
9696
);
9797

98-
option remote => (
98+
option remote => (
9999
is => 'ro',
100100
short => 'r',
101101
doc => 'URI for git repository (implies -g)',
@@ -104,12 +104,19 @@ option remote => (
104104
required => 0,
105105
);
106106

107+
option no_package_files => (
108+
is => 'ro',
109+
doc => "don't create files needed for CPAN packaging",
110+
required => 0,
111+
default => 0,
112+
);
113+
107114
# Last chance to validate args before we attempt to do something with them
108115
sub BUILD {
109116
my ( $self, $args ) = @_;
110117

111-
$self->osprey_usage( 1, qq{
112-
Invalid application name. Application names must not contain single colons,
118+
$self->osprey_usage( 1, qq{
119+
Invalid application name. Application names must not contain single colons,
113120
dots, hyphens or start with a number.
114121
}) unless is_module_name( $self->application );
115122

@@ -165,8 +172,10 @@ sub run {
165172
};
166173

167174
$self->_copy_templates( $files_to_copy, $vars, $self->overwrite );
168-
$self->_create_manifest( $files_to_copy, $app_path );
169-
$self->_add_to_manifest_skip( $app_path);
175+
unless( $self->no_package_files ) {
176+
$self->_create_manifest( $files_to_copy, $app_path );
177+
$self->_add_to_manifest_skip( $app_path );
178+
}
170179

171180
$self->_check_git( $vars );
172181
$self->_check_yaml;
@@ -183,7 +192,7 @@ sub _check_git {
183192
184193
WARNING: Couldn't initialize a git repo despite being asked to do so.
185194
186-
To resolve this, cd to your application directory and run the following
195+
To resolve this, cd to your application directory and run the following
187196
commands:
188197
189198
git init
@@ -200,13 +209,13 @@ commands:
200209
path( $gitignore )->copy( $app_path );
201210

202211
chdir File::Spec->rel2abs( $app_path ) or die "Can't cd to $app_path: $!";
203-
if( _run_shell_cmd( 'git', 'init') != 0 or
204-
_run_shell_cmd( 'git', 'add', '.') != 0 or
212+
if( _run_shell_cmd( 'git', 'init') != 0 or
213+
_run_shell_cmd( 'git', 'add', '.') != 0 or
205214
_run_shell_cmd( 'git', 'commit', "-m 'Initial commit of $app_name by Dancer2'" ) != 0 ) {
206215
print $git_error;
207216
}
208217
else {
209-
if( $self->remote &&
218+
if( $self->remote &&
210219
_run_shell_cmd( 'git', 'remote', 'add', 'origin', $self->remote ) != 0 ) {
211220
print $git_error;
212221
print " git remote add origin " . $self->remote . "\n";
@@ -290,7 +299,7 @@ sub _build_file_list {
290299
warn "File not found: $file" unless $file->exists; # Paranoia
291300
next if $file->basename =~ m{^\.git(/|$)};
292301
next if $file->is_dir;
293-
302+
294303
my $filename = $file->relative( $from );
295304
push @result, [ $file, path( $to, $filename )];
296305
}
@@ -302,6 +311,9 @@ sub _copy_templates {
302311

303312
foreach my $pair (@$files) {
304313
my ( $from, $to ) = @{$pair};
314+
next if $self->no_package_files && $from =~ /MANIFEST\.SKIP$/;
315+
next if $self->no_package_files && $from =~ /Makefile.PL$/;
316+
305317
if ( -f $to && !$overwrite ) {
306318
print "! $to exists, overwrite? (or rerun this command with -o) [N/y/a]: ";
307319
my $res = <STDIN>; chomp($res);
@@ -315,7 +327,7 @@ sub _copy_templates {
315327
$to_dir->mkpath;
316328
}
317329

318-
# Skeleton files whose names are prefixed with + need to be executable, but we must strip
330+
# Skeleton files whose names are prefixed with + need to be executable, but we must strip
319331
# that from the name when copying them
320332
my $to_file = path( $to )->basename;
321333
my $ex = ( $to_file =~ s/^\+// );
@@ -378,7 +390,7 @@ sub _process_template {
378390
return $engine->render( \$template, $tokens );
379391
}
380392

381-
# These are good candidates to move to Dancer2::CLI if other commands
393+
# These are good candidates to move to Dancer2::CLI if other commands
382394
# need them later.
383395
sub _get_app_path {
384396
my ( $self, $path, $appname ) = @_;
@@ -431,8 +443,8 @@ sub _run_shell_cmd {
431443

432444
my $exit_status = try {
433445
my $pid = IPC::Open3::open3(
434-
my $stdin,
435-
my $stdout,
446+
my $stdin,
447+
my $stdout,
436448
my $stderr = Symbol::gensym,
437449
@cmds,
438450
);

lib/Dancer2/ConfigReader.pm

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# ABSTRACT: Config reader for Dancer2 App
2+
package Dancer2::ConfigReader;
3+
4+
use Moo;
5+
6+
use File::Spec;
7+
use Config::Any;
8+
use Hash::Merge::Simple;
9+
use Carp 'croak';
10+
use Module::Runtime qw{ use_module };
11+
12+
use Dancer2::Core::Factory;
13+
use Dancer2::Core;
14+
use Dancer2::Core::Types;
15+
use Dancer2::ConfigUtils 'normalize_config_entry';
16+
17+
has location => (
18+
is => 'ro',
19+
isa => Str,
20+
required => 1,
21+
);
22+
23+
has default_config => (
24+
is => 'ro',
25+
isa => HashRef,
26+
required => 1,
27+
);
28+
29+
has config_location => (
30+
is => 'ro',
31+
isa => ReadableFilePath,
32+
lazy => 1,
33+
default => sub { $_[0]->location },
34+
);
35+
36+
# The type for this attribute is Str because we don't require
37+
# an existing directory with configuration files for the
38+
# environments. An application without environments is still
39+
# valid and works.
40+
has environments_location => (
41+
is => 'ro',
42+
isa => Str,
43+
lazy => 1,
44+
default => sub {
45+
$ENV{DANCER_ENVDIR}
46+
|| File::Spec->catdir( $_[0]->config_location, 'environments' );
47+
},
48+
);
49+
50+
has config => (
51+
is => 'ro',
52+
isa => HashRef,
53+
lazy => 1,
54+
builder => '_build_config',
55+
);
56+
57+
has environment => (
58+
is => 'ro',
59+
isa => Str,
60+
required => 1,
61+
);
62+
63+
has config_readers => (
64+
is => 'ro',
65+
lazy => 1,
66+
isa => ArrayRef,
67+
builder => '_build_config_readers',
68+
);
69+
70+
# The config builder
71+
sub _build_config {
72+
my ($self) = @_;
73+
74+
my $default = $self->default_config;
75+
my $config = Hash::Merge::Simple->merge(
76+
$default,
77+
map {
78+
warn "Merging config from @{[ $_->name() ]}\n" if $ENV{DANCER_CONFIG_VERBOSE};
79+
$_->read_config()
80+
} @{ $self->config_readers }
81+
);
82+
83+
$config = $self->_normalize_config($config);
84+
return $config;
85+
}
86+
87+
sub _normalize_config {
88+
my ( $self, $config ) = @_;
89+
90+
foreach my $key ( keys %{$config} ) {
91+
my $value = $config->{$key};
92+
$config->{$key} = normalize_config_entry( $key, $value );
93+
}
94+
return $config;
95+
}
96+
97+
sub _build_config_readers {
98+
my ($self) = @_;
99+
100+
my @config_reader_names = $ENV{'DANCER_CONFIG_READERS'}
101+
? (split qr{,}msx, $ENV{'DANCER_CONFIG_READERS'})
102+
: ( q{Dancer2::ConfigReader::Config::Any} );
103+
104+
warn "ConfigReaders to use: @config_reader_names\n" if $ENV{DANCER_CONFIG_VERBOSE};
105+
return [
106+
map use_module($_)->new(
107+
location => $self->location,
108+
environment => $self->environment,
109+
), @config_reader_names
110+
];
111+
}
112+
113+
1;
114+
115+
__END__
116+
117+
=head1 DESCRIPTION
118+
119+
This class provides a C<config> attribute that - when accessing
120+
the first time - feeds itself by executing one or more
121+
B<ConfigReader> packages.
122+
123+
Also provides a C<setting()> method which is supposed to be used by externals to
124+
read/write config entries.
125+
126+
You can control which B<ConfigReader>
127+
class or classes to use to create the config.
128+
129+
Use C<DANCER_CONFIG_READERS> environment variable to define
130+
which class or classes you want.
131+
132+
DANCER_CONFIG_READERS='Dancer2::ConfigReader::Config::Any,Dancer2::ConfigReader::CustomConfig'
133+
134+
If you want several, separate them with a comma (",").
135+
Configs are added in left-to-write order where the previous
136+
config items get overwritten by subsequent ones.
137+
138+
For example, if config
139+
140+
item1: content1
141+
item2: content2
142+
item3:
143+
subitem1: subcontent1
144+
subitem2: subcontent2
145+
subitem3:
146+
subsubitem1:
147+
subsubcontent1
148+
item4:
149+
subitem1: subcontent1
150+
subitem2: subcontent2
151+
152+
was followed by config
153+
154+
item2: content9
155+
item3:
156+
subitem2: subcontent8
157+
subitem3:
158+
subsubitem1:
159+
subsubcontent7
160+
subitem4:
161+
subsubitem5: subsubcontent5
162+
item4: content4
163+
164+
then the final config would be
165+
166+
item1: content1
167+
item2: content9
168+
item3:
169+
subitem1: subcontent1
170+
subitem2: subcontent8
171+
subitem3:
172+
subsubitem1:
173+
subsubcontent7
174+
subitem4:
175+
subsubitem5: subsubcontent5
176+
item4: content4
177+
178+
The default B<ConfigReader> is C<Dancer2::ConfigReader::Config::Any>.
179+
180+
You can also create your own custom B<ConfigReader> classes.
181+
182+
If you want, you can also extend class C<Dancer2::ConfigReader::Config::Any>.
183+
Here is an example:
184+
185+
package Dancer2::ConfigReader::FileExtended;
186+
use Moo;
187+
extends 'Dancer2::ConfigReader::Config::Any';
188+
has name => (
189+
is => 'ro',
190+
default => sub {'FileExtended'},
191+
);
192+
around read_config => sub {
193+
my ($orig, $self) = @_;
194+
my $config = $orig->($self, @_);
195+
$config->{'dummy'}->{'item'} = 123;
196+
return $config;
197+
};
198+
199+
Another (more complex) example is in class C<Dancer2::ConfigReader::Config::Any>.
200+
201+
=head1 ATTRIBUTES
202+
203+
=attr location
204+
205+
Absolute path to the directory where the server started.
206+
207+
=attr config_location
208+
209+
Gets the location from the configuration. Same as C<< $object->location >>.
210+
211+
=attr environments_location
212+
213+
Gets the directory where the environment files are stored.
214+
215+
=attr config
216+
217+
Returns the whole configuration.
218+
This must not be used directly.
219+
Instead, use this via C<Dancer2::Core::Role::HasConfig> role
220+
which manages configuration after it is created.
221+
222+
=attr environment
223+
224+
Returns the name of the environment.

0 commit comments

Comments
 (0)