xref: /aosp_15_r20/external/curl/scripts/release-notes.pl (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl
2*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
3*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
4*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
5*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
6*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
7*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
8*6236dae4SAndroid Build Coastguard Worker#
9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
10*6236dae4SAndroid Build Coastguard Worker#
11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker#
15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker#
19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker#
22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker#
24*6236dae4SAndroid Build Coastguard Worker###########################################################################
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker###############################################
27*6236dae4SAndroid Build Coastguard Worker#
28*6236dae4SAndroid Build Coastguard Worker# ==== How to use this script ====
29*6236dae4SAndroid Build Coastguard Worker#
30*6236dae4SAndroid Build Coastguard Worker# 1. Get recent commits added to RELEASE-NOTES:
31*6236dae4SAndroid Build Coastguard Worker#
32*6236dae4SAndroid Build Coastguard Worker# $ ./scripts/release-notes.pl
33*6236dae4SAndroid Build Coastguard Worker#
34*6236dae4SAndroid Build Coastguard Worker# 2. Edit RELEASE-NOTES and remove all entries that don't belong.  Unused
35*6236dae4SAndroid Build Coastguard Worker# references below will be cleaned up in the next step. Make sure to move
36*6236dae4SAndroid Build Coastguard Worker# "changes" up to the changes section. All entries will by default be listed
37*6236dae4SAndroid Build Coastguard Worker# under bug-fixes as this script can't know where to put them.
38*6236dae4SAndroid Build Coastguard Worker#
39*6236dae4SAndroid Build Coastguard Worker# 3. Run the cleanup script and let it sort the entries and remove unused
40*6236dae4SAndroid Build Coastguard Worker# references from lines you removed in step (2):
41*6236dae4SAndroid Build Coastguard Worker#
42*6236dae4SAndroid Build Coastguard Worker# $ ./scripts/release-notes.pl cleanup
43*6236dae4SAndroid Build Coastguard Worker#
44*6236dae4SAndroid Build Coastguard Worker# 4. Reload RELEASE-NOTES and verify that things look okay. The cleanup
45*6236dae4SAndroid Build Coastguard Worker# procedure can and should be re-run when lines are removed or rephrased.
46*6236dae4SAndroid Build Coastguard Worker#
47*6236dae4SAndroid Build Coastguard Worker# 5. Run ./scripts/contributors.sh and update the contributor list of names
48*6236dae4SAndroid Build Coastguard Worker# The list can also be extended or edited manually.
49*6236dae4SAndroid Build Coastguard Worker#
50*6236dae4SAndroid Build Coastguard Worker# 6. Run ./scripts/delta and update the contributor count at the top, and
51*6236dae4SAndroid Build Coastguard Worker# double-check/update the other counters.
52*6236dae4SAndroid Build Coastguard Worker#
53*6236dae4SAndroid Build Coastguard Worker# 7. Commit the file using "RELEASE-NOTES: synced" as commit message.
54*6236dae4SAndroid Build Coastguard Worker#
55*6236dae4SAndroid Build Coastguard Worker################################################
56*6236dae4SAndroid Build Coastguard Worker
57*6236dae4SAndroid Build Coastguard Workermy $cleanup = ($ARGV[0] eq "cleanup");
58*6236dae4SAndroid Build Coastguard Workermy @gitlog=`git log @^{/RELEASE-NOTES:.synced}..` if(!$cleanup);
59*6236dae4SAndroid Build Coastguard Workermy @releasenotes=`cat RELEASE-NOTES`;
60*6236dae4SAndroid Build Coastguard Worker
61*6236dae4SAndroid Build Coastguard Workermy @o; # the entire new RELEASE-NOTES
62*6236dae4SAndroid Build Coastguard Workermy @refused; # [num] = [2 bits of use info]
63*6236dae4SAndroid Build Coastguard Workermy @refs; # [number] = [URL]
64*6236dae4SAndroid Build Coastguard Workerfor my $l (@releasenotes) {
65*6236dae4SAndroid Build Coastguard Worker    if($l =~ /^ o .*\[(\d+)\]/) {
66*6236dae4SAndroid Build Coastguard Worker        # referenced, set bit 0
67*6236dae4SAndroid Build Coastguard Worker        $refused[$1]=1;
68*6236dae4SAndroid Build Coastguard Worker    }
69*6236dae4SAndroid Build Coastguard Worker    elsif($l =~ /^ \[(\d+)\] = (.*)/) {
70*6236dae4SAndroid Build Coastguard Worker        # listed in a reference, set bit 1
71*6236dae4SAndroid Build Coastguard Worker        $refused[$1] |= 2;
72*6236dae4SAndroid Build Coastguard Worker        $refs[$1] = $2;
73*6236dae4SAndroid Build Coastguard Worker    }
74*6236dae4SAndroid Build Coastguard Worker}
75*6236dae4SAndroid Build Coastguard Worker
76*6236dae4SAndroid Build Coastguard Worker# Return a new fresh reference number
77*6236dae4SAndroid Build Coastguard Workersub getref {
78*6236dae4SAndroid Build Coastguard Worker    for my $r (1 .. $#refs) {
79*6236dae4SAndroid Build Coastguard Worker        if(!$refused[$r] & 1) {
80*6236dae4SAndroid Build Coastguard Worker            return $r;
81*6236dae4SAndroid Build Coastguard Worker        }
82*6236dae4SAndroid Build Coastguard Worker    }
83*6236dae4SAndroid Build Coastguard Worker    # add at the end
84*6236dae4SAndroid Build Coastguard Worker    return $#refs + 1;
85*6236dae4SAndroid Build Coastguard Worker}
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker# '#num'
88*6236dae4SAndroid Build Coastguard Worker# 'num'
89*6236dae4SAndroid Build Coastguard Worker# 'https://github.com/curl/curl/issues/6939'
90*6236dae4SAndroid Build Coastguard Worker# 'https://github.com/curl/curl-www/issues/69'
91*6236dae4SAndroid Build Coastguard Worker# 'https://elsewhere.example.com/discussion'
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Workersub extract {
94*6236dae4SAndroid Build Coastguard Worker    my ($ref)=@_;
95*6236dae4SAndroid Build Coastguard Worker    if($ref =~ /^(\#|)(\d+)/) {
96*6236dae4SAndroid Build Coastguard Worker        # return the plain number
97*6236dae4SAndroid Build Coastguard Worker        return $2;
98*6236dae4SAndroid Build Coastguard Worker    }
99*6236dae4SAndroid Build Coastguard Worker    elsif($ref =~ /^https:\/\/github.com\/curl\/curl\/.*\/(\d+)/) {
100*6236dae4SAndroid Build Coastguard Worker        # return the plain number
101*6236dae4SAndroid Build Coastguard Worker        return $1;
102*6236dae4SAndroid Build Coastguard Worker    }
103*6236dae4SAndroid Build Coastguard Worker    elsif($ref =~ /:\/\//) {
104*6236dae4SAndroid Build Coastguard Worker        # contains a '://', return the URL
105*6236dae4SAndroid Build Coastguard Worker        return $ref;
106*6236dae4SAndroid Build Coastguard Worker    }
107*6236dae4SAndroid Build Coastguard Worker    # false alarm, not a valid line
108*6236dae4SAndroid Build Coastguard Worker}
109*6236dae4SAndroid Build Coastguard Worker
110*6236dae4SAndroid Build Coastguard Workermy $short;
111*6236dae4SAndroid Build Coastguard Workermy $first;
112*6236dae4SAndroid Build Coastguard Workerfor my $l (@gitlog) {
113*6236dae4SAndroid Build Coastguard Worker    chomp $l;
114*6236dae4SAndroid Build Coastguard Worker    if($l =~ /^commit/) {
115*6236dae4SAndroid Build Coastguard Worker        if($first) {
116*6236dae4SAndroid Build Coastguard Worker            onecommit($short);
117*6236dae4SAndroid Build Coastguard Worker        }
118*6236dae4SAndroid Build Coastguard Worker        # starts a new commit
119*6236dae4SAndroid Build Coastguard Worker        undef @fixes;
120*6236dae4SAndroid Build Coastguard Worker        undef @closes;
121*6236dae4SAndroid Build Coastguard Worker        undef @bug;
122*6236dae4SAndroid Build Coastguard Worker        $short = "";
123*6236dae4SAndroid Build Coastguard Worker        $first = 0;
124*6236dae4SAndroid Build Coastguard Worker    }
125*6236dae4SAndroid Build Coastguard Worker    elsif(($l =~ /^    (.*)/) && !$first) {
126*6236dae4SAndroid Build Coastguard Worker        # first line
127*6236dae4SAndroid Build Coastguard Worker        $short = $1;
128*6236dae4SAndroid Build Coastguard Worker        $short =~ s/ ?\[(ci skip|skip ci)\]//g;
129*6236dae4SAndroid Build Coastguard Worker        $first = 1;
130*6236dae4SAndroid Build Coastguard Worker        push @line, $short;
131*6236dae4SAndroid Build Coastguard Worker    }
132*6236dae4SAndroid Build Coastguard Worker    elsif(($l =~ /^    (.*)/) && $first) {
133*6236dae4SAndroid Build Coastguard Worker        # not the first
134*6236dae4SAndroid Build Coastguard Worker        my $line = $1;
135*6236dae4SAndroid Build Coastguard Worker
136*6236dae4SAndroid Build Coastguard Worker        if($line =~ /^Fixes(:|) *(.*)/i) {
137*6236dae4SAndroid Build Coastguard Worker            my $ref = extract($2);
138*6236dae4SAndroid Build Coastguard Worker            push @fixes, $ref if($ref);
139*6236dae4SAndroid Build Coastguard Worker        }
140*6236dae4SAndroid Build Coastguard Worker        elsif($line =~ /^Clo(s|)es(:|) *(.*)/i) {
141*6236dae4SAndroid Build Coastguard Worker            my $ref = extract($3);
142*6236dae4SAndroid Build Coastguard Worker            push @closes, $ref if($ref);
143*6236dae4SAndroid Build Coastguard Worker        }
144*6236dae4SAndroid Build Coastguard Worker        elsif($line =~ /^Bug: (.*)/i) {
145*6236dae4SAndroid Build Coastguard Worker            my $ref = extract($1);
146*6236dae4SAndroid Build Coastguard Worker            push @bug, $ref if($ref);
147*6236dae4SAndroid Build Coastguard Worker        }
148*6236dae4SAndroid Build Coastguard Worker    }
149*6236dae4SAndroid Build Coastguard Worker}
150*6236dae4SAndroid Build Coastguard Workerif($first) {
151*6236dae4SAndroid Build Coastguard Worker    onecommit($short);
152*6236dae4SAndroid Build Coastguard Worker}
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker# call at the end of a parsed commit
155*6236dae4SAndroid Build Coastguard Workersub onecommit {
156*6236dae4SAndroid Build Coastguard Worker    my ($short)=@_;
157*6236dae4SAndroid Build Coastguard Worker    my $ref;
158*6236dae4SAndroid Build Coastguard Worker
159*6236dae4SAndroid Build Coastguard Worker    if($bug[0]) {
160*6236dae4SAndroid Build Coastguard Worker        $ref = $bug[0];
161*6236dae4SAndroid Build Coastguard Worker    }
162*6236dae4SAndroid Build Coastguard Worker    elsif($fixes[0]) {
163*6236dae4SAndroid Build Coastguard Worker        $ref = $fixes[0];
164*6236dae4SAndroid Build Coastguard Worker    }
165*6236dae4SAndroid Build Coastguard Worker    elsif($closes[0]) {
166*6236dae4SAndroid Build Coastguard Worker        $ref = $closes[0];
167*6236dae4SAndroid Build Coastguard Worker    }
168*6236dae4SAndroid Build Coastguard Worker
169*6236dae4SAndroid Build Coastguard Worker    if($ref =~ /^#?(\d+)/) {
170*6236dae4SAndroid Build Coastguard Worker        $ref = "https://curl.se/bug/?i=$1"
171*6236dae4SAndroid Build Coastguard Worker    }
172*6236dae4SAndroid Build Coastguard Worker    if($ref) {
173*6236dae4SAndroid Build Coastguard Worker        my $r = getref();
174*6236dae4SAndroid Build Coastguard Worker        $refs[$r] = $ref;
175*6236dae4SAndroid Build Coastguard Worker        $moreinfo{$short}=$r;
176*6236dae4SAndroid Build Coastguard Worker        $refused[$r] |= 1;
177*6236dae4SAndroid Build Coastguard Worker    }
178*6236dae4SAndroid Build Coastguard Worker}
179*6236dae4SAndroid Build Coastguard Worker
180*6236dae4SAndroid Build Coastguard Worker#### Output the new RELEASE-NOTES
181*6236dae4SAndroid Build Coastguard Worker
182*6236dae4SAndroid Build Coastguard Workermy @bullets;
183*6236dae4SAndroid Build Coastguard Workerfor my $l (@releasenotes) {
184*6236dae4SAndroid Build Coastguard Worker    if(($l =~ /^This release includes the following bugfixes:/) && !$cleanup) {
185*6236dae4SAndroid Build Coastguard Worker        push @o, $l;
186*6236dae4SAndroid Build Coastguard Worker        push @o, "\n";
187*6236dae4SAndroid Build Coastguard Worker        for my $f (@line) {
188*6236dae4SAndroid Build Coastguard Worker            push @o, sprintf " o %s%s\n", $f,
189*6236dae4SAndroid Build Coastguard Worker                $moreinfo{$f}? sprintf(" [%d]", $moreinfo{$f}): "";
190*6236dae4SAndroid Build Coastguard Worker            $refused[$moreinfo{$f}]=3;
191*6236dae4SAndroid Build Coastguard Worker        }
192*6236dae4SAndroid Build Coastguard Worker        push @o, " --- new entries are listed above this ---";
193*6236dae4SAndroid Build Coastguard Worker        next;
194*6236dae4SAndroid Build Coastguard Worker    }
195*6236dae4SAndroid Build Coastguard Worker    elsif($cleanup) {
196*6236dae4SAndroid Build Coastguard Worker        if($l =~ /^ --- new entries are listed/) {
197*6236dae4SAndroid Build Coastguard Worker            # ignore this if still around
198*6236dae4SAndroid Build Coastguard Worker            next;
199*6236dae4SAndroid Build Coastguard Worker        }
200*6236dae4SAndroid Build Coastguard Worker        elsif($l =~ /^ o .*/) {
201*6236dae4SAndroid Build Coastguard Worker            push @bullets, $l;
202*6236dae4SAndroid Build Coastguard Worker            next;
203*6236dae4SAndroid Build Coastguard Worker        }
204*6236dae4SAndroid Build Coastguard Worker        elsif($bullets[0]) {
205*6236dae4SAndroid Build Coastguard Worker            # output them case insensitively
206*6236dae4SAndroid Build Coastguard Worker            for my $b (sort { "\L$a" cmp "\L$b" } @bullets) {
207*6236dae4SAndroid Build Coastguard Worker                push @o, $b;
208*6236dae4SAndroid Build Coastguard Worker            }
209*6236dae4SAndroid Build Coastguard Worker            undef @bullets;
210*6236dae4SAndroid Build Coastguard Worker        }
211*6236dae4SAndroid Build Coastguard Worker    }
212*6236dae4SAndroid Build Coastguard Worker    if($l =~ /^ \[(\d+)\] = /) {
213*6236dae4SAndroid Build Coastguard Worker        # stop now
214*6236dae4SAndroid Build Coastguard Worker        last;
215*6236dae4SAndroid Build Coastguard Worker    }
216*6236dae4SAndroid Build Coastguard Worker    else {
217*6236dae4SAndroid Build Coastguard Worker        push @o, $l;
218*6236dae4SAndroid Build Coastguard Worker    }
219*6236dae4SAndroid Build Coastguard Worker}
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Workermy @srefs;
222*6236dae4SAndroid Build Coastguard Workermy $ln;
223*6236dae4SAndroid Build Coastguard Workerfor my $n (1 .. $#refs) {
224*6236dae4SAndroid Build Coastguard Worker    my $r = $refs[$n];
225*6236dae4SAndroid Build Coastguard Worker    if($r && ($refused[$n] & 1)) {
226*6236dae4SAndroid Build Coastguard Worker        push @o, sprintf " [%d] = %s\n", $n, $r;
227*6236dae4SAndroid Build Coastguard Worker    }
228*6236dae4SAndroid Build Coastguard Worker}
229*6236dae4SAndroid Build Coastguard Worker
230*6236dae4SAndroid Build Coastguard Workeropen(O, ">RELEASE-NOTES");
231*6236dae4SAndroid Build Coastguard Workerfor my $l (@o) {
232*6236dae4SAndroid Build Coastguard Worker    print O $l;
233*6236dae4SAndroid Build Coastguard Worker}
234*6236dae4SAndroid Build Coastguard Workerclose(O);
235*6236dae4SAndroid Build Coastguard Worker
236*6236dae4SAndroid Build Coastguard Workerexit;
237*6236dae4SAndroid Build Coastguard Worker
238*6236dae4SAndroid Build Coastguard Worker# Debug: show unused references
239*6236dae4SAndroid Build Coastguard Workerfor my $r (1 .. $#refs) {
240*6236dae4SAndroid Build Coastguard Worker    if($refused[$r] != 3) {
241*6236dae4SAndroid Build Coastguard Worker        printf "%s is %d!\n", $r, $refused[$r];
242*6236dae4SAndroid Build Coastguard Worker    }
243*6236dae4SAndroid Build Coastguard Worker}
244