make-release: Run git describe once
[openafs.git] / build-tools / make-release
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 use Getopt::Long;
6 use Pod::Usage;
7 use File::Path;
8 use File::Temp;
9
10 my $help;
11 my $man;
12 my $tagPoint;
13 my $last;
14 my $outDir = ".";
15
16 GetOptions(
17     "help|?" => \$help,
18     "man" => \$man,
19     "tagpoint=s" => \$tagPoint,
20     "last=s" => \$last,
21     "dir=s" => \$outDir,
22 ) or pod2usage(2);
23
24 pod2usage(1) if $help;
25 pod2usage(-exitstatus => 0, -verbose => 2) if $man;
26
27 my $tagName = shift;
28 my $notused = shift;  # Used to be "version".
29
30 pod2usage(2) if !defined($tagName);
31 if (defined $notused) {
32     warn "Warning: argument '$notused' is ignored.\n";
33 }
34
35 # Tag the repository
36
37 if ($tagPoint) {
38     system ("git tag -s $tagName $tagPoint") == 0
39         or die "git tag failed with : $!";
40
41     # Push the tag upstream
42     system ("git push ssh://gerrit.openafs.org:29418/openafs tag $tagName") == 0
43         or die "git push failed with : $!";
44 }
45
46 my $version = `git describe --abbrev=4 $tagName`;
47 chomp $version;
48 if (!$version) {
49     die "Failed to describe $tagName.\n";
50 }
51 my $suffix = $version;
52 $suffix =~ s/openafs-[^-]*-//;
53 $suffix =~ s/_/./g;
54 my $name = "openafs-$suffix";
55
56 # Grab the tagged code into a temporary directory
57
58 my $tempDir = File::Temp::tempdir();
59 system ("git archive --format=tar --prefix=$name/ $tagName ".
60         " | tar -C $tempDir -x") == 0
61     or die "Git archive failed with: $?";
62
63 # Make the output path, if not already present.
64 File::Path::mkpath($outDir);
65
66 # Construct the ChangeLog
67 if ($last) {
68     system("git log $last..$tagName > $outDir/ChangeLog");
69 } else {
70     system("git log $tagName > $outDir/ChangeLog");
71 }
72
73 # Describe the tree
74 open(my $fh, ">", "$tempDir/$name/.version") or
75     die "Failed to open $tempDir/$name/.version: $!\n";
76 print $fh "$version\n";
77 close($fh);
78
79 # Run regen.sh to create the rest of the tree
80 system ("cd $tempDir/$name && ./regen.sh") == 0
81     or die $!;
82
83 # A list of files to compress
84 my @toCompress;
85
86 # Create the documentation tarball
87 system("tar -cf $outDir/$name-doc.tar -C $tempDir $name/doc") == 0
88     or die "Unable to create documentation tarball : $!";
89 push @toCompress, "$outDir/$name-doc.tar";
90
91 # Remove the docs directory (we've already build a tarball for it)
92 File::Path::rmtree("$tempDir/$name/doc");
93
94 # Create the source tarball (both .gz and .bz2)
95 system("tar -cf $outDir/$name-src.tar -C $tempDir $name") == 0
96     or die "Unable to create source code tarball : $!";
97 push @toCompress, "$outDir/$name-src.tar";
98
99 # Construct the diffs, and zip them
100 if ($last) {
101     system("git diff $last..$tagName > $outDir/$name.diff") == 0
102        or die "Unable to create diff : $!";
103     push @toCompress, "$outDir/$name.diff";
104 }
105
106 my @toMD5;
107
108 # Compress everything that needs squashing,
109 # and also set up a list for md5 checksumming.
110 foreach my $file (@toCompress) {
111     system("gzip < $file > $file.gz") == 0
112         or die "Unable to create gzip file of '$file' : $!";
113     push @toMD5, "$file.gz";
114
115     system("bzip2 < $file > $file.bz2") == 0
116         or die "Unable to create bzip file of '$file' : $!";
117     push @toMD5, "$file.bz2";
118
119     # Delete the uncompressed tar files.
120     if ($file =~ /\.tar$/) {
121       unlink($file);
122     } else {
123       # Otherwise, queue this file for md5 checksumming.
124       push @toMD5, $file;
125     }
126 }
127
128 foreach my $file (@toMD5) {
129     if (-x "/sbin/md5") {
130         system("/sbin/md5 -q $file > $file.md5");
131     } elsif (-x "/usr/bin/md5sum") {
132         system("/usr/bin/md5sum $file > $file.md5");
133     } else {
134         print STDERR "No md5 utility found. Not producing checksums\n";
135     }
136 }
137
138
139 __END__
140
141 =head1 NAME
142
143 make-release - Make an OpenAFS release from git
144
145 =head1 SYNOPSIS
146
147 make-release [options] <tag>
148
149  Options:
150     --help               brief help message
151     --man                full documentation
152     --tagpoint <object>  create new tag
153     --last <object>      generate changelog and diffs from this point
154     --dir <dir>          output results into this directory
155
156 =head1 DESCRIPTION
157
158 make-release constructs an OpenAFS release from a local git clone. If run
159 with just the standard arguments, it will extract the contents of the
160 specified tag into the current directory, creating src and doc tarballs,
161 gzipping and bzipping them, and generating md5 hashes. It will also create a
162 ChangeLog file, listing all of the changes in that release.
163
164 This standard behaviour may be modified by the following options
165
166 =head1 OPTIONS
167
168 =over 8
169
170 =item B<--last> I<object>
171
172 Generate the ChangeLog starting from I<object>. Also generate a
173 openafs-$version.diff file in the output directory containing all of the
174 changes between I<object> and the current tag
175
176 =item B<--dir> I<directory>
177
178 Instead of generating all of the output in the current directory, place it
179 in <directory>, which is created if it does not already exist.
180
181 =item B<--tagpoint> I<commit|branch>
182
183 Rather than using an existing tag, create a new one on the specified commit,
184 or on the tip of the specified branch. This will GPG sign the new tag, and
185 push it into gerrit.
186
187 =back
188
189 =cut