line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Module::Build::Notes; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# A class for persistent hashes |
4
|
|
|
|
|
|
|
|
5
|
293
|
|
|
293
|
|
2183
|
use strict; |
|
293
|
|
|
|
|
679
|
|
|
293
|
|
|
|
|
8879
|
|
6
|
293
|
|
|
293
|
|
1522
|
use warnings; |
|
293
|
|
|
|
|
564
|
|
|
293
|
|
|
|
|
13892
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.4234'; |
8
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
9
|
293
|
|
|
293
|
|
1768
|
use Data::Dumper; |
|
293
|
|
|
|
|
530
|
|
|
293
|
|
|
|
|
13832
|
|
10
|
293
|
|
|
293
|
|
1850
|
use Module::Build::Dumper; |
|
293
|
|
|
|
|
613
|
|
|
293
|
|
|
|
|
316504
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
13
|
3360
|
|
|
3360
|
0
|
18713
|
my ($class, %args) = @_; |
14
|
3360
|
50
|
|
|
|
13677
|
my $file = delete $args{file} or die "Missing required parameter 'file' to new()"; |
15
|
3360
|
|
|
|
|
56598
|
my $self = bless { |
16
|
|
|
|
|
|
|
disk => {}, |
17
|
|
|
|
|
|
|
new => {}, |
18
|
|
|
|
|
|
|
file => $file, |
19
|
|
|
|
|
|
|
%args, |
20
|
|
|
|
|
|
|
}, $class; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub restore { |
24
|
2862
|
|
|
2862
|
0
|
9780
|
my $self = shift; |
25
|
|
|
|
|
|
|
|
26
|
2862
|
50
|
|
|
|
146056
|
open(my $fh, '<', $self->{file}) or die "Can't read $self->{file}: $!"; |
27
|
2862
|
|
|
|
|
10055
|
$self->{disk} = eval do {local $/; <$fh>}; |
|
2862
|
|
|
|
|
16343
|
|
|
2862
|
|
|
|
|
411390
|
|
28
|
2862
|
50
|
|
|
|
20074
|
die $@ if $@; |
29
|
2862
|
|
|
|
|
40928
|
close $fh; |
30
|
2862
|
|
|
|
|
23507
|
$self->{new} = {}; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub access { |
34
|
127
|
|
|
127
|
0
|
460
|
my $self = shift; |
35
|
127
|
100
|
|
|
|
716
|
return $self->read() unless @_; |
36
|
|
|
|
|
|
|
|
37
|
44
|
|
|
|
|
255
|
my $key = shift; |
38
|
44
|
100
|
|
|
|
261
|
return $self->read($key) unless @_; |
39
|
|
|
|
|
|
|
|
40
|
25
|
|
|
|
|
103
|
my $value = shift; |
41
|
25
|
|
|
|
|
229
|
$self->write({ $key => $value }); |
42
|
25
|
|
|
|
|
123
|
return $self->read($key); |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub has_data { |
46
|
183
|
|
|
183
|
0
|
541
|
my $self = shift; |
47
|
183
|
|
|
|
|
402
|
return keys %{$self->read()} > 0; |
|
183
|
|
|
|
|
664
|
|
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub exists { |
51
|
2
|
|
|
2
|
0
|
18
|
my ($self, $key) = @_; |
52
|
2
|
|
33
|
|
|
67
|
return exists($self->{new}{$key}) || exists($self->{disk}{$key}); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub read { |
56
|
467
|
|
|
467
|
0
|
1325
|
my $self = shift; |
57
|
|
|
|
|
|
|
|
58
|
467
|
100
|
|
|
|
1817
|
if (@_) { |
59
|
|
|
|
|
|
|
# Return 1 key as a scalar |
60
|
44
|
|
|
|
|
111
|
my $key = shift; |
61
|
44
|
100
|
|
|
|
169
|
return $self->{new}{$key} if exists $self->{new}{$key}; |
62
|
42
|
|
|
|
|
305
|
return $self->{disk}{$key}; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Return all data |
66
|
423
|
|
|
|
|
3215
|
my $out = (keys %{$self->{new}} |
67
|
7
|
|
|
|
|
110
|
? {%{$self->{disk}}, %{$self->{new}}} |
|
7
|
|
|
|
|
102
|
|
68
|
423
|
100
|
|
|
|
816
|
: $self->{disk}); |
69
|
423
|
100
|
|
|
|
3787
|
return wantarray ? %$out : $out; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub _same { |
73
|
95
|
|
|
95
|
|
456
|
my ($self, $x, $y) = @_; |
74
|
95
|
0
|
33
|
|
|
617
|
return 1 if !defined($x) and !defined($y); |
75
|
95
|
100
|
66
|
|
|
1012
|
return 0 if !defined($x) or !defined($y); |
76
|
93
|
|
|
|
|
705
|
return $x eq $y; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub write { |
80
|
252
|
|
|
252
|
1
|
1185
|
my ($self, $href) = @_; |
81
|
252
|
|
100
|
|
|
1514
|
$href ||= {}; |
82
|
|
|
|
|
|
|
|
83
|
252
|
|
|
|
|
1609
|
@{$self->{new}}{ keys %$href } = values %$href; # Merge |
|
252
|
|
|
|
|
1409
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Do some optimization to avoid unnecessary writes |
86
|
252
|
|
|
|
|
933
|
foreach my $key (keys %{ $self->{new} }) { |
|
252
|
|
|
|
|
2088
|
|
87
|
233
|
100
|
|
|
|
1439
|
next if ref $self->{new}{$key}; |
88
|
230
|
100
|
66
|
|
|
3094
|
next if ref $self->{disk}{$key} or !exists $self->{disk}{$key}; |
89
|
95
|
100
|
|
|
|
770
|
delete $self->{new}{$key} if $self->_same($self->{new}{$key}, $self->{disk}{$key}); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
252
|
50
|
|
|
|
1809
|
if (my $file = $self->{file}) { |
93
|
252
|
|
|
|
|
9918
|
my ($vol, $dir, $base) = File::Spec->splitpath($file); |
94
|
252
|
|
|
|
|
4741
|
$dir = File::Spec->catpath($vol, $dir, ''); |
95
|
252
|
100
|
66
|
|
|
9111
|
return unless -e $dir && -d $dir; # The user needs to arrange for this |
96
|
|
|
|
|
|
|
|
97
|
224
|
100
|
100
|
|
|
4007
|
return if -e $file and !keys %{ $self->{new} }; # Nothing to do |
|
221
|
|
|
|
|
2802
|
|
98
|
|
|
|
|
|
|
|
99
|
102
|
|
|
|
|
364
|
@{$self->{disk}}{ keys %{$self->{new}} } = values %{$self->{new}}; # Merge |
|
102
|
|
|
|
|
496
|
|
|
102
|
|
|
|
|
379
|
|
|
102
|
|
|
|
|
587
|
|
100
|
102
|
|
|
|
|
769
|
$self->_dump($file, $self->{disk}); |
101
|
|
|
|
|
|
|
|
102
|
102
|
|
|
|
|
1245
|
$self->{new} = {}; |
103
|
|
|
|
|
|
|
} |
104
|
102
|
|
|
|
|
786
|
return $self->read; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub _dump { |
108
|
102
|
|
|
102
|
|
488
|
my ($self, $file, $data) = @_; |
109
|
|
|
|
|
|
|
|
110
|
102
|
50
|
|
|
|
20416
|
open(my $fh, '>', $file) or die "Can't create '$file': $!"; |
111
|
102
|
|
|
|
|
713
|
print {$fh} Module::Build::Dumper->_data_dump($data); |
|
102
|
|
|
|
|
2782
|
|
112
|
102
|
|
|
|
|
39196
|
close $fh; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my $orig_template = do { local $/; <DATA> }; |
116
|
|
|
|
|
|
|
close DATA; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub write_config_data { |
119
|
1
|
|
|
1
|
0
|
20
|
my ($self, %args) = @_; |
120
|
|
|
|
|
|
|
|
121
|
1
|
|
|
|
|
13
|
my $template = $orig_template; |
122
|
1
|
|
|
|
|
36
|
$template =~ s/NOTES_NAME/$args{config_module}/g; |
123
|
1
|
|
|
|
|
24
|
$template =~ s/MODULE_NAME/$args{module}/g; |
124
|
1
|
|
|
|
|
21
|
$template =~ s/=begin private\n//; |
125
|
1
|
|
|
|
|
25
|
$template =~ s/=end private/=cut/; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# strip out private POD markers we use to keep pod from being |
128
|
|
|
|
|
|
|
# recognized for *this* source file |
129
|
1
|
|
|
|
|
32
|
$template =~ s{$_\n}{} for '=begin private', '=end private'; |
130
|
|
|
|
|
|
|
|
131
|
1
|
50
|
|
|
|
75
|
open(my $fh, '>', $args{file}) or die "Can't create '$args{file}': $!"; |
132
|
1
|
|
|
|
|
4
|
print {$fh} $template; |
|
1
|
|
|
|
|
20
|
|
133
|
1
|
|
|
|
|
4
|
print {$fh} "\n__DATA__\n"; |
|
1
|
|
|
|
|
3
|
|
134
|
1
|
|
|
|
|
3
|
print {$fh} Module::Build::Dumper->_data_dump([$args{config_data}, $args{feature}, $args{auto_features}]); |
|
1
|
|
|
|
|
11
|
|
135
|
1
|
|
|
|
|
182
|
close $fh; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
1; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head1 NAME |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Module::Build::Notes - Create persistent distribution configuration modules |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head1 DESCRIPTION |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
This module is used internally by Module::Build to create persistent |
148
|
|
|
|
|
|
|
configuration files that can be installed with a distribution. See |
149
|
|
|
|
|
|
|
L<Module::Build::ConfigData> for an example. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head1 AUTHOR |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Ken Williams <kwilliams@cpan.org> |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head1 COPYRIGHT |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Copyright (c) 2001-2006 Ken Williams. All rights reserved. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or |
160
|
|
|
|
|
|
|
modify it under the same terms as Perl itself. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head1 SEE ALSO |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
perl(1), L<Module::Build>(3) |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=cut |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
__DATA__ |
169
|
|
|
|
|
|
|
package NOTES_NAME; |
170
|
|
|
|
|
|
|
use strict; |
171
|
|
|
|
|
|
|
my $arrayref = eval do {local $/; <DATA>} |
172
|
|
|
|
|
|
|
or die "Couldn't load ConfigData data: $@"; |
173
|
|
|
|
|
|
|
close DATA; |
174
|
|
|
|
|
|
|
my ($config, $features, $auto_features) = @$arrayref; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub config { $config->{$_[1]} } |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub set_config { $config->{$_[1]} = $_[2] } |
179
|
|
|
|
|
|
|
sub set_feature { $features->{$_[1]} = 0+!!$_[2] } # Constrain to 1 or 0 |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub auto_feature_names { sort grep !exists $features->{$_}, keys %$auto_features } |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub feature_names { |
184
|
|
|
|
|
|
|
my @features = (sort keys %$features, auto_feature_names()); |
185
|
|
|
|
|
|
|
@features; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub config_names { sort keys %$config } |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub write { |
191
|
|
|
|
|
|
|
my $me = __FILE__; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Can't use Module::Build::Dumper here because M::B is only a |
194
|
|
|
|
|
|
|
# build-time prereq of this module |
195
|
|
|
|
|
|
|
require Data::Dumper; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
my $mode_orig = (stat $me)[2] & 07777; |
198
|
|
|
|
|
|
|
chmod($mode_orig | 0222, $me); # Make it writeable |
199
|
|
|
|
|
|
|
open(my $fh, '+<', $me) or die "Can't rewrite $me: $!"; |
200
|
|
|
|
|
|
|
seek($fh, 0, 0); |
201
|
|
|
|
|
|
|
while (<$fh>) { |
202
|
|
|
|
|
|
|
last if /^__DATA__$/; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
die "Couldn't find __DATA__ token in $me" if eof($fh); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
seek($fh, tell($fh), 0); |
207
|
|
|
|
|
|
|
my $data = [$config, $features, $auto_features]; |
208
|
|
|
|
|
|
|
print($fh 'do{ my ' |
209
|
|
|
|
|
|
|
. Data::Dumper->new([$data],['x'])->Purity(1)->Dump() |
210
|
|
|
|
|
|
|
. '$x; }' ); |
211
|
|
|
|
|
|
|
truncate($fh, tell($fh)); |
212
|
|
|
|
|
|
|
close $fh; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
chmod($mode_orig, $me) |
215
|
|
|
|
|
|
|
or warn "Couldn't restore permissions on $me: $!"; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub feature { |
219
|
|
|
|
|
|
|
my ($package, $key) = @_; |
220
|
|
|
|
|
|
|
return $features->{$key} if exists $features->{$key}; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
my $info = $auto_features->{$key} or return 0; |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
require Module::Build; # XXX should get rid of this |
225
|
|
|
|
|
|
|
foreach my $type (sort keys %$info) { |
226
|
|
|
|
|
|
|
my $prereqs = $info->{$type}; |
227
|
|
|
|
|
|
|
next if $type eq 'description' || $type eq 'recommends'; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
foreach my $modname (sort keys %$prereqs) { |
230
|
|
|
|
|
|
|
my $status = Module::Build->check_installed_status($modname, $prereqs->{$modname}); |
231
|
|
|
|
|
|
|
if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; } |
232
|
|
|
|
|
|
|
if ( ! eval "require $modname; 1" ) { return 0; } |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
return 1; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=begin private |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=head1 NAME |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
NOTES_NAME - Configuration for MODULE_NAME |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head1 SYNOPSIS |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
use NOTES_NAME; |
247
|
|
|
|
|
|
|
$value = NOTES_NAME->config('foo'); |
248
|
|
|
|
|
|
|
$value = NOTES_NAME->feature('bar'); |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
@names = NOTES_NAME->config_names; |
251
|
|
|
|
|
|
|
@names = NOTES_NAME->feature_names; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
NOTES_NAME->set_config(foo => $new_value); |
254
|
|
|
|
|
|
|
NOTES_NAME->set_feature(bar => $new_value); |
255
|
|
|
|
|
|
|
NOTES_NAME->write; # Save changes |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=head1 DESCRIPTION |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
This module holds the configuration data for the C<MODULE_NAME> |
261
|
|
|
|
|
|
|
module. It also provides a programmatic interface for getting or |
262
|
|
|
|
|
|
|
setting that configuration data. Note that in order to actually make |
263
|
|
|
|
|
|
|
changes, you'll have to have write access to the C<NOTES_NAME> |
264
|
|
|
|
|
|
|
module, and you should attempt to understand the repercussions of your |
265
|
|
|
|
|
|
|
actions. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=head1 METHODS |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=over 4 |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item config($name) |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
Given a string argument, returns the value of the configuration item |
275
|
|
|
|
|
|
|
by that name, or C<undef> if no such item exists. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item feature($name) |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Given a string argument, returns the value of the feature by that |
280
|
|
|
|
|
|
|
name, or C<undef> if no such feature exists. |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item set_config($name, $value) |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Sets the configuration item with the given name to the given value. |
285
|
|
|
|
|
|
|
The value may be any Perl scalar that will serialize correctly using |
286
|
|
|
|
|
|
|
C<Data::Dumper>. This includes references, objects (usually), and |
287
|
|
|
|
|
|
|
complex data structures. It probably does not include transient |
288
|
|
|
|
|
|
|
things like filehandles or sockets. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=item set_feature($name, $value) |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
Sets the feature with the given name to the given boolean value. The |
293
|
|
|
|
|
|
|
value will be converted to 0 or 1 automatically. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=item config_names() |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Returns a list of all the names of config items currently defined in |
298
|
|
|
|
|
|
|
C<NOTES_NAME>, or in scalar context the number of items. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=item feature_names() |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Returns a list of all the names of features currently defined in |
303
|
|
|
|
|
|
|
C<NOTES_NAME>, or in scalar context the number of features. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=item auto_feature_names() |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Returns a list of all the names of features whose availability is |
308
|
|
|
|
|
|
|
dynamically determined, or in scalar context the number of such |
309
|
|
|
|
|
|
|
features. Does not include such features that have later been set to |
310
|
|
|
|
|
|
|
a fixed value. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=item write() |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
Commits any changes from C<set_config()> and C<set_feature()> to disk. |
315
|
|
|
|
|
|
|
Requires write access to the C<NOTES_NAME> module. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=back |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 AUTHOR |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
C<NOTES_NAME> was automatically created using C<Module::Build>. |
323
|
|
|
|
|
|
|
C<Module::Build> was written by Ken Williams, but he holds no |
324
|
|
|
|
|
|
|
authorship claim or copyright claim to the contents of C<NOTES_NAME>. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=end private |
327
|
|
|
|
|
|
|
|