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

Contents of /webroot/commitfeed/mkcommitfeed.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations) (download)
Mon Nov 24 06:31:25 2008 UTC (15 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.3: +23 -2 lines
File MIME type: text/plain
++ ChangeLog	24 Nov 2008 06:31:19 -0000
	* .htaccess: AddLangauge was missing.

	* Makefile: Add <link rel=feed> to |readme.html|.

	* mkcommitfeed.pl: Added availability sections to the document.

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     {
152     open my $file, '>:utf8', $file_name or die "$0: $file_name: $!";
153     print $file $doc->inner_html;
154     }
155    
156 wakaba 1.4 ## $Date: 2008/11/24 06:18:00 $
157 wakaba 1.3
158     __END__
159    
160     =head1 NAME
161    
162     mkcommitfeed.pl - Commit Log Feed Generator
163    
164     =head1 SYNOPSIS
165    
166     mkcommitfeed.pl \
167     --file-name filename.atom \
168     --feed-url http://example.com/myproject/filename.atom \
169     --feed-title "MyProject Commit Log" \
170     --feed-lang langtag \
171     --feed-related-url "http://example.com/myproject/" \
172     --feed-license-url "http://example.com/myproject/license" \
173     --feed-rights "Copyright or copyleft statement" \
174     < changes-in-this-revision.txt
175    
176     =head1 DESCRIPTION
177    
178     The C<mkcommitfeed.pl> script provides a command-line interface to
179     update an Atom Feed that is intended for providing commit logs for a
180     software developmenet project.
181    
182     The script, when invoked, adds an Atom Entry that describes a change
183     made to the project's repository.
184    
185     =head1 STANDARD INPUT
186    
187     A description for the change must be specified to the standard input.
188     It is used as the plain text content of the atom:content element of
189     the Entry for the change to add.
190    
191     Non-ASCII characters are not supported in this version of this script.
192     Maybe a future version of this script would support UTF-8.
193    
194     =head1 ARGUMENTS
195    
196     There are command-line options for the script. Some of them are
197     required, while the others are optional. As a general rule, an option
198     whose name begins with C<--entry> specifies a property for the Entry
199     to add, while an option whose name begins with C<--feed> specifies a
200     property for the entire Feed. Option values for Feed properties might
201     not be used when updating an existing Feed document.
202    
203     =over 4
204    
205     =item C<--entry-author-mail I<foo@domain.example>> (optional)
206    
207     Specifies the mail address of the person who made a change. It is
208     used as the content of the C<atom:email> element of the C<atom:author>
209     element of the Entry.
210    
211     If this option is not specified, but the standard input includes a
212     ChangeLog entry in the standard GNU format, then the mail address is
213     taken from the ChangeLog entry. Otherwise, C<atom:email> element is
214     not specified.
215    
216     The option value must be an RFC 2822 C<addr-spec> that does not match
217     C<obs-addr-spec> (i.e. standard email address format). Otherwise the
218     generated Feed would be non-conforming.
219    
220     =item C<--entry-author-name I<author-name>> (conditionally required)
221    
222     Specifies the human readable name of the person who made a change. It
223     is used as the content of the C<atom:name> element of the
224     C<atom:author> element of the Entry.
225    
226     If this option is not specified, but the standard input includes a
227     ChangeLog entry in the standard GNU format, then the name is taken
228     from the ChangeLog entry. If the standard input does not include a
229     GNU format ChangeLog entry, then the C<--entry-author-name> option
230     must be specified.
231    
232     Non-ASCII characters are not supported in this version of this script.
233    
234     =item C<--entry-content I<description>> (optional)
235    
236     Specifies the description of the change. It is used as the content of
237     the C<atom:content> element of the Entry, with C<type=text>.
238    
239     If this option is specified, its value is used as if it were from the
240     standard input and the actual standard input, if any, is ignored. If
241     neither this option nor the standard input is specified, then the
242     description is assumed as the empty string.
243    
244     Non-ASCII characters are not supported in this version of this script.
245    
246     =item C<--entry-title I<title>> (optional)
247    
248     Specifies the title of the change. It is used as the content of the
249     C<atom:title> element of the Entry, with C<type=text>.
250    
251     If this option is not specified, then the date of the change, as well
252     as the name of the author, is used as title.
253    
254     Non-ASCII characters are not supported in this version of this script.
255    
256     =item C<--feed-author-mail I<foo@domain.example>> (optional)
257    
258     Specifies the mail address of the author of the Feed. It is used as
259     the content of the C<atom:email> element of the C<atom:author> element
260     of the Feed.
261    
262     This option is ignored if the C<--feed-author-name> option is not
263     specified.
264    
265     If this option is not specified, C<atom:email> element is not
266     specified.
267    
268     The option value must be an RFC 2822 C<addr-spec> that does not match
269     C<obs-addr-spec> (i.e. standard email address format). Otherwise the
270     generated Feed would be non-conforming.
271    
272     This option is ignored if the Feed already has an C<atom:author>
273     element.
274    
275     =item C<--feed-author-name I<author-name>> (optional)
276    
277     Specifies the human readable name of the author of the Feed. It is
278     used as the content of the C<atom:name> element of the C<atom:author>
279     element of the Feed.
280    
281     If this option is not specified, the C<atom:author> element is not
282     specified in the Feed.
283    
284     Non-ASCII characters are not supported in this version of this script.
285    
286     This option is ignored if the Feed already has an C<atom:author>
287     element.
288    
289     =item C<--feed-author-url I<url>> (optional)
290    
291     Specifies the URI for the author (e.g. URL of the Web page for the
292     author). It is used as the content of the C<atom:uri> element of the
293     C<atom:author> element of the Feed.
294    
295     If the C<--feed-author-name> option is not specified, this option is
296     ignored.
297    
298     If this option is not specified, the C<atom:uri> element is not
299     specified.
300    
301     The option value must be a URI reference conforming to RFC 3986. It
302     should be an absolute reference unless you understand what is the base
303     URL that is used to resolve a relative reference. Non-ASCII
304     characters (i.e. IRI references) are not supported in this version of
305     this script.
306    
307     This option is ignored if the Feed already has an C<atom:author>
308     element.
309    
310     =item C<--feed-lang I<langtag>> (optional)
311    
312     Specifies the natural language used in textual parts of the Feed. It
313     is used as the value of C<xml:lang> attribute of the root element of
314     the Feed.
315    
316     If this option is not specified, the default value I<i-default> is used.
317    
318     This option is ignored if the Feed already exists and has a
319     C<atom:link> element.
320    
321     =item C<--feed-license-url I<url>> (optional)
322    
323     Specifies the URL that describes the license of the Feed. It is used
324     as the C<href> attribute value of an C<atom:link> element whose C<rel>
325     is C<license>.
326    
327     If this option is not specified, the C<atom:link> element whose C<rel>
328     is C<license> is not specified.
329    
330     The option value must be a URI reference conforming to RFC 3986. It
331     should be an absolute reference unless you understand what is the base
332     URL that is used to resolve a relative reference. Non-ASCII
333     characters (i.e. IRI references) are not supported in this version of
334     this script.
335    
336     This option is ignored if the Feed already has a C<atom:link>
337     element.
338    
339     =item C<--feed-related-url I<url>> (optional)
340    
341     Specifies a related URL for the Feed. Usually the URL for the project
342     Web page should be specified. It is used as the C<href> attribute
343     value of an C<atom:link> element whose C<rel> is C<related>.
344    
345     If this option is not specified, the C<atom:link> element whose C<rel>
346     is C<related> is not specified.
347    
348     The option value must be a URI reference conforming to RFC 3986. It
349     should be an absolute reference unless you understand what is the base
350     URL that is used to resolve a relative reference. Non-ASCII
351     characters (i.e. IRI references) are not supported in this version of
352     this script.
353    
354     This option is ignored if the Feed already has a C<atom:link>
355     element.
356    
357     =item C<--feed-rights C<license-terms>> (optional)
358    
359     Specifies the license terms for the Feed. It is used as the content
360     of the C<atom:rights> element of the Feed.
361    
362     If there is the C<atom:rights> element exists, its value is replaced
363     by the value of this option.
364    
365     If this option is not specified, the C<atom:rights> element is not
366     added. If there are already the C<atom:rights> element specified,
367     however, it is not removed from the Feed.
368    
369     Non-ASCII characters are not supported in this version of this script.
370    
371     =item C<--feed-title C<title>> (optional)
372    
373     Specifies the title of the Feed. It is used as the content of the
374     C<atom:title> of the Feed.
375    
376     If this option is not specified, the default value "ChangeLog" is used.
377    
378     If there is Feed exists, then this option is ignored.
379    
380     Non-ASCII characters are not supported in this version of this script.
381    
382     =item C<--feed-url C<url>> (required)
383    
384     Specifies the URL of the Feed itself. It is used in various places,
385     such as in the C<href> attribute of the C<atom:link> element whose
386     C<rel> is C<self>.
387    
388     The option value must be a URI reference conforming to RFC 3986. It
389     should be an absolute reference unless you understand what is the base
390     URL that is used to resolve a relative reference. Non-ASCII
391     characters (i.e. IRI references) are not supported in this version of
392     this script.
393    
394     =item C<--file-name C<path-to-atom-file>> (required)
395    
396     Specifies the path to the file that contains the Atom Feed.
397    
398     If the specified file is not found, then a new file is created.
399     Otherwise, the existing file is loaded as an Atom Feed and then it is
400     updated.
401    
402     The file, if exists, must be encoded in UTF-8. The new content of the
403     file generated by this script is encoded in UTF-8.
404    
405     =item C<--help>
406    
407     Shows a help message and aborts.
408    
409     =back
410    
411 wakaba 1.4 =head1 DEPENDENCY
412    
413     For the execution of C<mkcommitfeed.pl>, the libiraries below are
414     required, as well as Perl 5.10.0 or later:
415    
416     manakai-core L<http://suika.fam.cx/www/manakai-core/doc/web/>
417    
418     Whatpm L<http://suika.fam.cx/www/markup/html/whatpm/readme>
419    
420     =head1 DOWNLOAD
421    
422     The latest version of this script is available from the CVS
423     repository: L<http://suika.fam.cx/gate/cvs/webroot/commitfeed/>.
424    
425     A gzipped tarball for the files is also available:
426     L<http://suika.fam.cx/gate/cvs/webroot/commitfeed/commitfeed.tar.gz?tarball=1>.
427    
428     =head1 SEE ALSO
429    
430     The C<mkcommitfeed.pl> Web site
431     L<http://suika.fam.cx/commitfeed/readme>.
432 wakaba 1.3
433     =head1 AUTHOR
434    
435     Wakaba <w@suika.fam.cx>.
436    
437     =head1 HISTORY
438    
439     This module was originally developed as part of Whatpm
440     L<http://suika.fam.cx/www/markup/html/whatpm/readme>.
441    
442     An Atom Feed for updates for this script, which is itself generated by
443     this script, is available at
444     L<http://suika.fam.cx/commitfeed/commitfeed-commit>.
445    
446     =head1 LICENSE
447    
448     Copyright 2008 Wakaba <w@suika.fam.cx>
449    
450     This program is free software; you can redistribute it and/or
451     modify it under the same terms as Perl itself.
452    
453     =cut
454    
455 wakaba 1.4 ## $Date: 2008/11/24 06:18:00 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24