1Module::Metadata::ChangUesse(r3)Contributed Perl DocumenMtoadtuiloen::Metadata::Changes(3)
2
3
4

NAME

6       Module::Metadata::Changes - Manage machine-readable
7       Changes/CHANGES/Changelog.ini files
8

Synopsis

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

Description

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

Constructor and initialization

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

Methods

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

FAQ

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

Machine-Readable Change Log

666       The file Changes was converted into Changelog.ini by
667       Module::Metadata::Changes.
668

Version Numbers

670       Version numbers < 1.00 represent development versions. From 1.00 up,
671       they are production versions.
672

Repository

674       <https://github.com/ronsavage/Module-Metadata-Changes>.
675

Support

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

See Also

682       App::ParseCPANChanges.
683
684       CPAN::Changes
685
686       Module::Changes
687

Author

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.34.0                      2022-01-21      Module::Metadata::Changes(3)
Impressum