f097513063545a5c9348a570591df05c3e295ace
[exim.git] / release-process / micro-release
1 #!/usr/bin/perl
2
3 use v5.10.1;
4 use strict;
5 use warnings;
6 use feature 'say';
7 use Getopt::Long;
8 use File::Temp qw(tempfile);
9 use Pod::Usage;
10
11 my $BRANCH_PATTERN = qr/^
12     (?<base>(?<name>exim)-
13     (?<version>
14     (?<major>\d+)
15     _(?<minor>\d+)
16     )(?:_(?<security>\d+))?
17     )\+fixes/x;
18
19 sub trim { return join '', shift =~ /^\s*(.*?)\s*$/; }
20
21 my %o = (edit => 1, dotted => 1, force => 0, auto => 0);
22
23 GetOptions(
24     \%o,
25     'edit!',
26     'dotted!',
27     'force!', 'auto!',
28     'help|h' => sub { pod2usage(-verbose => 1, -exit => 0) },
29     'man|m'  => sub {
30         pod2usage(
31             -verbose   => 2,
32             -exit      => 0,
33             -noperldoc => system('perldoc -V >/dev/null 2>&1')
34         );
35     },
36 ) or pod2usage;
37
38 my $branch = trim `git rev-parse --abbrev-ref HEAD`;    # exim-4_90+fixes
39 die "$0: Branch `$branch` does not match `$BRANCH_PATTERN`"
40   unless "$branch" =~ /$BRANCH_PATTERN/;
41
42 my $name = $+{name};
43 my $base = $+{base};    # exim-4_90 (branch base)
44
45 my $release_legacy = $+{version} . ($+{security} // '_0');    # 4.90_0
46 my $release_dotted = join '.', $+{major}, $+{minor}, $+{security} // 0; # 4.90.0
47
48 my $distance = trim `git rev-list --count $base..`;
49
50 my $micro_legacy = "${release_legacy}_$distance";    # 4_90_0_20
51 my $micro_dotted = "${release_dotted}.$distance";    # 4.90.0.20
52
53 my $tag = "$name-" . ($o{dotted} ? $micro_dotted : $micro_legacy);
54
55 # my $commit = trim `git show --no-patch --pretty=format:%h`;
56
57 my ($fh, $filename) = tempfile();
58 print $fh <<XXX;
59 Exim fixup release $micro_dotted
60 # Enter a one line tag description. The above is the sensible default.
61 XXX
62 close $fh;
63
64 system(
65       defined $ENV{VISUAL} ? $ENV{VISUAL}
66     : defined $ENV{EDITOR} ? $ENV{EDITOR}
67     :                        'vi' => $filename
68   ) == 0
69   or exit $?
70   if $o{edit};
71
72 if (not $o{auto}) {
73     print "Commit tag `$tag` to local repository? [Y/n] ";
74     exit 0 unless <STDIN> =~ /^y(?:es)?|$/i;
75 }
76
77 system(
78     git => 'tag',
79     '--sign', ($o{force} ? '--force' : ()),
80     -a => $tag,
81     -F => $filename,
82   ) == 0
83   or exit $?;
84
85 exec git => 'tag',
86   '--verify'    => $tag;
87
88 __END__
89
90 =head1 NAME
91
92  micro-release - tag the current commit on a +fixes branch
93
94 =head1 SYNOPSIS
95
96  micro-release [--[no]-edit] [--[no]-dotted] [--force] [TAG]
97
98 =head1 DESCRIPTION
99
100 This tools is for internal use only. It tags the current commit
101 of a F<+fixes> branch as a "micro release".
102
103 The tag is taken from the command line parameter I<TAG> or is calculated from the
104 branch name and the distance to the release tag. The branch name needs
105 to match the branch tag.
106
107     branch tag:    exim-4_90
108     branch name:   exim-4_90+fixes
109     resulting tag: exim-4.90.0.<distance>   (dotted version)
110                    exim-4_90_0_<distance>   (classic version)
111
112     branch tag:    exim-4_90_1   (security release)
113     branch name:   exim-4_90_1+fixes
114     resulting tag: exim-4.90.1.<distance>   (dotted version)
115                    exim-4_90_1_<distance>   (classic version)
116
117 The tag will be GPG signed.
118
119 =head1 OPTIONS
120
121 =over
122
123 =item B<--[no]-edit>
124
125 Spawn or do not spawn an editor. The default message will be "Exim
126 <tagname> fixup release".
127
128 =item B<--dotted>
129
130 Generate a dotted tag name. (default: on)
131
132 =item B<--force>
133
134 (Re)Move an existing tag name. Use with care!
135
136 =item B<-h>|B<--help>
137
138 Short help.
139
140 =item B<-m>|B<--man>
141
142 The manual page.
143
144 =back
145
146 =cut