This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
eliminate make_patchnum.sh, and make the build process use make_patchnum.pl instead
[perl5.git] / make_patchnum.pl
1 #!/usr/bin/perl
2 # These two should go upon release to make the script Perl 5.005 compatible
3 use strict;
4 use warnings;
5
6 =head1 NAME
7
8 make_patchnum.pl - make patchnum
9
10 =head1 SYNOPSIS
11
12   miniperl make_patchnum.pl
13
14   perl make_patchnum.pl
15
16 This program creates the files holding the information
17 about locally applied patches to the source code. The created
18 files are C<.patchnum>, C<unpushed.h> and C<lib/Config_git.pl>.
19
20 C<.patchnum> contains ???
21
22 C<lib/Config_git.pl> contains the configuration of git for
23 this branch.
24
25 C<unpushed.h> contains the local changes that haven't been
26 synchronized with the remote repository as configured with
27 C<< git configure branch.<current branch>.remote >>
28
29 =cut
30
31 BEGIN {
32     my $root=".";
33     while (!-e "$root/perl.c" and length($root)<100) {
34         if ($root eq '.') {
35                 $root="..";
36         } else {
37                 $root.="/..";
38             }
39     }
40     die "Can't find toplevel" if !-e "$root/perl.c";
41     sub path_to { "$root/$_[0]" } # use $_[0] if this'd be placed in toplevel.
42 }
43
44 sub read_file {
45     my $file = path_to(@_);
46     return "" unless -e $file;
47     open my $fh, '<', $file
48         or die "Failed to open for read '$file':$!";
49     return do { local $/; <$fh> };
50 }
51
52 sub write_file {
53     my ($file, $content) = @_;
54     $file= path_to($file);
55     open my $fh, '>', $file
56         or die "Failed to open for write '$file':$!";
57     print $fh $content;
58     close $fh;
59 }
60
61 sub backtick {
62     my $command = shift;
63     if (wantarray) {
64         my @result= `$command`;
65         chomp @result;
66         return @result;
67     } else {
68         my $result= `$command`;
69         $result="" if ! defined $result;
70         chomp $result;
71         return $result;
72     }
73 }
74
75 sub write_files {
76     my %content= map { /WARNING: '([^']+)'/ || die "Bad mojo!"; $1 => $_ } @_;
77     my @files= sort keys %content;
78     my $files= join " and ", map { "'$_'" } @files;
79     foreach my $file (@files) { 
80         if (read_file($file) ne $content{$file}) {
81             print "Updating $files\n";
82             write_file($_,$content{$_}) for @files;
83             return 1;
84         } 
85     }
86     print "Reusing $files\n";
87     return 0;
88 }
89
90 my $unpushed_commits = '/*no-op*/';
91 my ($read, $branch, $snapshot_created, $commit_id, $describe)= ("") x 5;
92 my ($changed, $extra_info, $commit_title, $new_patchnum, $status)= ("") x 5;
93 if (my $patch_file= read_file(".patch")) {
94     ($branch, $snapshot_created, $commit_id, $describe) = split /\s+/, $patch_file;
95     $extra_info = "git_snapshot_date='$snapshot_created'";
96     $commit_title = "Snapshot of:";
97 }
98 elsif (-d path_to('.git')) {
99     # git branch | awk 'BEGIN{ORS=""} /\*/ { print $2 }'
100     ($branch) = map { /\* ([^(]\S*)/ ? $1 : () } backtick('git branch');
101     my ($remote,$merge);
102     if (length $branch) {
103         $merge= backtick("git config branch.$branch.merge"); 
104         $merge =~ s!^refs/heads/!!;
105         $remote= backtick("git config branch.$branch.remote");
106     }
107     $commit_id = backtick("git rev-parse HEAD");
108     $describe = backtick("git describe");
109     my $commit_created = backtick(qq{git log -1 --pretty="format:%ci"});
110     $new_patchnum = "describe: $describe";
111     $extra_info = "git_commit_date='$commit_created'";
112     if (length $branch && length $remote) {
113         # git cherry $remote/$branch | awk 'BEGIN{ORS=","} /\+/ {print $2}' | sed -e 's/,$//'
114         my $unpushed_commit_list =
115             join ",", map { (split /\s/, $_)[1] }
116             grep {/\+/} backtick("git cherry $remote/$merge");
117         # git cherry $remote/$branch | awk 'BEGIN{ORS="\t\\\\\n"} /\+/ {print ",\"" $2 "\""}'
118         $unpushed_commits =
119             join "", map { ',"'.(split /\s/, $_)[1]."\"\t\\\n" }
120             grep {/\+/} backtick("git cherry $remote/$merge");
121         if (length $unpushed_commits) {
122             $commit_title = "Local Commit:";
123             my $ancestor = backtick("git rev-parse $remote/$merge");
124             $extra_info = "$extra_info
125 git_ancestor='$ancestor'
126 git_remote_branch='$remote/$merge'
127 git_unpushed='$unpushed_commit_list'";
128         }
129     }
130     if ($changed) {
131         $changed = 'true';
132         $commit_title =  "Derived from:";
133         $status='"uncommitted-changes"'
134     } else {
135         $status='/*clean-working-directory*/'
136     }
137     $commit_title ||= "Commit id:";
138 }
139
140 # we extract the filename out of the warning header, so dont mess with that
141 exit(write_files(<<"EOF_HEADER", <<"EOF_CONFIG"));
142 /**************************************************************************
143 * WARNING: 'git_version.h' is automatically generated by make_patchnum.pl
144 *          DO NOT EDIT DIRECTLY - edit make_patchnum.pl instead
145 ***************************************************************************/
146 #define PERL_GIT_UNCOMMITTED_CHANGES $status
147 #define PERL_PATCHNUM "$describe"
148 #define PERL_GIT_UNPUSHED_COMMITS\t\t\\
149 $unpushed_commits/*leave-this-comment*/
150 EOF_HEADER
151 ######################################################################
152 # WARNING: 'lib/Config_git.pl' is generated by make_patchnum.pl
153 #          DO NOT EDIT DIRECTLY - edit make_patchnum.pl instead
154 ######################################################################
155 \$Config::Git_Data=<<'ENDOFGIT';
156 git_commit_id='$commit_id'
157 git_describe='$describe'
158 git_branch='$branch'
159 git_uncommitted_changes='$changed'
160 git_commit_id_title='$commit_title'
161 $extra_info
162 ENDOFGIT
163 EOF_CONFIG
164 # ex: set ts=4 sts=4 et ft=perl: