1Module::Metadata::ChangUesse(r3)Contributed Perl DocumenMtoadtuiloen::Metadata::Changes(3)
2
3
4
6 Module::Metadata::Changes - Manage machine-readable
7 Changes/CHANGES/Changelog.ini files
8
10 One-liners
11 These examples use Changes/CHANGES and Changelog.ini in the 'current'
12 directory.
13
14 The command line options (except for -h) correspond to the options
15 documented under "Constructor and initialization", below.
16
17 shell>ini.report.pl -h
18 shell>ini.report.pl -c
19 shell>ini.report.pl -r 1.23
20 shell>sudo ini.report.pl -w > /var/www/Changelog.html
21 shell>perl -MModule::Metadata::Changes -e 'Module::Metadata::Changes->new(convert => 1)->run'
22 shell>perl -MModule::Metadata::Changes -e 'print Module::Metadata::Changes->new->read->get_latest_version'
23 shell>perl -MModule::Metadata::Changes -e 'print Module::Metadata::Changes->new->read->report'
24 shell>perl -MModule::Metadata::Changes -e 'print Module::Metadata::Changes->new(release=>"2.00")->read->report'
25
26 Module::Metadata::Changes ships with "ini.report.pl" in the bin/
27 directory. It is installed along with the module.
28
29 Also, Module::Metadata::Changes uses Config::IniFiles to read and write
30 Changelog.ini files.
31
32 Reporters
33 With a script like this:
34
35 #!/usr/bin/env perl
36
37 use feature 'say';
38 use strict;
39 use warnings;
40
41 use File::chdir; # For magic $CWD.
42
43 use Module::Metadata::Changes;
44
45 # ------------------------------------------------
46
47 my($work) = "$ENV{HOME}/perl.modules";
48 my($m) = Module::Metadata::Changes -> new;
49
50 opendir(INX, $work) || die "Can't opendir($work)";
51 my(@name) = sort grep{! /^\.\.?$/} readdir INX;
52 closedir INX;
53
54 my($config);
55 my($version);
56
57 for my $name (@name)
58 {
59 $CWD = "$work/$name"; # Does a chdir.
60 $version = $m -> read -> get_latest_version;
61 $config = $m -> config; # Must call read() before config().
62
63 say $config -> val('Module', 'Name'), " V $version ", $config -> val("V $version", 'Date');
64 }
65
66 you can get a report of the latest version number, from Changelog.ini,
67 for each module in your vast library.
68
70 Module::Metadata::Changes is a pure Perl module.
71
72 It allows you to convert old-style Changes/CHANGES files, and to read
73 and write Changelog.ini files.
74
75 =head1 Distributions
76
77 This module is available as a Unix-style distro (*.tgz).
78
79 See http://savage.net.au/Perl-modules.html for details.
80
81 See http://savage.net.au/Perl-modules/html/installing-a-module.html for
82 help on unpacking and installing.
83
85 new(...) returns an object of type Module::Metadata::Changes.
86
87 This is the class contructor.
88
89 Usage: "Module::Metadata::Changes -> new()".
90
91 This method takes a hash of options. There are no mandatory options.
92
93 Call "new()" as "new(option_1 => value_1, option_2 => value_2, ...)".
94
95 Available options:
96
97 o convert
98 This takes the value 0 or 1.
99
100 The default is 0.
101
102 If the value is 0, calling "run()" calls "read()" and "report()".
103
104 If the value is 1, calling "run()" calls "writer(reader() )".
105
106 o inFileName
107 The default is 'Changes' (or, if absent, 'CHANGES') when calling
108 "reader()", and 'Changelog.ini' when calling "read()".
109
110 o outFileName
111 The default is 'Changelog.ini'.
112
113 o pathForHTML
114 This is path to the HTML::Template-style templates used by the
115 'table' and 'webPage' options.
116
117 The default is
118 '/usr/share/perl-Module-Metadata-Changes/templates/module/metadata/changes'.
119
120 o release
121 The default is ''.
122
123 If this option has a non-empty value, the value is assumed to be a
124 release/version number.
125
126 In that case, reports (text, HTML) are restricted to only the given
127 version.
128
129 The default ('') means reports contain all versions.
130
131 'release' was chosen, rather than 'version', in order to avoid a
132 clash with 'verbose', since all options could then be abbreviated
133 to 1 letter (when running ini.report.pl).
134
135 Also, a lot of other software uses -r to refer to release/version.
136
137 o table
138 This takes the value 0 or 1.
139
140 The default is 0.
141
142 This option is only used when "report()" is called.
143
144 If the value is 0, calling "report()" outputs a text report.
145
146 If the value is 1, calling "report()" outputs a HTML report.
147
148 By default, the HTML report will just be a HTML table.
149
150 However, if the 'webPage' option is 1, the HTML will be a complete
151 web page.
152
153 o urlForCSS
154 The default is '/.sysassets/css/module/metadata/changes/ini.css'.
155
156 This is only used if the 'webPage' option is 1.
157
158 o verbose
159 This takes the value 0 or 1.
160
161 The default is 0.
162
163 If the value is 1, write progress reports to STDERR.
164
165 o webPage
166 This takes the value 0 or 1.
167
168 The default is 0.
169
170 A value of 1 automatically sets 'table' to 1.
171
172 If the value is 0, the 'table' option outputs just a HTML table.
173
174 If the value is 1, the 'table' option outputs a complete web page.
175
177 o config()
178 Returns the Config::IniFiles object, from which you can extract all the
179 data.
180
181 This method must be called after calling "read()".
182
183 See "scripts/report.names.pl" for sample code.
184
185 The names of the sections, [Module] and [V 1.23], and the keys under
186 each, are documented in the FAQ.
187
188 o errstr()
189 Returns the last error message, or ''.
190
191 o get_latest_release()
192 Returns an hash ref of details for the latest release.
193
194 Returns {} if there is no such release.
195
196 The hash keys are (most of) the reserved tokens, as discussed below in
197 the FAQ.
198
199 Some reserved tokens, such as EOT, make no sense as hash keys.
200
201 o get_latest_version()
202 Returns the version number of the latest version.
203
204 Returns '' if there is no such version.
205
206 o parse_datetime()
207 Used by "transform()".
208
209 o parse_datetime_1()
210 Used by "transform()".
211
212 o parse_datetime_2()
213 Used by "transform()".
214
215 o read([$input_file_name])
216 This method reads the given file, using Config::IniFiles.
217
218 The $input_file_name is optional. It defaults to 'Changelog.ini'.
219
220 See config().
221
222 Return value: The object, for method chaining.
223
224 o reader([$input_file_name])
225 This method parses the given file, assuming it is format is the common-
226 or-garden Changes/CHANGES style.
227
228 The $input_file_name is optional. It defaults to 'Changes' (or, if
229 absent, 'CHANGES').
230
231 "reader()" calls "module_name()" to save the module name for use by
232 other methods.
233
234 "reader()" calls "transform()".
235
236 Return value: An arrayref of hashrefs, i.e. the return value of
237 "transform()".
238
239 This value is suitable for passing to "writer()".
240
241 o report()
242 Displays various items for one or all releases.
243
244 If the 'release' option to "new()" was not used, displays items for all
245 releases.
246
247 If 'release' was used, restrict the report to just that
248 release/version.
249
250 If either the 'table' or 'webPage' options to "new()" were used, output
251 HTML by calling "report_as_html()".
252
253 If these latter 2 options were not used, output text.
254
255 HTML is escaped using HTML::Entities::Interpolate.
256
257 Output is to STDOUT.
258
259 Clearly, you should not use -v to get logging output when using text or
260 HTML output.
261
262 o report_as_html()
263 Displays various items as HTML for one or all releases.
264
265 If the 'release' option to "new()" was not used, displays items for all
266 releases.
267
268 If 'release' was used, restrict the report to just that
269 release/version.
270
271 Warning: This method must be called via the "report()" method.
272
273 Output is to STDOUT.
274
275 o run()
276 Use the options passed to "new()" to determine what to do.
277
278 Calling "new(convert => 1)" and then "run()" will cause
279 "writer(reader() )" to be called.
280
281 If you do not set 'convert' to 1 (i.e. use 0 - the default), "run()"
282 will call "read()" and "report()".
283
284 Return value: 0.
285
286 o transform(@line)
287 Transform the memory-based version of Changes/CHANGES into an arrayref
288 of hashrefs, where each array element holds data for 1 version.
289
290 Must be called by "reader()".
291
292 The array is the text read in from Changes/CHANGES.
293
294 "transform()" stores the arrayref of hashrefs in $obj -> changes(), for
295 use by "writer()".
296
297 Return value: The object, for method chaining.
298
299 o validate($file_name)
300 This method is used by "read()" to validate the contents of the file
301 read in.
302
303 "validate()" does not read the file.
304
305 "validate()" calls die when a validation test fails.
306
307 The file name is just used for reporting.
308
309 Return value: The object, for method chaining.
310
311 o writer([$output_file_name])
312 This method writes the arrayref stored in $obj -> changes(), using
313 Config::IniFiles, to the given file.
314
315 See "transform()".
316
317 The $output_file_name is optional. It defaults to 'Changelog.ini'.
318
319 Return value: The object, for method chaining.
320
322 o Are there any things I should look out for?
323 o Invalid dates
324 Invalid dates in Changes/CHANGES cannot be distinguished from
325 comments. That means that if the output file is missing one or
326 more versions, it is because of those invalid dates.
327
328 o Invalid day-of-week (dow)
329 If Changes/CHANGES includes the dow, it is not cross-checked
330 with the date, so if the dow is wrong, you will not get an
331 error generated.
332
333 o How do I display Changelog.ini?
334 See "bin/ini.report.pl". It outputs text or HTML.
335
336 o What is the format of Changelog.ini?
337 See also the next question.
338
339 See "scripts/report.names.pl" for sample code.
340
341 Here is a sample:
342
343 [Module]
344 Name=CGI::Session
345 Changelog.Creator=Module::Metadata::Changes V 1.00
346 Changelog.Parser=Config::IniFiles V 2.39
347
348 [V 4.30]
349 Date=2008-04-25T00:00:00
350 Comments= <<EOT
351 * FIX: Patch POD for CGI::Session in various places, to emphasize even more that auto-flushing is
352 unreliable, and that flush() should always be called explicitly before the program exits.
353 The changes are a new section just after SYNOPSIS and DESCRIPTION, and the PODs for flush(),
354 and delete(). See RT#17299 and RT#34668
355 * NEW: Add t/new_with_undef.t and t/load_with_undef.t to explicitly demonstrate the effects of
356 calling new() and load() with various types of undefined or fake parameters. See RT#34668
357 EOT
358
359 [V 4.10]
360 Date=2006-03-28T00:00:00
361 Deploy.Action=Upgrade
362 Deploy.Reason=Security
363 Comments= <<EOT
364 * SECURITY: Hopefully this settles all of the problems with symlinks. Both the file
365 and db_file drivers now use O_NOFOLLOW with open when the file should exist and
366 O_EXCL|O_CREAT when creating the file. Tests added for symlinks. (Matt LeBlanc)
367 * SECURITY: sqlite driver no longer attempts to use /tmp/sessions.sqlt when no
368 Handle or DataSource is specified. This was a mistake from a security standpoint
369 as anyone on the machine would then be able to create and therefore insert data
370 into your sessions. (Matt LeBlanc)
371 * NEW: name is now an instance method (RT#17979) (Matt LeBlanc)
372 EOT
373
374 o What are the reserved tokens in this format?
375 I am using tokens to refer to both things in [] such as Module, and
376 things on the left hand side of the = signs, such as Date.
377
378 And yes, these tokens are case-sensitive.
379
380 Under the [Module] section, the tokens are:
381
382 o Changelog.Creator
383 sample: Changelog.Creator=Module::Metadata::Changes V 2.00
384
385 o Changelog.Parser
386 Sample: Changelog.Parser=Config::IniFiles V 2.66
387
388 o Name
389 Sample: Name=Manage::Module::Changes
390
391 Under each version (section), whose name is like [V 1.23], the
392 token are as follows.
393
394 Config::IniFiles calls the V in [V 1.23] a Group Name.
395
396 o Comments
397 Sample: Comments=- Original version
398
399 o Date
400 The datetime of the release, in W3CDTF format.
401
402 Sample: Date=2008-05-02T15:15:45
403
404 I know the embedded 'T' makes this format a bit harder to read,
405 but the idea is that such files will normally be processed by a
406 program.
407
408 o Deploy.Action
409 The module author makes this recommendation to the end user.
410
411 This enables the end user to quickly grep the Changelog.ini, or
412 the output of "ini.report.pl", for things like security fixes
413 and API changes.
414
415 Run 'bin/ini.report.pl -h' for help.
416
417 Suggestions:
418
419 Deploy.Action=Upgrade
420 Deploy.Reason=(Security|Major bug fix)
421
422 Deploy.Action=Upgrade with caution
423 Deploy.Reason=(Major|Minor) API change/Development version
424
425 Alternately, the classic syslog tokens could perhaps be used:
426
427 Debug/Info/Notice/Warning/Error/Critical/Alert/Emergency.
428
429 I think the values for these 2 tokens (Deploy.*) should be kept
430 terse, and the Comments section used for an expanded
431 explanation, if necessary.
432
433 Omitting Deploy.Action simply means the module author leaves it
434 up to the end user to read the comments and make up their own
435 mind.
436
437 "reader()" called directly, or via "ini.report.pl -c" (i.e. old
438 format to ini format converter), inserts these 2 tokens if it
439 sees the word /Security/i in the Comments. It is a crude but
440 automatic warning to end users. The HTML output options ("-t"
441 and "-w") use red text via CSS to highlight these 2 tokens.
442
443 Of course security is best handled by the module author
444 explicitly inserting a suitable note.
445
446 And, lastly, any such note is purely up to the judgement of the
447 author, which means differences in opinion are inevitable.
448
449 o Deploy.Reason
450 The module author gives this reason for their recommended
451 action.
452
453 o EOT
454 Config::IniFiles uses EOT to terminate multi-line comments.
455
456 If "transform()" finds a line beginning with EOT, it jams a '-'
457 in front of it.
458
459 o Why are there not more reserved tokens?
460 Various reasons:
461
462 o Any one person, or any group, can standardize on their own tokens
463 Obviously, it would help if they advertised their choice,
464 firstly so as to get as many people as possible using the same
465 tokens, and secondly to get agreement on the interpretation of
466 those choices.
467
468 Truely, there is no point in any particular token if it is not
469 given a consistent meaning.
470
471 o You can simply add your own to your Changelog.ini file
472 They will then live on as part of the file.
473
474 Special processing is normally only relevant when converting an
475 old-style Changes/CHANGES file to a new-style Changelog.ini file.
476
477 However, if you think the new tokens are important enough to be
478 displayed as part of the text and HTML format reports, let me know.
479
480 I have deliberately not included the Comments in reports since you
481 can always just examine the Changelog.ini file itself for such
482 items. But that too could be changed.
483
484 o Are single-line comments acceptable?
485 Sure. Here is one:
486
487 Comments=* INTERNAL: No Changes since 4.20_1. Declaring stable.
488
489 The '*' is not special, it is just part of the comment.
490
491 o What is with the datetime format?
492 It is called W3CDTF format. See:
493
494 http://search.cpan.org/dist/DateTime-Format-W3CDTF/
495
496 See also ISO8601 format:
497
498 http://search.cpan.org/dist/DateTime-Format-ISO8601/
499
500 o Why this file format?
501 Various reasons:
502
503 o [Module] allows for [Script], [Library], and so on.
504 o *.ini files are easy for beginners to comprehend
505 o Other formats were considered. I made a decision
506 There is no perfect format which will please everyone.
507
508 Various references, in no particular order:
509
510 http://use.perl.org/~miyagawa/journal/34850
511
512 http://use.perl.org/~hex/journal/34864
513
514 http://redhanded.hobix.com/inspect/yamlIsJson.html
515
516 http://use.perl.org/article.pl?sid=07/09/06/0324215
517
518 http://use.perl.org/comments.pl?sid=36862&cid=57590
519
520 http://use.perl.org/~RGiersig/journal/34370/
521
522 o The module Config::IniFiles already existed, for reading and
523 writing this format
524 Specifically, Config::IniFiles allows for here documents, which
525 I use to hold the comments authors produce for most of their
526 releases.
527
528 o What is the difference between release and version?
529 I am using release to refer not just to the version number, but
530 also to all the notes relating to that version.
531
532 And by notes I mean everything in one section under the name [V
533 $version].
534
535 o Will you switch to YAML or XML format?
536 YAML? No, never. It is targetted at other situations, and while it
537 can be used for simple applications like this, it can't be hand-
538 written by beginners.
539
540 And it's unreasonable to force people to write a simple program to
541 write a simple YAML file.
542
543 XML? Nope. It is great in some situations, but too visually dense
544 and slow to write for this one.
545
546 o What about adding Changed Requirements to the file?
547 No. That info will be in the changed "Build.PL" or "Makefile.PL"
548 files.
549
550 It is a pointless burden to make the module author also add that to
551 Changelog.ini.
552
553 o Who said you had the power to decide on this format?
554 No-one. But I do have the time and the inclination to maintain
555 Module::Metadata::Changes indefinitely.
556
557 Also, I had a pressing need for a better way to manage metadata
558 pertaining my own modules, for use in my database of modules.
559
560 One of the reports I produce from this database is visible here:
561
562 http://savage.net.au/Perl-modules.html
563
564 Ideally, there will come a time when all of your modules, if not
565 the whole of CPAN, will have Changelog.ini files, so producing such
566 a report will be easy, and hence will be that much more likely to
567 happen.
568
569 o Why not use, say, Config::Tiny to process Changelog.ini files?
570 Because Config::Tiny contains this line, 's/\s\;\s.+$//g;', so it
571 will mangle text containing English semi-colons.
572
573 Also, authors add comments per release, and most "Config::*"
574 modules only handle lines of the type X=Y.
575
576 o How are the old Changes/CHANGES files parsed?
577 The first line is scanned looking for /X::Y/ or /X\.$/. And yes, it
578 fails for modules which identify themselves like Fuse-PDF not at
579 the end of the line.
580
581 Then lines looking something like /$a_version_number ...
582 $a_datetime/ are searched for. This is deemed to be the start of
583 information pertaining to a specific release.
584
585 Everything up to the next release, or EOF, is deemed to belong to
586 the release just identified.
587
588 This means a line containing a version number without a date is not
589 recognized as a new release, so that that line and the following
590 comments are added to the 'current' release info.
591
592 For an example of this, process the "Changes" file from
593 CGI::Session (t/Changes), and scan the output for '[4.00_01]',
594 which you will see contains stuff for V 3.12, 3.8 and 3.x.
595
596 See above, under the list of reserved tokens, for how security
597 advisories are inserted in the output stream.
598
599 o Is this conversion process perfect?
600 Well, no, actually, but it will be as good as I can make it.
601
602 For example, version numbers like '3.x' are turned into '3.'.
603
604 You will simply have to scrutinize (which means 'read carefully')
605 the output of this conversion process.
606
607 If a Changes/CHANGES file is not handled by the current version,
608 log a bug report on Request Tracker: http://rt.cpan.org/Public/
609
610 o How are datetimes in old-style files parsed?
611 Firstly try DateTime::Format::HTTP, and if that fails, try these
612 steps:
613
614 o Strip 'st' from 1st, 'nd' from 2nd, etc
615 o Try DateTime::Format::Strptime
616 o If that fails, strip Monday, etc, and retry
617 DateTime::Format::Strptime
618 I noticed some dates were invalid because the day of the week
619 did not match the day of the month. So, I arbitrarily chop the
620 day of the week, and retry.
621
622 Other date parsing modules are Date::Manip, Date::Parse and
623 Regexp::Common::time.
624
625 o Why did you choose these 2 modules?
626 I had a look at a few Changes/CHANGES files, and these made sense.
627
628 If appropriate, other modules can be added to the algorithm.
629
630 See the discussion on this page (search for 'parse multiple
631 formats'):
632
633 http://datetime.perl.org/index.cgi?FAQBasicUsage
634
635 If things get more complicated, I will reconsider using
636 DateTime::Format::Builder.
637
638 o What happens for 2 releases on the same day?
639 It depends whether or not the version numbers are different.
640
641 The "Changes" file for CGI::Session contains 2 references to
642 version 4.06 :-(.
643
644 As long as the version numbers are different, the date does not
645 actually matter.
646
647 o Will a new file format mean more work for those who maintain CPAN?
648 Yes, I am afraid so, unless they completely ignore me!
649
650 But I am hopeful this will lead to less work overall.
651
652 o Why did you not use the "Template Toolkit" for the HTML?
653 It is too complex for this tiny project.
654
655 o Where do I go for support?
656 Log a bug report on Request Tracker: http://rt.cpan.org/Public/
657
658 If it concerns failure to convert a specific Changes/CHANGES file,
659 just provide the name of the module and the version number.
660
661 It would help - if the problem is failure to parse a specific
662 datetime format - if you could advise me on a suitable
663 "DateTime::Format::*" module to use.
664
666 The file Changes was converted into Changelog.ini by
667 Module::Metadata::Changes.
668
670 Version numbers < 1.00 represent development versions. From 1.00 up,
671 they are production versions.
672
674 <https://github.com/ronsavage/Module-Metadata-Changes>.
675
677 Email the author, or log a bug on RT:
678
679 <https://rt.cpan.org/Public/Dist/Display.html?Name=Module::Metadata::Changes>.
680
682 App::ParseCPANChanges.
683
684 CPAN::Changes
685
686 Module::Changes
687
689 Module::Metadata::Changes was written by Ron Savage <ron@savage.net.au>
690 in 2008.
691
692 Home page: http://savage.net.au/index.html
693
695 Australian copyright (c) 2008, Ron Savage. All Programs of mine
696 are 'OSI Certified Open Source Software'; you can redistribute
697 them and/or modify them under the terms of The Perl License, a
698 copy of which is available at: http://dev.perl.org/licenses/
699
700
701
702perl v5.36.0 2022-07-22 Module::Metadata::Changes(3)