tools: moveconfig: increment number of processed files monotonically

Currently, the progress " * defconfigs out of 1133" does not increase
monotonically.

Moreover, the number of processed defconfigs does not match the total
number of defconfigs when this tool finishes, like:

 1132 defconfigs out of 1133
Clean up headers? [y/n]:

It looks like the task was not completed, and some users might feel
upset about it.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Joe Hershberger <joe.hershberger@ni.com>
This commit is contained in:
Masahiro Yamada 2016-05-19 15:51:55 +09:00
parent bd63e5baf9
commit c5e60fd495

View file

@ -388,6 +388,29 @@ def cleanup_headers(config_attrs, dry_run):
patterns, dry_run) patterns, dry_run)
### classes ### ### classes ###
class Progress:
"""Progress Indicator"""
def __init__(self, total):
"""Create a new progress indicator.
Arguments:
total: A number of defconfig files to process.
"""
self.current = 0
self.total = total
def inc(self):
"""Increment the number of processed defconfig files."""
self.current += 1
def show(self):
"""Display the progress."""
print ' %d defconfigs out of %d\r' % (self.current, self.total),
sys.stdout.flush()
class KconfigParser: class KconfigParser:
"""A parser of .config and include/autoconf.mk.""" """A parser of .config and include/autoconf.mk."""
@ -395,17 +418,19 @@ class KconfigParser:
re_arch = re.compile(r'CONFIG_SYS_ARCH="(.*)"') re_arch = re.compile(r'CONFIG_SYS_ARCH="(.*)"')
re_cpu = re.compile(r'CONFIG_SYS_CPU="(.*)"') re_cpu = re.compile(r'CONFIG_SYS_CPU="(.*)"')
def __init__(self, config_attrs, options, build_dir): def __init__(self, config_attrs, options, progress, build_dir):
"""Create a new parser. """Create a new parser.
Arguments: Arguments:
config_attrs: A list of dictionaris, each of them includes the name, config_attrs: A list of dictionaris, each of them includes the name,
the type, and the default value of the target config. the type, and the default value of the target config.
options: option flags. options: option flags.
progress: A progress indicator
build_dir: Build directory. build_dir: Build directory.
""" """
self.config_attrs = config_attrs self.config_attrs = config_attrs
self.options = options self.options = options
self.progress = progress
self.build_dir = build_dir self.build_dir = build_dir
def get_cross_compile(self): def get_cross_compile(self):
@ -541,6 +566,7 @@ class KconfigParser:
# Some threads are running in parallel. # Some threads are running in parallel.
# Print log in one shot to not mix up logs from different threads. # Print log in one shot to not mix up logs from different threads.
print log, print log,
self.progress.show()
with open(dotconfig_path, 'a') as f: with open(dotconfig_path, 'a') as f:
for (action, value) in results: for (action, value) in results:
@ -559,21 +585,24 @@ class Slot:
for faster processing. for faster processing.
""" """
def __init__(self, config_attrs, options, devnull, make_cmd): def __init__(self, config_attrs, options, progress, devnull, make_cmd):
"""Create a new process slot. """Create a new process slot.
Arguments: Arguments:
config_attrs: A list of dictionaris, each of them includes the name, config_attrs: A list of dictionaris, each of them includes the name,
the type, and the default value of the target config. the type, and the default value of the target config.
options: option flags. options: option flags.
progress: A progress indicator.
devnull: A file object of '/dev/null'. devnull: A file object of '/dev/null'.
make_cmd: command name of GNU Make. make_cmd: command name of GNU Make.
""" """
self.options = options self.options = options
self.progress = progress
self.build_dir = tempfile.mkdtemp() self.build_dir = tempfile.mkdtemp()
self.devnull = devnull self.devnull = devnull
self.make_cmd = (make_cmd, 'O=' + self.build_dir) self.make_cmd = (make_cmd, 'O=' + self.build_dir)
self.parser = KconfigParser(config_attrs, options, self.build_dir) self.parser = KconfigParser(config_attrs, options, progress,
self.build_dir)
self.state = STATE_IDLE self.state = STATE_IDLE
self.failed_boards = [] self.failed_boards = []
@ -592,7 +621,7 @@ class Slot:
pass pass
shutil.rmtree(self.build_dir) shutil.rmtree(self.build_dir)
def add(self, defconfig, num, total): def add(self, defconfig):
"""Assign a new subprocess for defconfig and add it to the slot. """Assign a new subprocess for defconfig and add it to the slot.
If the slot is vacant, create a new subprocess for processing the If the slot is vacant, create a new subprocess for processing the
@ -613,8 +642,6 @@ class Slot:
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
self.defconfig = defconfig self.defconfig = defconfig
self.state = STATE_DEFCONFIG self.state = STATE_DEFCONFIG
self.num = num
self.total = total
return True return True
def poll(self): def poll(self):
@ -643,6 +670,8 @@ class Slot:
print >> sys.stderr, color_text(self.options.color, print >> sys.stderr, color_text(self.options.color,
COLOR_LIGHT_CYAN, COLOR_LIGHT_CYAN,
self.ps.stderr.read()) self.ps.stderr.read())
self.progress.inc()
self.progress.show()
if self.options.exit_on_error: if self.options.exit_on_error:
sys.exit("Exit on error.") sys.exit("Exit on error.")
# If --exit-on-error flag is not set, skip this board and continue. # If --exit-on-error flag is not set, skip this board and continue.
@ -654,9 +683,6 @@ class Slot:
if self.state == STATE_AUTOCONF: if self.state == STATE_AUTOCONF:
self.parser.update_dotconfig(self.defconfig) self.parser.update_dotconfig(self.defconfig)
print ' %d defconfigs out of %d\r' % (self.num + 1, self.total),
sys.stdout.flush()
"""Save off the defconfig in a consistent way""" """Save off the defconfig in a consistent way"""
cmd = list(self.make_cmd) cmd = list(self.make_cmd)
cmd.append('savedefconfig') cmd.append('savedefconfig')
@ -669,6 +695,7 @@ class Slot:
if not self.options.dry_run: if not self.options.dry_run:
shutil.move(os.path.join(self.build_dir, 'defconfig'), shutil.move(os.path.join(self.build_dir, 'defconfig'),
os.path.join('configs', self.defconfig)) os.path.join('configs', self.defconfig))
self.progress.inc()
self.state = STATE_IDLE self.state = STATE_IDLE
return True return True
@ -677,6 +704,8 @@ class Slot:
print >> sys.stderr, log_msg(self.options.color, COLOR_YELLOW, print >> sys.stderr, log_msg(self.options.color, COLOR_YELLOW,
self.defconfig, self.defconfig,
"Compiler is missing. Do nothing."), "Compiler is missing. Do nothing."),
self.progress.inc()
self.progress.show()
if self.options.exit_on_error: if self.options.exit_on_error:
sys.exit("Exit on error.") sys.exit("Exit on error.")
# If --exit-on-error flag is not set, skip this board and continue. # If --exit-on-error flag is not set, skip this board and continue.
@ -704,22 +733,24 @@ class Slots:
"""Controller of the array of subprocess slots.""" """Controller of the array of subprocess slots."""
def __init__(self, config_attrs, options): def __init__(self, config_attrs, options, progress):
"""Create a new slots controller. """Create a new slots controller.
Arguments: Arguments:
config_attrs: A list of dictionaris containing the name, the type, config_attrs: A list of dictionaris containing the name, the type,
and the default value of the target CONFIG. and the default value of the target CONFIG.
options: option flags. options: option flags.
progress: A progress indicator.
""" """
self.options = options self.options = options
self.slots = [] self.slots = []
devnull = get_devnull() devnull = get_devnull()
make_cmd = get_make_cmd() make_cmd = get_make_cmd()
for i in range(options.jobs): for i in range(options.jobs):
self.slots.append(Slot(config_attrs, options, devnull, make_cmd)) self.slots.append(Slot(config_attrs, options, progress, devnull,
make_cmd))
def add(self, defconfig, num, total): def add(self, defconfig):
"""Add a new subprocess if a vacant slot is found. """Add a new subprocess if a vacant slot is found.
Arguments: Arguments:
@ -729,7 +760,7 @@ class Slots:
Return True on success or False on failure Return True on success or False on failure
""" """
for slot in self.slots: for slot in self.slots:
if slot.add(defconfig, num, total): if slot.add(defconfig):
return True return True
return False return False
@ -808,13 +839,14 @@ def move_config(config_attrs, options):
for filename in fnmatch.filter(filenames, '*_defconfig'): for filename in fnmatch.filter(filenames, '*_defconfig'):
defconfigs.append(os.path.join(dirpath, filename)) defconfigs.append(os.path.join(dirpath, filename))
slots = Slots(config_attrs, options) progress = Progress(len(defconfigs))
slots = Slots(config_attrs, options, progress)
# Main loop to process defconfig files: # Main loop to process defconfig files:
# Add a new subprocess into a vacant slot. # Add a new subprocess into a vacant slot.
# Sleep if there is no available slot. # Sleep if there is no available slot.
for i, defconfig in enumerate(defconfigs): for defconfig in defconfigs:
while not slots.add(defconfig, i, len(defconfigs)): while not slots.add(defconfig):
while not slots.available(): while not slots.available():
# No available slot: sleep for a while # No available slot: sleep for a while
time.sleep(SLEEP_TIME) time.sleep(SLEEP_TIME)
@ -823,6 +855,7 @@ def move_config(config_attrs, options):
while not slots.empty(): while not slots.empty():
time.sleep(SLEEP_TIME) time.sleep(SLEEP_TIME)
progress.show()
print '' print ''
slots.show_failed_boards() slots.show_failed_boards()