xref: /rk3399_rockchip-uboot/scripts/fill_scrapyard.py (revision 478d9372d19019891966ff0e8f709cf940b0ba56)
1*478d9372SMasahiro Yamada#!/usr/bin/env python2
2*478d9372SMasahiro Yamada#
3*478d9372SMasahiro Yamada# Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
4*478d9372SMasahiro Yamada#
5*478d9372SMasahiro Yamada# SPDX-License-Identifier:	GPL-2.0+
6*478d9372SMasahiro Yamada#
7*478d9372SMasahiro Yamada
8*478d9372SMasahiro Yamada"""
9*478d9372SMasahiro YamadaFill the "Commit" and "Removed" fields of doc/README.scrapyard
10*478d9372SMasahiro Yamada
11*478d9372SMasahiro YamadaThe file doc/README.scrapyard is used to keep track of removed boards.
12*478d9372SMasahiro Yamada
13*478d9372SMasahiro YamadaWhen we remove support for boards, we are supposed to add entries to
14*478d9372SMasahiro Yamadadoc/README.scrapyard leaving "Commit" and "Removed" fields blank.
15*478d9372SMasahiro Yamada
16*478d9372SMasahiro YamadaThe "Commit" field is the commit hash in which the board was removed
17*478d9372SMasahiro Yamadaand the "Removed" is the date at which the board was removed.  Those
18*478d9372SMasahiro Yamadatwo are known only after the board removal patch was applied, thus they
19*478d9372SMasahiro Yamadaneed to be filled in later.
20*478d9372SMasahiro Yamada
21*478d9372SMasahiro YamadaThis effectively means that the person who removes other boards is
22*478d9372SMasahiro Yamadasupposed to fill in the blank fields before adding new entries to
23*478d9372SMasahiro Yamadadoc/README.scrapyard.
24*478d9372SMasahiro Yamada
25*478d9372SMasahiro YamadaThat is a really tedious task that should be automated.
26*478d9372SMasahiro YamadaThis script fills the blank fields of doc/README.scrapyard for you!
27*478d9372SMasahiro Yamada
28*478d9372SMasahiro YamadaUsage:
29*478d9372SMasahiro Yamada
30*478d9372SMasahiro YamadaThe "Commit" and "Removed" fields must be "-".  The other fields should
31*478d9372SMasahiro Yamadahave already been filled in by a former commit.
32*478d9372SMasahiro Yamada
33*478d9372SMasahiro YamadaRun
34*478d9372SMasahiro Yamada    scripts/fill_scrapyard.py
35*478d9372SMasahiro Yamada"""
36*478d9372SMasahiro Yamada
37*478d9372SMasahiro Yamadaimport os
38*478d9372SMasahiro Yamadaimport subprocess
39*478d9372SMasahiro Yamadaimport sys
40*478d9372SMasahiro Yamadaimport tempfile
41*478d9372SMasahiro Yamada
42*478d9372SMasahiro YamadaDOC='doc/README.scrapyard'
43*478d9372SMasahiro Yamada
44*478d9372SMasahiro Yamadadef get_last_modify_commit(file, line_num):
45*478d9372SMasahiro Yamada    """Get the commit that last modified the given line.
46*478d9372SMasahiro Yamada
47*478d9372SMasahiro Yamada    This function runs "git blame" against the given line of the given
48*478d9372SMasahiro Yamada    file and returns the commit hash that last modified it.
49*478d9372SMasahiro Yamada
50*478d9372SMasahiro Yamada    Arguments:
51*478d9372SMasahiro Yamada      file: the file to be git-blame'd.
52*478d9372SMasahiro Yamada      line_num: the line number to be git-blame'd.  This line number
53*478d9372SMasahiro Yamada                starts from 1, not 0.
54*478d9372SMasahiro Yamada
55*478d9372SMasahiro Yamada    Returns:
56*478d9372SMasahiro Yamada      Commit hash that last modified the line.  The number of digits is
57*478d9372SMasahiro Yamada      long enough to form a unique commit.
58*478d9372SMasahiro Yamada    """
59*478d9372SMasahiro Yamada    result = subprocess.check_output(['git', 'blame', '-L',
60*478d9372SMasahiro Yamada                                      '%d,%d' % (line_num, line_num), file])
61*478d9372SMasahiro Yamada    commit = result.split()[0]
62*478d9372SMasahiro Yamada
63*478d9372SMasahiro Yamada    if commit[0] == '^':
64*478d9372SMasahiro Yamada        sys.exit('%s: line %d: ' % (file, line_num) +
65*478d9372SMasahiro Yamada                 'this line was modified before the beginning of git history')
66*478d9372SMasahiro Yamada
67*478d9372SMasahiro Yamada    if commit == '0' * len(commit):
68*478d9372SMasahiro Yamada        sys.exit('%s: line %d: locally modified\n' % (file, line_num) +
69*478d9372SMasahiro Yamada                 'Please run this script in a clean repository.')
70*478d9372SMasahiro Yamada
71*478d9372SMasahiro Yamada    return commit
72*478d9372SMasahiro Yamada
73*478d9372SMasahiro Yamadadef get_committer_date(commit):
74*478d9372SMasahiro Yamada    """Get the committer date of the given commit.
75*478d9372SMasahiro Yamada
76*478d9372SMasahiro Yamada    This function returns the date when the given commit was applied.
77*478d9372SMasahiro Yamada
78*478d9372SMasahiro Yamada    Arguments:
79*478d9372SMasahiro Yamada      commit: commit-ish object.
80*478d9372SMasahiro Yamada
81*478d9372SMasahiro Yamada    Returns:
82*478d9372SMasahiro Yamada      The committer date of the given commit in the form YY-MM-DD.
83*478d9372SMasahiro Yamada    """
84*478d9372SMasahiro Yamada    committer_date = subprocess.check_output(['git', 'show', '-s',
85*478d9372SMasahiro Yamada                                              '--format=%ci', commit])
86*478d9372SMasahiro Yamada    return committer_date.split()[0]
87*478d9372SMasahiro Yamada
88*478d9372SMasahiro Yamadadef move_to_topdir():
89*478d9372SMasahiro Yamada    """Change directory to the top of the git repository.
90*478d9372SMasahiro Yamada
91*478d9372SMasahiro Yamada    Or, exit with an error message if called out of a git repository.
92*478d9372SMasahiro Yamada    """
93*478d9372SMasahiro Yamada    try:
94*478d9372SMasahiro Yamada        toplevel = subprocess.check_output(['git', 'rev-parse',
95*478d9372SMasahiro Yamada                                            '--show-toplevel'])
96*478d9372SMasahiro Yamada    except subprocess.CalledProcessError:
97*478d9372SMasahiro Yamada        sys.exit('Please run in a git repository.')
98*478d9372SMasahiro Yamada
99*478d9372SMasahiro Yamada    # strip '\n'
100*478d9372SMasahiro Yamada    toplevel = toplevel.rstrip()
101*478d9372SMasahiro Yamada
102*478d9372SMasahiro Yamada    # Change the current working directory to the toplevel of the respository
103*478d9372SMasahiro Yamada    # for our easier life.
104*478d9372SMasahiro Yamada    os.chdir(toplevel)
105*478d9372SMasahiro Yamada
106*478d9372SMasahiro Yamadaclass TmpFile:
107*478d9372SMasahiro Yamada
108*478d9372SMasahiro Yamada    """Useful class to handle a temporary file.
109*478d9372SMasahiro Yamada
110*478d9372SMasahiro Yamada    tempfile.mkstemp() is often used to create a unique temporary file,
111*478d9372SMasahiro Yamada    but what is inconvenient is that the caller is responsible for
112*478d9372SMasahiro Yamada    deleting the file when done with it.
113*478d9372SMasahiro Yamada
114*478d9372SMasahiro Yamada    Even when the caller errors out on the way, the temporary file must
115*478d9372SMasahiro Yamada    be deleted somehow.  The idea here is that we delete the file in
116*478d9372SMasahiro Yamada    the destructor of this class because the destructor is always
117*478d9372SMasahiro Yamada    invoked when the instance of the class is freed.
118*478d9372SMasahiro Yamada    """
119*478d9372SMasahiro Yamada
120*478d9372SMasahiro Yamada    def __init__(self):
121*478d9372SMasahiro Yamada        """Constructor - create a temporary file"""
122*478d9372SMasahiro Yamada        fd, self.filename = tempfile.mkstemp()
123*478d9372SMasahiro Yamada        self.file = os.fdopen(fd, 'w')
124*478d9372SMasahiro Yamada
125*478d9372SMasahiro Yamada    def __del__(self):
126*478d9372SMasahiro Yamada        """Destructor - delete the temporary file"""
127*478d9372SMasahiro Yamada        try:
128*478d9372SMasahiro Yamada            os.remove(self.filename)
129*478d9372SMasahiro Yamada        except:
130*478d9372SMasahiro Yamada            pass
131*478d9372SMasahiro Yamada
132*478d9372SMasahiro Yamadadef main():
133*478d9372SMasahiro Yamada    move_to_topdir()
134*478d9372SMasahiro Yamada
135*478d9372SMasahiro Yamada    line_num = 1
136*478d9372SMasahiro Yamada
137*478d9372SMasahiro Yamada    tmpfile = TmpFile()
138*478d9372SMasahiro Yamada    for line in open(DOC):
139*478d9372SMasahiro Yamada        tmp = line.split(None, 5)
140*478d9372SMasahiro Yamada        modified = False
141*478d9372SMasahiro Yamada
142*478d9372SMasahiro Yamada        if len(tmp) >= 5:
143*478d9372SMasahiro Yamada            # fill "Commit" field
144*478d9372SMasahiro Yamada            if tmp[3] == '-':
145*478d9372SMasahiro Yamada                tmp[3] = get_last_modify_commit(DOC, line_num)
146*478d9372SMasahiro Yamada                modified = True
147*478d9372SMasahiro Yamada            # fill "Removed" field
148*478d9372SMasahiro Yamada            if tmp[4] == '-':
149*478d9372SMasahiro Yamada                tmp[4] = get_committer_date(tmp[3])
150*478d9372SMasahiro Yamada            if modified:
151*478d9372SMasahiro Yamada                line  = tmp[0].ljust(17)
152*478d9372SMasahiro Yamada                line += tmp[1].ljust(12)
153*478d9372SMasahiro Yamada                line += tmp[2].ljust(15)
154*478d9372SMasahiro Yamada                line += tmp[3].ljust(12)
155*478d9372SMasahiro Yamada                line += tmp[4].ljust(12)
156*478d9372SMasahiro Yamada                if len(tmp) >= 6:
157*478d9372SMasahiro Yamada                    line += tmp[5]
158*478d9372SMasahiro Yamada                line = line.rstrip() + '\n'
159*478d9372SMasahiro Yamada
160*478d9372SMasahiro Yamada        tmpfile.file.write(line)
161*478d9372SMasahiro Yamada        line_num += 1
162*478d9372SMasahiro Yamada
163*478d9372SMasahiro Yamada    os.rename(tmpfile.filename, DOC)
164*478d9372SMasahiro Yamada
165*478d9372SMasahiro Yamadaif __name__ == '__main__':
166*478d9372SMasahiro Yamada    main()
167