We are removing bunch of non-generic boards these days. Updating doc/README.scrapyard is a really tedious task, but it can be automated. I hope this tool will make our life easier. Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com> Reviewed-by: Simon Glass <sjg@chromium.org>master
parent
a90e77dbeb
commit
478d9372d1
@ -0,0 +1,166 @@ |
||||
#!/usr/bin/env python2 |
||||
# |
||||
# Author: Masahiro Yamada <yamada.m@jp.panasonic.com> |
||||
# |
||||
# SPDX-License-Identifier: GPL-2.0+ |
||||
# |
||||
|
||||
""" |
||||
Fill the "Commit" and "Removed" fields of doc/README.scrapyard |
||||
|
||||
The file doc/README.scrapyard is used to keep track of removed boards. |
||||
|
||||
When we remove support for boards, we are supposed to add entries to |
||||
doc/README.scrapyard leaving "Commit" and "Removed" fields blank. |
||||
|
||||
The "Commit" field is the commit hash in which the board was removed |
||||
and the "Removed" is the date at which the board was removed. Those |
||||
two are known only after the board removal patch was applied, thus they |
||||
need to be filled in later. |
||||
|
||||
This effectively means that the person who removes other boards is |
||||
supposed to fill in the blank fields before adding new entries to |
||||
doc/README.scrapyard. |
||||
|
||||
That is a really tedious task that should be automated. |
||||
This script fills the blank fields of doc/README.scrapyard for you! |
||||
|
||||
Usage: |
||||
|
||||
The "Commit" and "Removed" fields must be "-". The other fields should |
||||
have already been filled in by a former commit. |
||||
|
||||
Run |
||||
scripts/fill_scrapyard.py |
||||
""" |
||||
|
||||
import os |
||||
import subprocess |
||||
import sys |
||||
import tempfile |
||||
|
||||
DOC='doc/README.scrapyard' |
||||
|
||||
def get_last_modify_commit(file, line_num): |
||||
"""Get the commit that last modified the given line. |
||||
|
||||
This function runs "git blame" against the given line of the given |
||||
file and returns the commit hash that last modified it. |
||||
|
||||
Arguments: |
||||
file: the file to be git-blame'd. |
||||
line_num: the line number to be git-blame'd. This line number |
||||
starts from 1, not 0. |
||||
|
||||
Returns: |
||||
Commit hash that last modified the line. The number of digits is |
||||
long enough to form a unique commit. |
||||
""" |
||||
result = subprocess.check_output(['git', 'blame', '-L', |
||||
'%d,%d' % (line_num, line_num), file]) |
||||
commit = result.split()[0] |
||||
|
||||
if commit[0] == '^': |
||||
sys.exit('%s: line %d: ' % (file, line_num) + |
||||
'this line was modified before the beginning of git history') |
||||
|
||||
if commit == '0' * len(commit): |
||||
sys.exit('%s: line %d: locally modified\n' % (file, line_num) + |
||||
'Please run this script in a clean repository.') |
||||
|
||||
return commit |
||||
|
||||
def get_committer_date(commit): |
||||
"""Get the committer date of the given commit. |
||||
|
||||
This function returns the date when the given commit was applied. |
||||
|
||||
Arguments: |
||||
commit: commit-ish object. |
||||
|
||||
Returns: |
||||
The committer date of the given commit in the form YY-MM-DD. |
||||
""" |
||||
committer_date = subprocess.check_output(['git', 'show', '-s', |
||||
'--format=%ci', commit]) |
||||
return committer_date.split()[0] |
||||
|
||||
def move_to_topdir(): |
||||
"""Change directory to the top of the git repository. |
||||
|
||||
Or, exit with an error message if called out of a git repository. |
||||
""" |
||||
try: |
||||
toplevel = subprocess.check_output(['git', 'rev-parse', |
||||
'--show-toplevel']) |
||||
except subprocess.CalledProcessError: |
||||
sys.exit('Please run in a git repository.') |
||||
|
||||
# strip '\n' |
||||
toplevel = toplevel.rstrip() |
||||
|
||||
# Change the current working directory to the toplevel of the respository |
||||
# for our easier life. |
||||
os.chdir(toplevel) |
||||
|
||||
class TmpFile: |
||||
|
||||
"""Useful class to handle a temporary file. |
||||
|
||||
tempfile.mkstemp() is often used to create a unique temporary file, |
||||
but what is inconvenient is that the caller is responsible for |
||||
deleting the file when done with it. |
||||
|
||||
Even when the caller errors out on the way, the temporary file must |
||||
be deleted somehow. The idea here is that we delete the file in |
||||
the destructor of this class because the destructor is always |
||||
invoked when the instance of the class is freed. |
||||
""" |
||||
|
||||
def __init__(self): |
||||
"""Constructor - create a temporary file""" |
||||
fd, self.filename = tempfile.mkstemp() |
||||
self.file = os.fdopen(fd, 'w') |
||||
|
||||
def __del__(self): |
||||
"""Destructor - delete the temporary file""" |
||||
try: |
||||
os.remove(self.filename) |
||||
except: |
||||
pass |
||||
|
||||
def main(): |
||||
move_to_topdir() |
||||
|
||||
line_num = 1 |
||||
|
||||
tmpfile = TmpFile() |
||||
for line in open(DOC): |
||||
tmp = line.split(None, 5) |
||||
modified = False |
||||
|
||||
if len(tmp) >= 5: |
||||
# fill "Commit" field |
||||
if tmp[3] == '-': |
||||
tmp[3] = get_last_modify_commit(DOC, line_num) |
||||
modified = True |
||||
# fill "Removed" field |
||||
if tmp[4] == '-': |
||||
tmp[4] = get_committer_date(tmp[3]) |
||||
if modified: |
||||
line = tmp[0].ljust(17) |
||||
line += tmp[1].ljust(12) |
||||
line += tmp[2].ljust(15) |
||||
line += tmp[3].ljust(12) |
||||
line += tmp[4].ljust(12) |
||||
if len(tmp) >= 6: |
||||
line += tmp[5] |
||||
line = line.rstrip() + '\n' |
||||
|
||||
tmpfile.file.write(line) |
||||
line_num += 1 |
||||
|
||||
os.rename(tmpfile.filename, DOC) |
||||
|
||||
if __name__ == '__main__': |
||||
main() |
Loading…
Reference in new issue