Isolate steps into own module in order to provide better
structure of the code.

In order to do that the step interfaces was defined to,
step(bb, git, opts, pkg_ctx)

        - bb: Bitbake helper instance.
        - git: Git helper instance.
        - opts: Upgrade helper options.
        - pkg_ctx: Package context per upgrade, it stores
        all information related to one upgrade.

Signed-off-by: Aníbal Limón <anibal.li...@linux.intel.com>
---
 steps.py         | 142 ++++++++++++++++++++++++++++++
 upgradehelper.py | 259 +++++++++++++++++--------------------------------------
 2 files changed, 221 insertions(+), 180 deletions(-)
 create mode 100644 steps.py

diff --git a/steps.py b/steps.py
new file mode 100644
index 0000000..ea314da
--- /dev/null
+++ b/steps.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# vim: set ts=4 sw=4 et:
+#
+# Copyright (c) 2013 - 2015 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+#
+
+import os
+import sys
+
+from logging import debug as D
+from logging import info as I
+from logging import warning as W
+from logging import error as E
+from logging import critical as C
+
+from errors import *
+from buildhistory import BuildHistory
+from recipe import Recipe
+from gitrecipe import GitRecipe
+from svnrecipe import SvnRecipe
+
+def load_env(bb, git, opts, pkg_ctx):
+    stdout = git.status()
+    if stdout != "":
+        if opts['interactive']:
+            W(" %s: git repository has uncommited work which will be dropped!" 
\
+                    " Proceed? (y/N)" % pkg_ctx['PN'])
+            answer = sys.stdin.readline().strip().upper()
+            if answer == '' or answer != 'Y':
+                I(" %s: User abort!" % pkg_ctx['PN'])
+                exit(1)
+
+        I(" %s: Dropping uncommited work!" % pkg_ctx['PN'])
+        git.reset_hard()
+        git.clean_untracked()
+
+    pkg_ctx['env'] = bb.env(pkg_ctx['PN'])
+    if pkg_ctx['env']['PV'] == pkg_ctx['NPV']:
+        raise UpgradeNotNeededError
+
+def load_dirs(bb, git, opts, pkg_ctx):
+    pkg_ctx['workdir'] = os.path.join(pkg_ctx['base_dir'], pkg_ctx['PN'])
+    os.mkdir(pkg_ctx['workdir'])
+
+    pkg_ctx['recipe_dir'] = os.path.dirname(pkg_ctx['env']['FILE'])
+
+def clean_repo(bb, git, opts, pkg_ctx):
+    try:
+        git.checkout_branch("upgrades")
+    except Error:
+        git.create_branch("upgrades")
+
+    try:
+        git.delete_branch("remove_patches")
+    except:
+        pass
+
+def detect_recipe_type(bb, git, opts, pkg_ctx):
+    if pkg_ctx['env']['SRC_URI'].find("ftp://";) != -1 or  \
+            pkg_ctx['env']['SRC_URI'].find("http://";) != -1 or \
+            pkg_ctx['env']['SRC_URI'].find("https://";) != -1:
+        recipe = Recipe
+    elif pkg_ctx['env']['SRC_URI'].find("git://") != -1:
+        recipe = GitRecipe
+    else:
+        raise UnsupportedProtocolError
+
+    pkg_ctx['recipe'] = recipe(pkg_ctx['env'], pkg_ctx['NPV'],
+            opts['interactive'], pkg_ctx['workdir'],
+            pkg_ctx['recipe_dir'], bb, git)
+
+def buildhistory_init(bb, git, opts, pkg_ctx):
+    if not opts['buildhistory_enabled']:
+        return
+
+    pkg_ctx['buildhistory'] = BuildHistory(bb, pkg_ctx['PN'],
+            pkg_ctx['workdir'])
+    I(" %s: Initial buildhistory for %s ..." % (pkg_ctx['PN'],
+            opts['machines']))
+    pkg_ctx['buildhistory'].init(opts['machines'])
+
+def unpack_original(bb, git, opts, pkg_ctx):
+    pkg_ctx['recipe'].unpack()
+
+def rename(bb, git, opts, pkg_ctx):
+    pkg_ctx['recipe'].rename()
+
+    pkg_ctx['env'] = bb.env(pkg_ctx['PN'])
+
+    pkg_ctx['recipe'].update_env(pkg_ctx['env'])
+
+def cleanall(bb, git, opts, pkg_ctx):
+    pkg_ctx['recipe'].cleanall()
+
+def fetch(bb, git, opts, pkg_ctx):
+    pkg_ctx['recipe'].fetch()
+
+def compile(bb, git, opts, pkg_ctx):
+    if opts['skip_compilation']:
+        W(" %s: Compilation was skipped by user choice!")
+        return
+
+    for machine in opts['machines']:
+        I(" %s: compiling for %s ..." % (pkg_ctx['PN'], machine))
+        pkg_ctx['recipe'].compile(machine)
+        if opts['buildhistory_enabled']:
+            pkg_ctx['buildhistory'].add()
+
+def buildhistory_diff(bb, git, opts, pkg_ctx):
+    if not opts['buildhistory_enabled']:
+        return
+
+    I(" %s: Checking buildhistory ..." % pkg_ctx['PN'])
+    pkg_ctx['buildhistory'].diff()
+
+upgrade_steps = [
+    (load_env, "Loading environment ..."),
+    (load_dirs, None),
+    (clean_repo, "Cleaning git repository of temporary branch ..."),
+    (detect_recipe_type, None),
+    (buildhistory_init, None),
+    (unpack_original, "Fetch & unpack original version ..."),
+    (rename, "Renaming recipes, reset PR (if exists) ..."),
+    (cleanall, "Clean all ..."),
+    (fetch, "Fetch new version (old checksums) ..."),
+    (compile, None),
+    (buildhistory_diff, None)
+]
diff --git a/upgradehelper.py b/upgradehelper.py
index 1c3dcbc..22365b7 100755
--- a/upgradehelper.py
+++ b/upgradehelper.py
@@ -29,12 +29,14 @@
 import argparse
 import os
 import subprocess
+
 import logging as log
 from logging import debug as D
 from logging import info as I
 from logging import warning as W
 from logging import error as E
 from logging import critical as C
+
 import re
 import signal
 import sys
@@ -43,14 +45,14 @@ from datetime import datetime
 from datetime import date
 import shutil
 from errors import *
+
 from git import Git
 from bitbake import Bitbake
-from buildhistory import BuildHistory
+
 from emailhandler import Email
 from statistics import Statistics
-from recipe import Recipe
-from gitrecipe import GitRecipe
-from svnrecipe import SvnRecipe
+
+from steps import upgrade_steps
 
 help_text = """Usage examples:
 * To upgrade xmodmap recipe to the latest available version, interactively:
@@ -140,7 +142,8 @@ class Updater(object):
 
         self.email_handler = Email(settings)
         self.statistics = Statistics()
-        self.git = None
+        # XXX: assume that the poky directory is the first entry in the PATH
+        self.git = Git(os.path.dirname(os.getenv('PATH', False).split(':')[0]))
 
         self.opts = {}
         self.opts['interactive'] = not auto_mode
@@ -165,21 +168,6 @@ class Updater(object):
         self.uh_recipes_failed_dir = os.path.join(self.uh_work_dir, "failed")
         os.mkdir(self.uh_recipes_failed_dir)
 
-        self.upgrade_steps = [
-            (self._load_env, "Loading environment ..."),
-            (self._create_workdir, None),
-            (self._detect_repo, "Detecting git repository location ..."),
-            (self._clean_repo, "Cleaning git repository of temporary branch 
..."),
-            (self._detect_recipe_type, None),
-            (self._buildhistory_init, None),
-            (self._unpack_original, "Fetch & unpack original version ..."),
-            (self._rename, "Renaming recipes, reset PR (if exists) ..."),
-            (self._cleanall, "Clean all ..."),
-            (self._fetch, "Fetch new version (old checksums) ..."),
-            (self._compile, None),
-            (self._buildhistory_diff, None)
-        ]
-
     def _get_status_msg(self, err):
         if err:
             return str(err)
@@ -208,105 +196,6 @@ class Updater(object):
 
         return enabled
 
-    def _load_env(self):
-        self.env = self.bb.env(self.pn)
-
-    def _create_workdir(self):
-        self.workdir = os.path.join(self.uh_recipes_all_dir, self.pn)
-        os.mkdir(self.workdir)
-
-    def _detect_repo(self):
-        self.recipe_dir = os.path.dirname(self.env['FILE'])
-
-        if self.env['PV'] == self.new_ver:
-            raise UpgradeNotNeededError
-
-        # UniverseUpdater use git poky respository 
-        if isinstance(self.git, UniverseUpdater):
-            return
-
-        self.git = Git(self.recipe_dir)
-
-        stdout = self.git.status()
-        if stdout != "":
-            if self.opts['interactive']:
-                W(" %s: git repository has uncommited work which will be 
dropped! Proceed? (y/N)" % self.pn)
-                answer = sys.stdin.readline().strip().upper()
-                if answer == '' or answer != 'Y':
-                    I(" %s: User abort!" % self.pn)
-                    exit(0)
-
-            W(" %s: Dropping uncommited work!" % self.pn)
-            self.git.reset_hard()
-            self.git.clean_untracked()
-
-            self.env = self.bb.env(self.pn)
-
-    def _clean_repo(self):
-        try:
-            self.git.checkout_branch("upgrades")
-        except Error:
-            self.git.create_branch("upgrades")
-        try:
-            self.git.delete_branch("remove_patches")
-        except:
-            pass
-
-    def _detect_recipe_type(self):
-        if self.env['SRC_URI'].find("ftp://";) != -1 or  \
-                self.env['SRC_URI'].find("http://";) != -1 or \
-                self.env['SRC_URI'].find("https://";) != -1:
-            recipe = Recipe
-        elif self.env['SRC_URI'].find("git://") != -1:
-            recipe = GitRecipe
-        else:
-            raise UnsupportedProtocolError
-
-        self.recipe = recipe(self.env, self.new_ver, self.opts['interactive'], 
self.workdir,
-                             self.recipe_dir, self.bb, self.git)
-
-    def _buildhistory_init(self):
-        if not self.opts['buildhistory_enabled']:
-            return
-
-        self.buildhistory = BuildHistory(self.bb, self.pn, self.workdir)
-        I(" %s: Initial buildhistory for %s ..." % (self.pn, 
self.opts['machines']))
-        self.buildhistory.init(self.opts['machines'])
-
-    def _unpack_original(self):
-        self.recipe.unpack()
-
-    def _rename(self):
-        self.recipe.rename()
-
-        self.env = self.bb.env(self.pn)
-
-        self.recipe.update_env(self.env)
-
-    def _cleanall(self):
-        self.recipe.cleanall()
-
-    def _fetch(self):
-        self.recipe.fetch()
-
-    def _compile(self):
-        if self.opts['skip_compilation']:
-            W(" %s: Compilation was skipped by user choice!")
-            return
-
-        for machine in self.opts['machines']:
-            I(" %s: compiling for %s ..." % (self.pn, machine))
-            self.recipe.compile(machine)
-            if self.opts['buildhistory_enabled']:
-                self.buildhistory.add()
-
-    def _buildhistory_diff(self):
-        if not self.opts['buildhistory_enabled']:
-            return
-
-        I(" %s: Checking buildhistory ..." % self.pn)
-        self.buildhistory.diff()
-
     def _get_packages_to_upgrade(self, packages=None):
         if packages is None:
             I( "Nothing to upgrade")
@@ -315,14 +204,14 @@ class Updater(object):
             return packages
 
     # this function will be called at the end of each recipe upgrade
-    def pkg_upgrade_handler(self, err):
-        if err and self.patch_file and self.opts['interactive']:
+    def pkg_upgrade_handler(self, pkg_ctx):
+        if self.opts['interactive'] and pkg_ctx['error'] and 
pkg_ctx['patch_file']:
             answer = "N"
-            I(" %s: Do you want to keep the changes? (y/N)" % self.pn)
+            I(" %s: Do you want to keep the changes? (y/N)" % pkg_ctx['PN'])
             answer = sys.stdin.readline().strip().upper()
 
             if answer == '' or answer == 'N':
-                I(" %s: Dropping changes from git ..." % self.pn)
+                I(" %s: Dropping changes from git ..." % pkg_ctx['PN'])
                 self.git.reset_hard(1)
                 self.git.clean_untracked()
                 return
@@ -331,8 +220,8 @@ class Updater(object):
         # problems and other recipes depend on it. Give the other recipes a
         # chance...
         if (settings.get("drop_previous_commits", "no") == "yes" and
-                not err) or (err and self.patch_file):
-            I(" %s: Dropping changes from git ..." % self.pn)
+                not pkg_ctx['error']) or (pkg_ctx['error'] and 
pkg_ctx['patch_file']):
+            I(" %s: Dropping changes from git ..." % pkg_ctx['PN'])
             self.git.reset_hard(1)
             self.git.clean_untracked()
 
@@ -361,44 +250,44 @@ class Updater(object):
             "Any problem please contact Anibal Limon 
<anibal.li...@intel.com>.\n\n" \
             "Regards,\nThe Upgrade Helper"
 
-        if self.maintainer in maintainer_override:
-            to_addr = maintainer_override[self.maintainer]
+        if pkg_ctx['MAINTAINER'] in maintainer_override:
+            to_addr = maintainer_override[pkg_ctx['MAINTAINER']]
         else:
-            to_addr = self.maintainer
+            to_addr = pkg_ctx['MAINTAINER']
 
         cc_addr = None
         if "status_recipients" in settings:
             cc_addr = settings["status_recipients"].split()
 
-        subject = "[AUH] " + self.pn + ": upgrading to " + self.new_ver
-        if not err:
+        subject = "[AUH] " + pkg_ctx['PN'] + ": upgrading to " + pkg_ctx['NPV']
+        if not pkg_ctx['error']:
             subject += " SUCCEEDED"
         else:
             subject += " FAILED"
-        msg_body = mail_header % (self.pn, self.new_ver,
-                self._get_status_msg(err))
-        license_diff_fn = self.recipe.get_license_diff_file_name()
+        msg_body = mail_header % (pkg_ctx['PN'], pkg_ctx['NPV'],
+                self._get_status_msg(pkg_ctx['error']))
+        license_diff_fn = pkg_ctx['recipe'].get_license_diff_file_name()
         if license_diff_fn:
             msg_body += license_change_info % license_diff_fn
-        if not err:
+        if not pkg_ctx['error']:
             msg_body += next_steps_info % (', '.join(self.opts['machines']),
-                    os.path.basename(self.patch_file))
+                    os.path.basename(pkg_ctx['patch_file']))
 
         msg_body += mail_footer
 
         # Add possible attachments to email
         attachments = []
-        for attachment in os.listdir(self.workdir):
-            attachment_fullpath = os.path.join(self.workdir, attachment)
+        for attachment in os.listdir(pkg_ctx['workdir']):
+            attachment_fullpath = os.path.join(pkg_ctx['workdir'], attachment)
             if os.path.isfile(attachment_fullpath):
                 attachments.append(attachment_fullpath)
 
         # Only send email to Maintainer when recipe upgrade succeed.
-        if self.opts['send_email'] and not err:
+        if self.opts['send_email'] and not pkg_ctx['error']:
             self.email_handler.send_email(to_addr, subject, msg_body, 
attachments, cc_addr=cc_addr)
 
         # Preserve email for review purposes.
-        email_file = os.path.join(self.workdir,
+        email_file = os.path.join(pkg_ctx['workdir'],
                     "email_summary")
         with open(email_file, "w+") as f:
             f.write("To: %s\n" % to_addr)
@@ -411,22 +300,26 @@ class Updater(object):
             f.write("Attachments: %s\n" % ' '.join(attachments))
             f.write("\n%s\n" % msg_body)
 
-    def _commit_changes(self):
+    def commit_changes(self, pkg_ctx):
         try:
-            self.patch_file = None
-            if self.recipe is not None:
-                I(" %s: Auto commit changes ..." % self.pn)
-                self.git.commit(self.recipe.commit_msg, self.opts['author'])
-                I(" %s: Save patch in %s." % (self.pn, self.workdir))
-                stdout = self.git.create_patch(self.workdir)
-                self.patch_file = stdout.strip()
+            pkg_ctx['patch_file'] = None
+
+            if pkg_ctx['recipe']:
+                I(" %s: Auto commit changes ..." % pkg_ctx['PN'])
+                self.git.commit(pkg_ctx['recipe'].commit_msg, 
self.opts['author'])
+
+                I(" %s: Save patch in directory: %s." %
+                        (pkg_ctx['PN'], pkg_ctx['workdir']))
+
+                stdout = self.git.create_patch(pkg_ctx['workdir'])
+                pkg_ctx['patch_file'] = stdout.strip()
         except Error as e:
             for line in e.stdout.split("\n"):
                 if line.find("nothing to commit") == 0:
-                    I(" %s: Nothing to commit!" % self.pn)
+                    I(" %s: Nothing to commit!" % pkg_ctx['PN'])
                     return
 
-            I(" %s: %s" % (self.pn, e.stdout))
+            I(" %s: %s" % (pkg_ctx['PN'], e.stdout))
             raise e
 
     def send_status_mail(self):
@@ -445,7 +338,6 @@ class Updater(object):
         else:
             W("No recipes attempted, not sending status mail!")
 
-
     def _order_pkgs_to_upgrade(self, pkgs_to_upgrade):
         def _get_pn_dep_dic(pn_list, dependency_file): 
             import re
@@ -534,33 +426,43 @@ class Updater(object):
                 self._get_packages_to_upgrade(package_list))
         total_pkgs = len(pkgs_to_upgrade)
 
+        pkgs_ctx = {}
+
         I(" ########### The list of recipes to be upgraded #############")
         for p, v, m in pkgs_to_upgrade:
             I(" %s, %s, %s" % (p, v, m))
+
+            pkgs_ctx[p] = {}
+            pkgs_ctx[p]['PN'] = p
+            pkgs_ctx[p]['NPV'] = v
+            pkgs_ctx[p]['MAINTAINER'] = m
+
+            pkgs_ctx[p]['base_dir'] = self.uh_recipes_all_dir
         I(" ############################################################")
 
         attempted_pkgs = 0
-        for self.pn, self.new_ver, self.maintainer in pkgs_to_upgrade:
-            error = None
-            self.recipe = None
+        for pn, _, _ in pkgs_to_upgrade:
+            pkg_ctx = pkgs_ctx[pn]
+            pkg_ctx['error'] = None
+
             attempted_pkgs += 1
             I(" ATTEMPT PACKAGE %d/%d" % (attempted_pkgs, total_pkgs))
             try:
-                I(" %s: Upgrading to %s" % (self.pn, self.new_ver))
-                for step, msg in self.upgrade_steps:
+                I(" %s: Upgrading to %s" % (pkg_ctx['PN'], pkg_ctx['NPV']))
+                for step, msg in upgrade_steps:
                     if msg is not None:
-                        I(" %s: %s" % (self.pn, msg))
-                    step()
+                        I(" %s: %s" % (pkg_ctx['PN'], msg))
+                    step(self.bb, self.git, self.opts, pkg_ctx)
 
-                os.symlink(self.workdir, os.path.join( \
-                    self.uh_recipes_succeed_dir, self.pn))
+                os.symlink(pkg_ctx['workdir'], os.path.join( \
+                    self.uh_recipes_succeed_dir, pkg_ctx['PN']))
 
-                I(" %s: Upgrade SUCCESSFUL! Please test!" % self.pn)
+                I(" %s: Upgrade SUCCESSFUL! Please test!" % pkg_ctx['PN'])
             except Exception as e:
                 if isinstance(e, UpgradeNotNeededError):
-                    I(" %s: %s" % (self.pn, e.message))
+                    I(" %s: %s" % (pkg_ctx['PN'], e.message))
                 elif isinstance(e, UnsupportedProtocolError):
-                    I(" %s: %s" % (self.pn, e.message))
+                    I(" %s: %s" % (pkg_ctx['PN'], e.message))
                 else:
                     if not isinstance(e, Error):
                         import traceback
@@ -568,24 +470,25 @@ class Updater(object):
                         e = Error(message=msg)
                         error = e
 
-                    E(" %s: %s" % (self.pn, e.message))
+                    E(" %s: %s" % (pkg_ctx['PN'], e.message))
 
-                    if os.listdir(self.workdir):
+                    if os.listdir(pkg_ctx['workdir']):
                         E(" %s: Upgrade FAILED! Logs and/or file diffs are 
available in %s"
-                            % (self.pn, self.workdir))
+                            % (pkg_ctx['PN'], pkg_ctx['workdir']))
 
-                error = e
+                pkg_ctx['error'] = e
 
-                os.symlink(self.workdir, os.path.join( \
-                    self.uh_recipes_failed_dir, self.pn))
+                os.symlink(pkg_ctx['workdir'], os.path.join( \
+                    self.uh_recipes_failed_dir, pkg_ctx['PN']))
 
-            self._commit_changes()
+            self.commit_changes(pkg_ctx)
 
-            self.pkg_upgrade_handler(error)
+            self.statistics.update(pkg_ctx['PN'], pkg_ctx['NPV'],
+                    pkg_ctx['MAINTAINER'], pkg_ctx['error'])
 
-            self.statistics.update(self.pn, self.new_ver, self.maintainer, 
error)
+            self.pkg_upgrade_handler(pkg_ctx)
 
-        if (attempted_pkgs > 1):
+        if attempted_pkgs > 1:
             statistics_summary = self.statistics.pkg_stats() + \
                     self.statistics.maintainer_stats()
 
@@ -603,9 +506,6 @@ class UniverseUpdater(Updater):
     def __init__(self):
         Updater.__init__(self, True, True)
 
-        # XXX: assume that the poky directory is the first entry in the PATH
-        self.git = Git(os.path.dirname(os.getenv('PATH', False).split(':')[0]))
-
         # read history file
         self.history_file = os.path.join(get_build_dir(), "upgrade-helper", 
"history.uh")
         self.history = dict()
@@ -642,7 +542,6 @@ class UniverseUpdater(Updater):
             I(" Removing tmp directory ...")
             shutil.rmtree(os.path.join(get_build_dir(), "tmp"))
 
-
     def _check_upstream_versions(self, packages=[("universe", None, None)]):
         I(" Fetching upstream version(s) ...")
 
@@ -789,10 +688,10 @@ class UniverseUpdater(Updater):
                            upgrade_status + "\n")
         os.rename(self.history_file + ".tmp", self.history_file)
 
-    def pkg_upgrade_handler(self, err):
-        super(UniverseUpdater, self).pkg_upgrade_handler(err)
-        self._update_history(self.pn, self.new_ver, self.maintainer,
-                self._get_status_msg(err))
+    def pkg_upgrade_handler(self, pkg_ctx):
+        super(UniverseUpdater, self).pkg_upgrade_handler(pkg_ctx)
+        self._update_history(pkg_ctx['PN'], pkg_ctx['NPV'], 
pkg_ctx['MAINTAINER'],
+                self._get_status_msg(pkg_ctx['error']))
 
     def run(self):
         self._update_master()
-- 
2.1.4

-- 
_______________________________________________
yocto mailing list
yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to