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

Contents of /webroot/commitfeed/mkcommitfeed.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (show 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 #!/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 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 {
160 open my $file, '>:utf8', $file_name or die "$0: $file_name: $!";
161 print $file $doc->inner_html;
162 }
163
164 ## $Date: 2008/11/24 06:31:25 $
165
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 =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
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 ## $Date: 2008/11/24 06:31:25 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24