xref: /openbmc/u-boot/scripts/fill_scrapyard.py (revision e8f80a5a)
1478d9372SMasahiro Yamada#!/usr/bin/env python2
2*83d290c5STom Rini# SPDX-License-Identifier: GPL-2.0+
3478d9372SMasahiro Yamada#
4478d9372SMasahiro Yamada# Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
5478d9372SMasahiro Yamada#
6478d9372SMasahiro Yamada
7478d9372SMasahiro Yamada"""
8478d9372SMasahiro YamadaFill the "Commit" and "Removed" fields of doc/README.scrapyard
9478d9372SMasahiro Yamada
10478d9372SMasahiro YamadaThe file doc/README.scrapyard is used to keep track of removed boards.
11478d9372SMasahiro Yamada
12478d9372SMasahiro YamadaWhen we remove support for boards, we are supposed to add entries to
13478d9372SMasahiro Yamadadoc/README.scrapyard leaving "Commit" and "Removed" fields blank.
14478d9372SMasahiro Yamada
15478d9372SMasahiro YamadaThe "Commit" field is the commit hash in which the board was removed
16478d9372SMasahiro Yamadaand the "Removed" is the date at which the board was removed.  Those
17478d9372SMasahiro Yamadatwo are known only after the board removal patch was applied, thus they
18478d9372SMasahiro Yamadaneed to be filled in later.
19478d9372SMasahiro Yamada
20478d9372SMasahiro YamadaThis effectively means that the person who removes other boards is
21478d9372SMasahiro Yamadasupposed to fill in the blank fields before adding new entries to
22478d9372SMasahiro Yamadadoc/README.scrapyard.
23478d9372SMasahiro Yamada
24478d9372SMasahiro YamadaThat is a really tedious task that should be automated.
25478d9372SMasahiro YamadaThis script fills the blank fields of doc/README.scrapyard for you!
26478d9372SMasahiro Yamada
27478d9372SMasahiro YamadaUsage:
28478d9372SMasahiro Yamada
29478d9372SMasahiro YamadaThe "Commit" and "Removed" fields must be "-".  The other fields should
30478d9372SMasahiro Yamadahave already been filled in by a former commit.
31478d9372SMasahiro Yamada
32478d9372SMasahiro YamadaRun
33478d9372SMasahiro Yamada    scripts/fill_scrapyard.py
34478d9372SMasahiro Yamada"""
35478d9372SMasahiro Yamada
36478d9372SMasahiro Yamadaimport os
37478d9372SMasahiro Yamadaimport subprocess
38478d9372SMasahiro Yamadaimport sys
39478d9372SMasahiro Yamadaimport tempfile
40478d9372SMasahiro Yamada
41478d9372SMasahiro YamadaDOC='doc/README.scrapyard'
42478d9372SMasahiro Yamada
43478d9372SMasahiro Yamadadef get_last_modify_commit(file, line_num):
44478d9372SMasahiro Yamada    """Get the commit that last modified the given line.
45478d9372SMasahiro Yamada
46478d9372SMasahiro Yamada    This function runs "git blame" against the given line of the given
47478d9372SMasahiro Yamada    file and returns the commit hash that last modified it.
48478d9372SMasahiro Yamada
49478d9372SMasahiro Yamada    Arguments:
50478d9372SMasahiro Yamada      file: the file to be git-blame'd.
51478d9372SMasahiro Yamada      line_num: the line number to be git-blame'd.  This line number
52478d9372SMasahiro Yamada                starts from 1, not 0.
53478d9372SMasahiro Yamada
54478d9372SMasahiro Yamada    Returns:
55478d9372SMasahiro Yamada      Commit hash that last modified the line.  The number of digits is
56478d9372SMasahiro Yamada      long enough to form a unique commit.
57478d9372SMasahiro Yamada    """
58478d9372SMasahiro Yamada    result = subprocess.check_output(['git', 'blame', '-L',
59478d9372SMasahiro Yamada                                      '%d,%d' % (line_num, line_num), file])
60478d9372SMasahiro Yamada    commit = result.split()[0]
61478d9372SMasahiro Yamada
62478d9372SMasahiro Yamada    if commit[0] == '^':
63478d9372SMasahiro Yamada        sys.exit('%s: line %d: ' % (file, line_num) +
64478d9372SMasahiro Yamada                 'this line was modified before the beginning of git history')
65478d9372SMasahiro Yamada
66478d9372SMasahiro Yamada    if commit == '0' * len(commit):
67478d9372SMasahiro Yamada        sys.exit('%s: line %d: locally modified\n' % (file, line_num) +
68478d9372SMasahiro Yamada                 'Please run this script in a clean repository.')
69478d9372SMasahiro Yamada
70478d9372SMasahiro Yamada    return commit
71478d9372SMasahiro Yamada
72478d9372SMasahiro Yamadadef get_committer_date(commit):
73478d9372SMasahiro Yamada    """Get the committer date of the given commit.
74478d9372SMasahiro Yamada
75478d9372SMasahiro Yamada    This function returns the date when the given commit was applied.
76478d9372SMasahiro Yamada
77478d9372SMasahiro Yamada    Arguments:
78478d9372SMasahiro Yamada      commit: commit-ish object.
79478d9372SMasahiro Yamada
80478d9372SMasahiro Yamada    Returns:
81478d9372SMasahiro Yamada      The committer date of the given commit in the form YY-MM-DD.
82478d9372SMasahiro Yamada    """
83478d9372SMasahiro Yamada    committer_date = subprocess.check_output(['git', 'show', '-s',
84478d9372SMasahiro Yamada                                              '--format=%ci', commit])
85478d9372SMasahiro Yamada    return committer_date.split()[0]
86478d9372SMasahiro Yamada
87478d9372SMasahiro Yamadadef move_to_topdir():
88478d9372SMasahiro Yamada    """Change directory to the top of the git repository.
89478d9372SMasahiro Yamada
90478d9372SMasahiro Yamada    Or, exit with an error message if called out of a git repository.
91478d9372SMasahiro Yamada    """
92478d9372SMasahiro Yamada    try:
93478d9372SMasahiro Yamada        toplevel = subprocess.check_output(['git', 'rev-parse',
94478d9372SMasahiro Yamada                                            '--show-toplevel'])
95478d9372SMasahiro Yamada    except subprocess.CalledProcessError:
96478d9372SMasahiro Yamada        sys.exit('Please run in a git repository.')
97478d9372SMasahiro Yamada
98478d9372SMasahiro Yamada    # strip '\n'
99478d9372SMasahiro Yamada    toplevel = toplevel.rstrip()
100478d9372SMasahiro Yamada
101478d9372SMasahiro Yamada    # Change the current working directory to the toplevel of the respository
102478d9372SMasahiro Yamada    # for our easier life.
103478d9372SMasahiro Yamada    os.chdir(toplevel)
104478d9372SMasahiro Yamada
105478d9372SMasahiro Yamadaclass TmpFile:
106478d9372SMasahiro Yamada
107478d9372SMasahiro Yamada    """Useful class to handle a temporary file.
108478d9372SMasahiro Yamada
109478d9372SMasahiro Yamada    tempfile.mkstemp() is often used to create a unique temporary file,
110478d9372SMasahiro Yamada    but what is inconvenient is that the caller is responsible for
111478d9372SMasahiro Yamada    deleting the file when done with it.
112478d9372SMasahiro Yamada
113478d9372SMasahiro Yamada    Even when the caller errors out on the way, the temporary file must
114478d9372SMasahiro Yamada    be deleted somehow.  The idea here is that we delete the file in
115478d9372SMasahiro Yamada    the destructor of this class because the destructor is always
116478d9372SMasahiro Yamada    invoked when the instance of the class is freed.
117478d9372SMasahiro Yamada    """
118478d9372SMasahiro Yamada
119478d9372SMasahiro Yamada    def __init__(self):
120478d9372SMasahiro Yamada        """Constructor - create a temporary file"""
121478d9372SMasahiro Yamada        fd, self.filename = tempfile.mkstemp()
122478d9372SMasahiro Yamada        self.file = os.fdopen(fd, 'w')
123478d9372SMasahiro Yamada
124478d9372SMasahiro Yamada    def __del__(self):
125478d9372SMasahiro Yamada        """Destructor - delete the temporary file"""
126478d9372SMasahiro Yamada        try:
127478d9372SMasahiro Yamada            os.remove(self.filename)
128478d9372SMasahiro Yamada        except:
129478d9372SMasahiro Yamada            pass
130478d9372SMasahiro Yamada
131478d9372SMasahiro Yamadadef main():
132478d9372SMasahiro Yamada    move_to_topdir()
133478d9372SMasahiro Yamada
134478d9372SMasahiro Yamada    line_num = 1
135478d9372SMasahiro Yamada
136478d9372SMasahiro Yamada    tmpfile = TmpFile()
137478d9372SMasahiro Yamada    for line in open(DOC):
138478d9372SMasahiro Yamada        tmp = line.split(None, 5)
139478d9372SMasahiro Yamada        modified = False
140478d9372SMasahiro Yamada
141478d9372SMasahiro Yamada        if len(tmp) >= 5:
142478d9372SMasahiro Yamada            # fill "Commit" field
143478d9372SMasahiro Yamada            if tmp[3] == '-':
144478d9372SMasahiro Yamada                tmp[3] = get_last_modify_commit(DOC, line_num)
145478d9372SMasahiro Yamada                modified = True
146478d9372SMasahiro Yamada            # fill "Removed" field
147478d9372SMasahiro Yamada            if tmp[4] == '-':
148478d9372SMasahiro Yamada                tmp[4] = get_committer_date(tmp[3])
149478d9372SMasahiro Yamada            if modified:
150478d9372SMasahiro Yamada                line  = tmp[0].ljust(17)
151478d9372SMasahiro Yamada                line += tmp[1].ljust(12)
152478d9372SMasahiro Yamada                line += tmp[2].ljust(15)
153478d9372SMasahiro Yamada                line += tmp[3].ljust(12)
154478d9372SMasahiro Yamada                line += tmp[4].ljust(12)
155478d9372SMasahiro Yamada                if len(tmp) >= 6:
156478d9372SMasahiro Yamada                    line += tmp[5]
157478d9372SMasahiro Yamada                line = line.rstrip() + '\n'
158478d9372SMasahiro Yamada
159478d9372SMasahiro Yamada        tmpfile.file.write(line)
160478d9372SMasahiro Yamada        line_num += 1
161478d9372SMasahiro Yamada
162478d9372SMasahiro Yamada    os.rename(tmpfile.filename, DOC)
163478d9372SMasahiro Yamada
164478d9372SMasahiro Yamadaif __name__ == '__main__':
165478d9372SMasahiro Yamada    main()
166