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