2 # Copyright (C) 2019-2020 all contributors <meta@public-inbox.org>
3 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
4 # Generates NEWS, NEWS.atom, and NEWS.html files using release emails
5 # this uses unstable internal APIs of public-inbox, and this script
6 # needs to be updated if they change.
10 use PublicInbox::MsgTime qw(msg_datestamp);
11 use PublicInbox::MID qw(mids mid_escape);
12 END { $INC{'Plack/Util.pm'} and warn "$0 should not have loaded Plack::Util\n" }
13 my $dst = shift @ARGV or die "Usage: $0 <NEWS|NEWS.atom|NEWS.html>";
17 my $dir = 'Documentation/RelNotes';
18 my $base_url = 'https://public-inbox.org/meta';
19 my $html_url = 'https://public-inbox.org/NEWS.html';
20 my $atom_url = 'https://public-inbox.org/NEWS.atom';
21 my $addr = 'meta@public-inbox.org';
23 my $latest = shift(@releases) or die 'no releases?';
25 my $mime_latest = release2mime($latest, \$mtime);
29 open $out, '>:encoding(utf8)', $tmp or die;
30 mime2txt($out, $mime_latest);
31 for my $v (@releases) {
32 print $out "\n" or die;
33 mime2txt($out, release2mime($v));
35 } elsif ($dst eq 'NEWS.atom' || $dst eq 'NEWS.html') {
36 open $out, '>', $tmp or die;
37 my $ibx = My::MockObject->new(
38 description => 'public-inbox releases',
40 search => 1, # for WwwStream::html_top
41 base_url => "$base_url/",
43 $ibx->{-primary_address} = $addr;
46 -upfx => "$base_url/",
49 if ($dst eq 'NEWS.html') {
50 html_start($out, $ctx);
51 mime2html($out, $mime_latest, $ctx);
52 while (defined(my $v = shift(@releases))) {
53 mime2html($out, release2mime($v), $ctx);
56 } elsif ($dst eq 'NEWS.atom') {
57 my $astream = atom_start($out, $ctx, $mtime);
58 for my $v (reverse(@releases)) {
59 mime2atom($out, $astream, release2mime($v), $ctx);
61 mime2atom($out, $astream, $mime_latest, $ctx);
62 print $out '</feed>' or die;
64 die "BUG: Unrecognized $dst\n";
67 die "Unrecognized $dst\n";
71 utime($mtime, $mtime, $tmp) or die;
72 rename($tmp, $dst) or die;
76 my ($release, $mtime_ref) = @_;
77 my $f = "$dir/$release.eml";
78 open(my $fh, '<', $f) or die "open($f): $!";
79 my $mime = PublicInbox::Eml->new(\(do { local $/; <$fh> }));
80 # Documentation/include.mk relies on mtimes of each .eml file
81 # to trigger rebuild, so make sure we sync the mtime to the Date:
83 my $mtime = msg_datestamp($mime->header_obj);
84 utime($mtime, $mtime, $fh) or warn "futimes $f: $!";
85 $$mtime_ref = $mtime if $mtime_ref;
90 my ($out, $mime) = @_;
91 my $title = $mime->header('Subject');
92 $title =~ s/^\s*\[\w+\]\s*//g; # [ANNOUNCE] or [ANN]
93 my $dtime = msg_datestamp($mime->header_obj);
94 $title .= ' - ' . PublicInbox::View::fmt_ts($dtime) . ' UTC';
95 print $out $title, "\n" or die;
96 my $uline = '=' x length($title);
97 print $out $uline, "\n\n" or die;
99 my $mid = mids($mime)->[0];
100 print $out 'Link: ', $base_url, '/', mid_escape($mid), "/\n\n" or die;
101 print $out $mime->body_str or die;
105 my ($out, $eml, $ctx) = @_;
106 my $smsg = $ctx->{smsg} = bless {}, 'PublicInbox::Smsg';
107 $smsg->populate($eml);
108 $ctx->{msgs} = [ 1 ]; # for <hr> in eml_entry
109 print $out PublicInbox::View::eml_entry($ctx, $eml) or die;
113 my ($out, $ctx) = @_;
114 require PublicInbox::WwwStream;
115 $ctx->{www} = My::MockObject->new(style => '');
116 my $www_stream = PublicInbox::WwwStream::init($ctx);
117 print $out $www_stream->html_top, '<pre>' or die;
121 print $out <<EOF or die;
122 git clone $PublicInbox::WwwStream::CODE_URL
128 my ($out, $ctx, $mtime) = @_;
129 require PublicInbox::WwwAtomStream;
130 # WwwAtomStream stats this dir for mtime
131 my $astream = PublicInbox::WwwAtomStream->new($ctx);
132 delete $astream->{emit_header};
133 my $ibx = $ctx->{-inbox};
134 my $title = PublicInbox::WwwAtomStream::title_tag($ibx->description);
135 my $updated = PublicInbox::WwwAtomStream::feed_updated($mtime);
136 print $out <<EOF or die;
137 <?xml version="1.0" encoding="us-ascii"?>
139 xmlns="http://www.w3.org/2005/Atom"
140 xmlns:thr="http://purl.org/syndication/thread/1.0">$title<link
143 href="$html_url"/><link
145 href="$atom_url"/><id>$atom_url</id>$updated
151 my ($out, $astream, $eml, $ctx) = @_;
152 my $smsg = bless {}, 'PublicInbox::Smsg';
153 $smsg->populate($eml);
154 if (defined(my $str = $astream->feed_entry($smsg, $eml))) {
155 print $out $str or die;
158 package My::MockObject;
163 my ($class, %values) = @_;
164 bless \%values, $class;
169 my $attr = (split(/::/, $AUTOLOAD))[-1];