[U-Boot] [PATCH v2 2/2] tools: moveconfig: Add a new --git-ref option

Joe Hershberger joe.hershberger at ni.com
Thu Jun 2 05:30:07 CEST 2016


This option allows the 'make *_defconfig' step to run against a former
repo state, while the savedefconfig step runs against the current repo
state. This is convenient for the case where something in the Kconfig
has changed such that the defconfig is no longer complete with the new
Kconfigs. This feature allows the .config to be built assuming those old
Kconfigs, but then savedefconfig based on the new state of the Kconfigs.

Signed-off-by: Joe Hershberger <joe.hershberger at ni.com>
---

Changes in v2:
- Stop reusing functions from patman
- Rebase on top of the latest moveconfig series

 tools/moveconfig.py | 101 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 84 insertions(+), 17 deletions(-)

diff --git a/tools/moveconfig.py b/tools/moveconfig.py
index 01350ce..7d9d31e 100755
--- a/tools/moveconfig.py
+++ b/tools/moveconfig.py
@@ -143,6 +143,10 @@ Available options
    Specify the number of threads to run simultaneously.  If not specified,
    the number of threads is the same as the number of CPU cores.
 
+ -r, --git-ref
+   Specify the git ref to clone for the make *_defconfig step. If unspecified
+   use the CWD.
+
  -v, --verbose
    Show any build errors as boards are built
 
@@ -412,6 +416,9 @@ class KconfigParser:
         self.options = options
         self.dotconfig = os.path.join(build_dir, '.config')
         self.autoconf = os.path.join(build_dir, 'include', 'autoconf.mk')
+        if options.git_ref:
+            self.autoconf_orig = os.path.join(build_dir, 'include',
+                                              'autoconf.orig.mk')
         self.config_autoconf = os.path.join(build_dir, 'include', 'config',
                                             'auto.conf')
         self.defconfig = os.path.join(build_dir, 'defconfig')
@@ -464,14 +471,6 @@ class KconfigParser:
         """
         not_set = '# %s is not set' % config
 
-        for line in dotconfig_lines:
-            line = line.rstrip()
-            if line.startswith(config + '=') or line == not_set:
-                old_val = line
-                break
-        else:
-            return (ACTION_NO_ENTRY, config)
-
         for line in autoconf_lines:
             line = line.rstrip()
             if line.startswith(config + '='):
@@ -480,6 +479,14 @@ class KconfigParser:
         else:
             new_val = not_set
 
+        for line in dotconfig_lines:
+            line = line.rstrip()
+            if line.startswith(config + '=') or line == not_set:
+                old_val = line
+                break
+        else:
+            return (ACTION_NO_ENTRY, config)
+
         if old_val == new_val:
             return (ACTION_NO_CHANGE, new_val)
 
@@ -515,8 +522,14 @@ class KconfigParser:
         with open(self.dotconfig) as f:
             dotconfig_lines = f.readlines()
 
-        with open(self.autoconf) as f:
-            autoconf_lines = f.readlines()
+
+        if self.options.git_ref:
+            # Pull the target value from the original autoconf.mk
+            with open(self.autoconf_orig) as f:
+                autoconf_lines = f.readlines()
+        else:
+            with open(self.autoconf) as f:
+                autoconf_lines = f.readlines()
 
         for config in self.configs:
             result = self.parse_one_config(config, dotconfig_lines,
@@ -585,7 +598,7 @@ class Slot:
     for faster processing.
     """
 
-    def __init__(self, configs, options, progress, devnull, make_cmd):
+    def __init__(self, configs, options, progress, devnull, make_cmd, defconfig_src_dir):
         """Create a new process slot.
 
         Arguments:
@@ -600,8 +613,11 @@ class Slot:
         self.build_dir = tempfile.mkdtemp()
         self.devnull = devnull
         self.make_cmd = (make_cmd, 'O=' + self.build_dir)
+        self.defconfig_src_dir = defconfig_src_dir
         self.parser = KconfigParser(configs, options, self.build_dir)
         self.state = STATE_IDLE
+        if self.options.git_ref:
+            self.use_git_ref = True
         self.failed_boards = []
 
     def __del__(self):
@@ -609,7 +625,7 @@ class Slot:
 
         This function makes sure the temporary directory is cleaned away
         even if Python suddenly dies due to error.  It should be done in here
-        because it is guranteed the destructor is always invoked when the
+        because it is guaranteed the destructor is always invoked when the
         instance of the class gets unreferenced.
 
         If the subprocess is still running, wait until it finishes.
@@ -638,6 +654,7 @@ class Slot:
         self.defconfig = defconfig
         self.state = STATE_INIT
         self.log = ''
+        self.use_git_ref = True
         return True
 
     def poll(self):
@@ -662,6 +679,9 @@ class Slot:
         if self.state == STATE_INIT:
             cmd = list(self.make_cmd)
             cmd.append(self.defconfig)
+            if self.options.git_ref and self.use_git_ref:
+                cmd.append('-C')
+                cmd.append(self.defconfig_src_dir)
             self.ps = subprocess.Popen(cmd, stdout=self.devnull,
                                        stderr=subprocess.PIPE)
             self.state = STATE_DEFCONFIG
@@ -692,12 +712,22 @@ class Slot:
                 cmd.append('CROSS_COMPILE=%s' % self.cross_compile)
             cmd.append('KCONFIG_IGNORE_DUPLICATES=1')
             cmd.append('include/config/auto.conf')
+            if self.options.git_ref and self.use_git_ref:
+                cmd.append('-C')
+                cmd.append(self.defconfig_src_dir)
             self.ps = subprocess.Popen(cmd, stdout=self.devnull,
                                        stderr=subprocess.PIPE)
             self.state = STATE_AUTOCONF
             return False
 
         if self.state == STATE_AUTOCONF:
+            if self.options.git_ref and self.use_git_ref:
+                shutil.move(os.path.join(self.build_dir, 'include/autoconf.mk'),
+                            os.path.join(self.build_dir, 'include/autoconf.orig.mk'))
+                self.state = STATE_INIT
+                self.use_git_ref = False
+                return False
+
             (updated, log) = self.parser.update_dotconfig()
             self.log += log
 
@@ -724,7 +754,7 @@ class Slot:
             updated = not filecmp.cmp(orig_defconfig, new_defconfig)
 
             if updated:
-                self.log += color_text(self.options.color, COLOR_LIGHT_GREEN,
+                self.log += color_text(self.options.color, COLOR_LIGHT_BLUE,
                                        "defconfig was updated.\n")
 
             if not self.options.dry_run and updated:
@@ -771,7 +801,7 @@ class Slots:
 
     """Controller of the array of subprocess slots."""
 
-    def __init__(self, configs, options, progress):
+    def __init__(self, configs, options, progress, defconfig_src_dir):
         """Create a new slots controller.
 
         Arguments:
@@ -785,7 +815,7 @@ class Slots:
         make_cmd = get_make_cmd()
         for i in range(options.jobs):
             self.slots.append(Slot(configs, options, progress, devnull,
-                                   make_cmd))
+                                   make_cmd, defconfig_src_dir))
 
     def add(self, defconfig):
         """Add a new subprocess if a vacant slot is found.
@@ -842,6 +872,24 @@ class Slots:
                 for board in failed_boards:
                     f.write(board + '\n')
 
+class WorkDir:
+    def __init__(self):
+        """Create a new working directory."""
+        self.work_dir = tempfile.mkdtemp()
+
+    def __del__(self):
+        """Delete the working directory
+
+        This function makes sure the temporary directory is cleaned away
+        even if Python suddenly dies due to error.  It should be done in here
+        because it is guaranteed the destructor is always invoked when the
+        instance of the class gets unreferenced.
+        """
+        shutil.rmtree(self.work_dir)
+
+    def get(self):
+        return self.work_dir
+
 def move_config(configs, options):
     """Move config options to defconfig files.
 
@@ -853,11 +901,28 @@ def move_config(configs, options):
         if options.force_sync:
             print 'No CONFIG is specified. You are probably syncing defconfigs.',
         else:
-            print 'Neigher CONFIG nor --force-sync is specified. Nothing will happen.',
+            print 'Neither CONFIG nor --force-sync is specified. Nothing will happen.',
     else:
         print 'Move ' + ', '.join(configs),
     print '(jobs: %d)\n' % options.jobs
 
+    defconfig_src_dir = ''
+
+    if options.git_ref:
+        work_dir = WorkDir()
+        defconfig_src_dir = work_dir.get()
+        cwd = os.getcwd()
+        print "Cloning git repo for 'make *_defconfig' step..."
+	subprocess.check_output(['git', 'clone', cwd, '.'], \
+				cwd=defconfig_src_dir)
+        print "Checkout '%s' to find original configs." % \
+            subprocess.check_output(['git', 'rev-parse', '--short', \
+				    options.git_ref]).strip()
+        os.chdir(defconfig_src_dir)
+	subprocess.check_output(['git', 'checkout', options.git_ref],
+                                stderr=subprocess.STDOUT)
+        os.chdir(cwd)
+
     if options.defconfigs:
         defconfigs = [line.strip() for line in open(options.defconfigs)]
         for i, defconfig in enumerate(defconfigs):
@@ -875,7 +940,7 @@ def move_config(configs, options):
                 defconfigs.append(os.path.join(dirpath, filename))
 
     progress = Progress(len(defconfigs))
-    slots = Slots(configs, options, progress)
+    slots = Slots(configs, options, progress, defconfig_src_dir)
 
     # Main loop to process defconfig files:
     #  Add a new subprocess into a vacant slot.
@@ -917,6 +982,8 @@ def main():
                       help='only cleanup the headers')
     parser.add_option('-j', '--jobs', type='int', default=cpu_count,
                       help='the number of jobs to run simultaneously')
+    parser.add_option('-r', '--git-ref', type='string',
+                      help='the git ref to clone for the make *_defconfig step')
     parser.add_option('-v', '--verbose', action='store_true', default=False,
                       help='show any build errors as boards are built')
     parser.usage += ' CONFIG ...'
-- 
1.7.11.5



More information about the U-Boot mailing list