/[suikacvs]/webroot/commitfeed/mkcommitfeed.pl
Suika

Contents of /webroot/commitfeed/mkcommitfeed.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (hide annotations) (download)
Mon Nov 24 06:34:49 2008 UTC (15 years, 5 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +10 -2 lines
File MIME type: text/plain
++ ChangeLog	24 Nov 2008 06:34:40 -0000
	* mkcommitfeed.pl: Update <atom:updated> of the Feed as well as
	<atom:updated> of the Entry when an Entry is added.

2008-11-24  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 #!/usr/bin/perl
2     use strict;
3    
4     use Getopt::Long;
5     use Pod::Usage;
6     use Time::Local;
7    
8     my $file_name;
9     my $feed_url;
10     my $feed_title = 'ChangeLog';
11     my $feed_author_name;
12     my $feed_author_mail;
13     my $feed_author_url;
14     my $feed_lang = 'i-default';
15     my $feed_related_url;
16     my $feed_license_url;
17     my $feed_rights;
18     my $entry_content;
19     my $entry_author_name;
20     my $entry_author_mail;
21     my $entry_date;
22     my $entry_title;
23    
24     GetOptions (
25     'entry-author-mail=s' => \$entry_author_mail,
26     'entry-author-name=s' => \$entry_author_name,
27     'entry-content=s' => \$entry_content,
28     'entry-title=s' => \$entry_title,
29     'feed-author-mail=s' => \$feed_author_mail,
30     'feed-author-name=s' => \$feed_author_name,
31     'feed-author-url=s' => \$feed_author_url,
32     'feed-lang=s' => \$feed_lang,
33     'feed-license-url=s' => \$feed_license_url,
34     'feed-related-url=s' => \$feed_related_url,
35     'feed-rights=s' => \$feed_rights,
36     'feed-title=s' => \$feed_title,
37     'feed-url=s' => \$feed_url,
38     'file-name=s' => \$file_name,
39     'help' => sub {
40     pod2usage (-exitval => 0, -verbose => 2);
41     },
42     ) or pod2usage (-exitval => 1, -verbose => 1);
43     pod2usage (-exitval => 1, -verbose => 1,
44     -msg => "Required argument --file-name is not specified.\n")
45     unless defined $file_name;
46     pod2usage (-exitval => 1, -verbose => 1,
47     -msg => "Required argument --feed-url is not specified.\n")
48     unless defined $feed_url;
49    
50     unless (defined $entry_content) {
51     $entry_content = '';
52     $entry_content .= $_ while <>;
53     }
54    
55     if ($entry_content =~ /^(\d+)-(\d+)-(\d+)\s+(.+)<([^<>]+)>/m) {
56     # $entry_date //= timegm (0, 0, 0, $3, $2-1, $1);
57     $entry_author_name //= $4;
58     $entry_author_mail //= $5;
59     $entry_author_name =~ s/\s+$//;
60     }
61     $entry_date //= time;
62    
63     pod2usage (-exitval => 1, -verbose => 1,
64     -msg => "Required argument --entry-author-name is not specified.\n")
65     unless defined $entry_author_name;
66    
67     unless (defined $entry_title) {
68     my $time = [gmtime $entry_date];
69     $entry_title = sprintf '%04d-%02d-%02d %s', 1900+$time->[5], 1+$time->[4],
70     $time->[3], $entry_author_name;
71     }
72    
73     require Message::DOM::DOMImplementation;
74     my $dom = Message::DOM::DOMImplementation->new;
75     my $doc;
76    
77     {
78     if (-f $file_name) {
79     open my $file, '<:encoding(utf8)', $file_name or die "$0: $file_name: $!";
80     local $/ = undef;
81     $doc = $dom->create_document;
82     $doc->inner_html (<$file>);
83     } else {
84     $doc = $dom->create_atom_feed_document
85     ($feed_url, $feed_title, $feed_lang);
86     }
87     }
88    
89     $doc->dom_config
90     ->{q<http://suika.fam.cx/www/2006/dom-config/create-child-element>} = 1;
91     my $feed = $doc->document_element;
92     unless ($feed) {
93     $feed = $doc->create_element_ns ('http://www.w3.org/2005/Atom', 'feed');
94     $doc->append_child ($feed);
95     }
96     $feed->set_attribute_ns ('http://www.w3.org/2000/xmlns/',
97     'xmlns', $feed->namespace_uri);
98    
99     unless (@{$feed->author_elements}) {
100     if (defined $feed_author_name) {
101     my $author = $doc->create_element_ns ($feed->namespace_uri, 'author');
102     $author->name ($feed_author_name);
103     $author->email ($feed_author_mail) if defined $feed_author_mail;
104     $author->uri ($feed_author_url) if defined $feed_author_url;
105     $feed->append_child ($author);
106     }
107     }
108     unless (@{$feed->link_elements}) {
109     my $link_self = $doc->create_element_ns ($feed->namespace_uri, 'link');
110     $link_self->rel ('self');
111     $link_self->type ('application/atom+xml');
112     $link_self->hreflang ($feed_lang);
113     $link_self->href ($feed_url);
114     $feed->append_child ($link_self);
115    
116     if (defined $feed_related_url) {
117     my $link = $doc->create_element_ns ($feed->namespace_uri, 'link');
118     $link->rel ('related');
119     $link->href ($feed_related_url);
120     $feed->append_child ($link);
121     }
122    
123     if (defined $feed_license_url) {
124     my $link = $doc->create_element_ns ($feed->namespace_uri, 'link');
125     $link->rel ('license');
126     $link->href ($feed_license_url);
127     $feed->append_child ($link);
128     }
129     }
130    
131     if (defined $feed_rights) {
132     $feed->rights_element->text_content ($feed_rights);
133     }
134    
135     my $entry_id = 'entry-' . time;
136     my $entry = $feed->add_new_entry ($feed_url . '#' . $entry_id,
137     $entry_title);
138     $entry->set_attribute_ns ('http://www.w3.org/XML/1998/namespace',
139     'xml:id' => $entry_id);
140     if (defined $entry_author_name) {
141     my $author = $doc->create_element_ns ($feed->namespace_uri, 'author');
142     $author->name ($entry_author_name);
143     $author->email ($entry_author_mail) if defined $entry_author_mail;
144     $entry->append_child ($author);
145     }
146     $entry->updated_element->value ($entry_date);
147     my $content = $entry->content_element;
148     $content->type ('text');
149     $content->text_content ($entry_content);
150    
151 wakaba 1.5 my $feed_date = $entry_date;
152     my $feed_updated = $feed->updated_element;
153     my $feed_updated_value = $feed_updated->value;
154     if ($feed_updated_value < $feed_date) {
155     $feed_updated->value ($feed_date);
156     }
157    
158    
159 wakaba 1.1 {
160     open my $file, '>:utf8', $file_name or die "$0: $file_name: $!";
161     print $file $doc->inner_html;
162     }
163    
164 wakaba 1.5 ## $Date: 2008/11/24 06:31:25 $
165 wakaba 1.3
166     __END__
167    
168     =head1 NAME
169    
170     mkcommitfeed.pl - Commit Log Feed Generator
171    
172     =head1 SYNOPSIS
173    
174     mkcommitfeed.pl \
175     --file-name filename.atom \
176     --feed-url http://example.com/myproject/filename.atom \
177     --feed-title "MyProject Commit Log" \
178     --feed-lang langtag \
179     --feed-related-url "http://example.com/myproject/" \
180     --feed-license-url "http://example.com/myproject/license" \
181     --feed-rights "Copyright or copyleft statement" \
182     < changes-in-this-revision.txt
183    
184     =head1 DESCRIPTION
185    
186     The C<mkcommitfeed.pl> script provides a command-line interface to
187     update an Atom Feed that is intended for providing commit logs for a
188     software developmenet project.
189    
190     The script, when invoked, adds an Atom Entry that describes a change
191     made to the project's repository.
192    
193     =head1 STANDARD INPUT
194    
195     A description for the change must be specified to the standard input.
196     It is used as the plain text content of the atom:content element of
197     the Entry for the change to add.
198    
199     Non-ASCII characters are not supported in this version of this script.
200     Maybe a future version of this script would support UTF-8.
201    
202     =head1 ARGUMENTS
203    
204     There are command-line options for the script. Some of them are
205     required, while the others are optional. As a general rule, an option
206     whose name begins with C<--entry> specifies a property for the Entry
207     to add, while an option whose name begins with C<--feed> specifies a
208     property for the entire Feed. Option values for Feed properties might
209     not be used when updating an existing Feed document.
210    
211     =over 4
212    
213     =item C<--entry-author-mail I<foo@domain.example>> (optional)
214    
215     Specifies the mail address of the person who made a change. It is
216     used as the content of the C<atom:email> element of the C<atom:author>
217     element of the Entry.
218    
219     If this option is not specified, but the standard input includes a
220     ChangeLog entry in the standard GNU format, then the mail address is
221     taken from the ChangeLog entry. Otherwise, C<atom:email> element is
222     not specified.
223    
224     The option value must be an RFC 2822 C<addr-spec> that does not match
225     C<obs-addr-spec> (i.e. standard email address format). Otherwise the
226     generated Feed would be non-conforming.
227    
228     =item C<--entry-author-name I<author-name>> (conditionally required)
229    
230     Specifies the human readable name of the person who made a change. It
231     is used as the content of the C<atom:name> element of the
232     C<atom:author> element of the Entry.
233    
234     If this option is not specified, but the standard input includes a
235     ChangeLog entry in the standard GNU format, then the name is taken
236     from the ChangeLog entry. If the standard input does not include a
237     GNU format ChangeLog entry, then the C<--entry-author-name> option
238     must be specified.
239    
240     Non-ASCII characters are not supported in this version of this script.
241    
242     =item C<--entry-content I<description>> (optional)
243    
244     Specifies the description of the change. It is used as the content of
245     the C<atom:content> element of the Entry, with C<type=text>.
246    
247     If this option is specified, its value is used as if it were from the
248     standard input and the actual standard input, if any, is ignored. If
249     neither this option nor the standard input is specified, then the
250     description is assumed as the empty string.
251    
252     Non-ASCII characters are not supported in this version of this script.
253    
254     =item C<--entry-title I<title>> (optional)
255    
256     Specifies the title of the change. It is used as the content of the
257     C<atom:title> element of the Entry, with C<type=text>.
258    
259     If this option is not specified, then the date of the change, as well
260     as the name of the author, is used as title.
261    
262     Non-ASCII characters are not supported in this version of this script.
263    
264     =item C<--feed-author-mail I<foo@domain.example>> (optional)
265    
266     Specifies the mail address of the author of the Feed. It is used as
267     the content of the C<atom:email> element of the C<atom:author> element
268     of the Feed.
269    
270     This option is ignored if the C<--feed-author-name> option is not
271     specified.
272    
273     If this option is not specified, C<atom:email> element is not
274     specified.
275    
276     The option value must be an RFC 2822 C<addr-spec> that does not match
277     C<obs-addr-spec> (i.e. standard email address format). Otherwise the
278     generated Feed would be non-conforming.
279    
280     This option is ignored if the Feed already has an C<atom:author>
281     element.
282    
283     =item C<--feed-author-name I<author-name>> (optional)
284    
285     Specifies the human readable name of the author of the Feed. It is
286     used as the content of the C<atom:name> element of the C<atom:author>
287     element of the Feed.
288    
289     If this option is not specified, the C<atom:author> element is not
290     specified in the Feed.
291    
292     Non-ASCII characters are not supported in this version of this script.
293    
294     This option is ignored if the Feed already has an C<atom:author>
295     element.
296    
297     =item C<--feed-author-url I<url>> (optional)
298    
299     Specifies the URI for the author (e.g. URL of the Web page for the
300     author). It is used as the content of the C<atom:uri> element of the
301     C<atom:author> element of the Feed.
302    
303     If the C<--feed-author-name> option is not specified, this option is
304     ignored.
305    
306     If this option is not specified, the C<atom:uri> element is not
307     specified.
308    
309     The option value must be a URI reference conforming to RFC 3986. It
310     should be an absolute reference unless you understand what is the base
311     URL that is used to resolve a relative reference. Non-ASCII
312     characters (i.e. IRI references) are not supported in this version of
313     this script.
314    
315     This option is ignored if the Feed already has an C<atom:author>
316     element.
317    
318     =item C<--feed-lang I<langtag>> (optional)
319    
320     Specifies the natural language used in textual parts of the Feed. It
321     is used as the value of C<xml:lang> attribute of the root element of
322     the Feed.
323    
324     If this option is not specified, the default value I<i-default> is used.
325    
326     This option is ignored if the Feed already exists and has a
327     C<atom:link> element.
328    
329     =item C<--feed-license-url I<url>> (optional)
330    
331     Specifies the URL that describes the license of the Feed. It is used
332     as the C<href> attribute value of an C<atom:link> element whose C<rel>
333     is C<license>.
334    
335     If this option is not specified, the C<atom:link> element whose C<rel>
336     is C<license> is not specified.
337    
338     The option value must be a URI reference conforming to RFC 3986. It
339     should be an absolute reference unless you understand what is the base
340     URL that is used to resolve a relative reference. Non-ASCII
341     characters (i.e. IRI references) are not supported in this version of
342     this script.
343    
344     This option is ignored if the Feed already has a C<atom:link>
345     element.
346    
347     =item C<--feed-related-url I<url>> (optional)
348    
349     Specifies a related URL for the Feed. Usually the URL for the project
350     Web page should be specified. It is used as the C<href> attribute
351     value of an C<atom:link> element whose C<rel> is C<related>.
352    
353     If this option is not specified, the C<atom:link> element whose C<rel>
354     is C<related> is not specified.
355    
356     The option value must be a URI reference conforming to RFC 3986. It
357     should be an absolute reference unless you understand what is the base
358     URL that is used to resolve a relative reference. Non-ASCII
359     characters (i.e. IRI references) are not supported in this version of
360     this script.
361    
362     This option is ignored if the Feed already has a C<atom:link>
363     element.
364    
365     =item C<--feed-rights C<license-terms>> (optional)
366    
367     Specifies the license terms for the Feed. It is used as the content
368     of the C<atom:rights> element of the Feed.
369    
370     If there is the C<atom:rights> element exists, its value is replaced
371     by the value of this option.
372    
373     If this option is not specified, the C<atom:rights> element is not
374     added. If there are already the C<atom:rights> element specified,
375     however, it is not removed from the Feed.
376    
377     Non-ASCII characters are not supported in this version of this script.
378    
379     =item C<--feed-title C<title>> (optional)
380    
381     Specifies the title of the Feed. It is used as the content of the
382     C<atom:title> of the Feed.
383    
384     If this option is not specified, the default value "ChangeLog" is used.
385    
386     If there is Feed exists, then this option is ignored.
387    
388     Non-ASCII characters are not supported in this version of this script.
389    
390     =item C<--feed-url C<url>> (required)
391    
392     Specifies the URL of the Feed itself. It is used in various places,
393     such as in the C<href> attribute of the C<atom:link> element whose
394     C<rel> is C<self>.
395    
396     The option value must be a URI reference conforming to RFC 3986. It
397     should be an absolute reference unless you understand what is the base
398     URL that is used to resolve a relative reference. Non-ASCII
399     characters (i.e. IRI references) are not supported in this version of
400     this script.
401    
402     =item C<--file-name C<path-to-atom-file>> (required)
403    
404     Specifies the path to the file that contains the Atom Feed.
405    
406     If the specified file is not found, then a new file is created.
407     Otherwise, the existing file is loaded as an Atom Feed and then it is
408     updated.
409    
410     The file, if exists, must be encoded in UTF-8. The new content of the
411     file generated by this script is encoded in UTF-8.
412    
413     =item C<--help>
414    
415     Shows a help message and aborts.
416    
417     =back
418    
419 wakaba 1.4 =head1 DEPENDENCY
420    
421     For the execution of C<mkcommitfeed.pl>, the libiraries below are
422     required, as well as Perl 5.10.0 or later:
423    
424     manakai-core L<http://suika.fam.cx/www/manakai-core/doc/web/>
425    
426     Whatpm L<http://suika.fam.cx/www/markup/html/whatpm/readme>
427    
428     =head1 DOWNLOAD
429    
430     The latest version of this script is available from the CVS
431     repository: L<http://suika.fam.cx/gate/cvs/webroot/commitfeed/>.
432    
433     A gzipped tarball for the files is also available:
434     L<http://suika.fam.cx/gate/cvs/webroot/commitfeed/commitfeed.tar.gz?tarball=1>.
435    
436     =head1 SEE ALSO
437    
438     The C<mkcommitfeed.pl> Web site
439     L<http://suika.fam.cx/commitfeed/readme>.
440 wakaba 1.3
441     =head1 AUTHOR
442    
443     Wakaba <w@suika.fam.cx>.
444    
445     =head1 HISTORY
446    
447     This module was originally developed as part of Whatpm
448     L<http://suika.fam.cx/www/markup/html/whatpm/readme>.
449    
450     An Atom Feed for updates for this script, which is itself generated by
451     this script, is available at
452     L<http://suika.fam.cx/commitfeed/commitfeed-commit>.
453    
454     =head1 LICENSE
455    
456     Copyright 2008 Wakaba <w@suika.fam.cx>
457    
458     This program is free software; you can redistribute it and/or
459     modify it under the same terms as Perl itself.
460    
461     =cut
462    
463 wakaba 1.5 ## $Date: 2008/11/24 06:31:25 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24