tools: moveconfig: increment number of processed files monotonically
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Thu, 19 May 2016 06:51:55 +0000 (15:51 +0900)
committerMasahiro Yamada <yamada.masahiro@socionext.com>
Sun, 12 Jun 2016 22:46:28 +0000 (07:46 +0900)
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>
tools/moveconfig.py

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