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