summaryrefslogtreecommitdiff
path: root/make_patchnum.pl
blob: 5b85b51bc70c4ecb71b8aa6971198b1a6253b93c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
=head1 NAME

make_patchnum.pl - make patchnum

=head1 SYNOPSIS

...

=cut

use strict;
use warnings;
no warnings 'uninitialized';

my $existing_patchnum = read_file('.patchnum');
my $existing_config   = read_file('lib/Config_git.pl');
my $existing_unpushed = read_file('unpushed.h');

my $unpushed_commits = '/*no-op*/';
my ($read, $branch, $snapshot_created, $commit_id, $describe);
my ($changed, $extra_info, $commit_title, $new_patchnum);
if (-s path_to('.patch')) {
    open my $fh, '<', path_to('.patch') or die "Failed to read .patch:$!";
    ($read, $branch, $snapshot_created, $commit_id, $describe) = map { chomp $_; $_ } <$fh>;
    $changed = '';
    $extra_info = "git_snapshot_date='$snapshot_created'";
    $commit_title = "Snapshot of:";
}
elsif (-d path_to('.git')) {
    # git branch | awk 'BEGIN{ORS=""} /\*/ { print $2 }'
    $branch = join "", map { (split /\s/, $_)[1] }
              grep {/\*/} split /\n/, backtick('git branch');
    my $remote;
    if (length $branch) {
        $remote = backtick("git config branch.$branch.remote");
    }
    $commit_id = backtick("git rev-parse HEAD");
    $describe = backtick("git describe --tags");
    my $commit_created = backtick(qq{git log -1 --pretty="format:%ci"});
    $new_patchnum = "describe: $describe";
    $extra_info = "git_commit_date='$commit_created'";
    if (length $branch && length $remote) {
        # git cherry $remote/$branch | awk 'BEGIN{ORS=","} /\+/ {print $2}' | sed -e 's/,$//'
        my $unpushed_commit_list =
            join ",", map { (split /\s/, $_)[1] }
            grep {/\+/} split /\n/, backtick("git cherry $remote/$branch");
        # git cherry $remote/$branch | awk 'BEGIN{ORS="\t\\\\\n"} /\+/ {print ",\"" $2 "\""}'
        $unpushed_commits = 
            join "", map { ',"'.(split /\s/, $_)[1].'"'."\t\\\n" }
            grep {/\+/} split /\n/, backtick("git cherry $remote/$branch");
        if (length $unpushed_commits) {
            $commit_title = "Local Commit:";
            my $ancestor = backtick("git rev-parse $remote/$branch");
            $extra_info = "$extra_info
git_ancestor='$ancestor'
git_unpushed='$unpushed_commit_list'";
        }
    }
    if (length $changed) {
        $changed = 'true';
        $commit_title =  "Derived from:";
        $new_patchnum = "$new_patchnum
status: uncommitted-changes";
    }
    if (not length $commit_title) {
        $commit_title = "Commit id:";
    }
}

my $new_unpushed =<<"EOFTEXT";
/*********************************************************************
* WARNING: unpushed.h is automatically generated by make_patchnum.pl *
*          DO NOT EDIT DIRECTLY - edit make_patchnum.pl instead      *
*********************************************************************/
#define PERL_GIT_UNPUSHED_COMMITS       $unpushed_commits
/*leave-this-comment*/
EOFTEXT

my $new_config =<<"EOFDATA";
#################################################################
# WARNING: lib/Config_git.pl is generated by make_patchnum.pl   #
#          DO NOT EDIT DIRECTLY - edit make_patchnum.pl instead #
#################################################################
\$Config::Git_Data=<<'ENDOFGIT';
git_commit_id='$commit_id'
git_describe='$describe'
git_branch='$branch'
git_uncommitted_changes='$changed'
git_commit_id_title='$commit_title'
$extra_info
ENDOFGIT
EOFDATA

# only update the files if necessary, other build product depends on these files
if (( $existing_patchnum ne $new_patchnum ) || ( $existing_config ne $new_config ) || ( $existing_unpushed ne $new_unpushed )) {
    print "Updating .patchnum and lib/Config_git.pl\n";
    write_file('.patchnum', $new_patchnum);
    write_file('lib/Config_git.pl', $new_config);
    write_file('unpushed.h', $new_unpushed);
}
else {
    print "Reusing .patchnum and lib/Config_git.pl\n"
}

sub path_to { "../$_[0]" } # use $_[0] if this'd be placed in toplevel.

sub read_file {
    my $file = shift;
    return unless -f path_to($file);
    open my $fh, '<', path_to($file) or die "Failed to open $file:$!";
    return do { local $/; <$fh> };
}

sub write_file {
    my ($file, $content) = @_;
    open my $fh, '>', path_to($file) or die "Failed to open $file:$!";
    print $fh $content;
    close $fh;
}

sub backtick {
    my $command = shift;
    my $result = `$command`;
    chomp $result;
    return $result;
}