From fb415b5c58d773b0757bcbcdac57b9506c39d254 Mon Sep 17 00:00:00 2001
From: Iikka Eklund <iikka.eklund@digia.com>
Date: Mon, 17 Sep 2012 09:12:00 +0300
Subject: [PATCH] Add strict mode into SDK/installer packaging scripts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

By default the strict mode is enabled. If any archive, template or
metadata file is missing the script will stop executing. The strict
mode can be disabled e.g. for testing purposes.

Change-Id: Ibf96c93cb68488e34e3017b2f3f2034e1a49ee57
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Simo Fält <simo.falt@digia.com>
---
 release-tools/create_installer.py | 40 +++++++++++++++++++++++-
 release-tools/sdkcomponent.py     | 51 ++++++++++++++++++++++++-------
 2 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/release-tools/create_installer.py b/release-tools/create_installer.py
index 8b10863..e5af43f 100644
--- a/release-tools/create_installer.py
+++ b/release-tools/create_installer.py
@@ -89,8 +89,10 @@ OFFLINE_MODE                = False
 TESTCLIENT_MODE             = False
 ARCHIVE_LOCATION_RESOLVER   = None
 SDK_COMPONENT_LIST          = []
+SDK_COMPONENT_LIST_SKIPPED  = []
 SDK_COMPONENT_IGNORE_LIST   = []
 USE_OLD_REPOGEN_SYNTAX      = False
+STRICT_MODE                 = True
 
 INSTALLER_NAMING_SCHEME_COMPILER    = ''
 INSTALLER_NAMING_SCHEME_TARGET_ARCH = ''
@@ -201,6 +203,7 @@ def parse_cmd_line():
     global INSTALLER_NAMING_SCHEME_TARGET_ARCH
     global LICENSE_TYPE
     global CONFIGURATIONS_DIR
+    global STRICT_MODE
 
     MAIN_CONFIG_NAME = sys.argv[1]
     if(arg_count > 2):
@@ -233,6 +236,11 @@ def parse_cmd_line():
                 values = argument.split('=')
                 if values[1] != '':
                     CONFIGURATIONS_DIR = values[1]
+            elif argument.find('strict_mode') >= 0:
+                values = item.split('=')
+                tmp = values[1]
+                if tmp == 'false' or tmp == 'no':
+                    STRICT_MODE = False
             else:
                 print '*** Unsupported argument given: ' + argument
                 sys.exit(-1)
@@ -648,6 +656,7 @@ def finalize_package_archives(sdk_component):
 def parse_component_data(configuration_file, configurations_base_path):
     """Parse SDK component data"""
     global SDK_COMPONENT_LIST
+    global SDK_COMPONENT_LIST_SKIPPED
     global SDK_COMPONENT_IGNORE_LIST
     print ' -> Reading target configuration file: ' + configuration_file
     configuration = ConfigParser.ConfigParser()
@@ -665,7 +674,21 @@ def parse_component_data(configuration_file, configurations_base_path):
         if section.startswith(PACKAGE_NAMESPACE):
             if section not in SDK_COMPONENT_IGNORE_LIST:
                 sdk_component = SdkComponent(section, configuration, PACKAGES_DIR_NAME_LIST, ARCHIVE_LOCATION_RESOLVER)
-                SDK_COMPONENT_LIST.append(sdk_component)
+                # if online installer, we are interested only about the root component!
+                if not OFFLINE_MODE and not sdk_component.is_root_component():
+                    continue
+
+                # validate component
+                sdk_component.validate()
+                if sdk_component.is_valid():
+                    SDK_COMPONENT_LIST.append(sdk_component)
+                else:
+                    if STRICT_MODE:
+                        print sdk_component.error_msg()
+                        sys.exit(-1)
+                    else:
+                        print '!!! Ignored component in non-strict mode (missing archive data or metadata?): ' + section
+                        SDK_COMPONENT_LIST_SKIPPED.append(sdk_component)
     # check for extra configuration files if defined
     extra_conf_list = bldinstallercommon.safe_config_key_fetch(configuration, 'ExtraPackageConfigurationFiles', 'file_list')
     if extra_conf_list:
@@ -959,6 +982,19 @@ def create_mac_disk_image():
     bldinstallercommon.do_execute_sub_process(cmd_args, SCRIPT_ROOT_DIR, True)
 
 
+def print_warnings():
+    # check if any components were skipped
+    if SDK_COMPONENT_LIST_SKIPPED:
+        print ''
+        print 'Warning! The following components were not included in offline'
+        print '         installer or in online repository. The reason may be that'
+        print '         the script was run in non-strict mode and the packages'
+        print '         had incomplete metadata or the archive (.7z) was missing?'
+        print ''
+        for item in SDK_COMPONENT_LIST_SKIPPED:
+            print '*** ' + item.package_name
+
+
 ##############################################################
 # All main build steps
 ##############################################################
@@ -994,6 +1030,8 @@ def create_installer():
     # for mac we need some extra work
     if bldinstallercommon.is_mac_platform():
         create_mac_disk_image()
+    # print warning messages if encountered any problems
+    print_warnings()
 
 
 ##############################################################
diff --git a/release-tools/sdkcomponent.py b/release-tools/sdkcomponent.py
index 0e6acbb..faf9e3b 100644
--- a/release-tools/sdkcomponent.py
+++ b/release-tools/sdkcomponent.py
@@ -69,17 +69,16 @@ class SdkComponent:
             if self.archive_uri.startswith('http'):
                 res = bldinstallercommon.is_content_url_valid(self.archive_uri)
                 if not res:
-                    print '*** Archive check fail! ***\n*** Unable to locate archive: ' + self.archive_uri
-                    sys.exit(-1)
+                    return '*** Archive check fail! ***\n*** Unable to locate archive: ' + self.archive_uri
             elif not os.path.isfile(self.archive_uri):
-                print '*** Archive check fail! ***\n*** Unable to locate archive: ' + self.archive_uri
-                sys.exit(-1)
+                return '*** Archive check fail! ***\n*** Unable to locate archive: ' + self.archive_uri
 
 
     def __init__(self, section_name, target_config, packages_full_path_list, archive_location_resolver):
         self.static_component           = bldinstallercommon.safe_config_key_fetch(target_config, section_name, 'static_component')
         self.root_component             = bldinstallercommon.safe_config_key_fetch(target_config, section_name, 'root_component')
         self.package_name               = section_name
+        self.packages_full_path_list    = packages_full_path_list
         self.archives                   = bldinstallercommon.safe_config_key_fetch(target_config, section_name, 'archives')
         self.archives                   = self.archives.replace(' ', '')
         self.archive_server_name        = bldinstallercommon.safe_config_key_fetch(target_config, section_name, 'archive_server_name')
@@ -92,10 +91,21 @@ class SdkComponent:
         self.sorting_priority           = bldinstallercommon.safe_config_key_fetch(target_config, section_name, 'sorting_priority')
         self.downloadable_arch_list_qs  = []
         self.pkg_template_dir           = ''
+        self.sanity_check_error_msg     = ''
+        self.target_config              = target_config
+        self.archive_location_resolver  = archive_location_resolver
+
+
+    def is_root_component(self):
+        if self.root_component == 'yes' or self.root_component == 'true':
+            return True
+        return False
+
+    def validate(self):
         # look up correct package template directory from list
         found = False
-        for item in packages_full_path_list:
-            template_full_path = os.path.normpath(item + os.sep + section_name)
+        for item in self.packages_full_path_list:
+            template_full_path = os.path.normpath(item + os.sep + self.package_name)
             if os.path.exists(template_full_path):
                 if not (found):
                     # take the first match
@@ -108,37 +118,56 @@ class SdkComponent:
                     print '*** Only one template for package should exist!'
                     print '*** Fix your configuration! Abort!'
                     sys.exit(-1)
-        self.parse_archives(target_config, archive_location_resolver)
-        self.check_component_data(target_config)
+        self.parse_archives(self.target_config, self.archive_location_resolver)
+        self.check_component_data(self.target_config)
 
 
     def check_component_data(self, target_config):
         if self.static_component:
             if not os.path.isfile(self.static_component):
                 self.sanity_check_fail(self.package_name, 'Unable to locate given static package: ' + self.static_component)
+                return
             # no more checks needed for static component
             return
         if not self.package_name:
             self.sanity_check_fail(self.package_name, 'Undefined package name?')
+            return
         if self.archives and not self.target_install_base:
             self.sanity_check_fail(self.package_name, 'Undefined target_install_base?')
+            return
         if self.version and not self.version_tag:
             self.sanity_check_fail(self.package_name, 'Undefined version_tag?')
+            return
         if self.version_tag and not self.version:
             self.sanity_check_fail(self.package_name, 'Undefined version?')
+            return
         if self.package_default not in ['true', 'false', 'script']:
             self.package_default = 'false'
         # check that package template exists
         if not os.path.exists(self.pkg_template_dir):
             self.sanity_check_fail(self.package_name, 'Package template dir does not exist: ' + self.pkg_template_dir)
+            return
         # next check that archive locations exist
         for archive in self.downloadable_archive_list:
-            archive.check_archive_data()
+            error_msg = archive.check_archive_data()
+            if error_msg:
+                self.sanity_check_fail(self.package_name, error_msg)
+                return
 
 
     def sanity_check_fail(self, component_name, message):
-        print '\n*** Sanity check fail! ***\n*** Component: [' + component_name + ']\n*** ' + message
-        sys.exit(-1)
+        self.sanity_check_error_msg = '*** Sanity check fail! ***\n*** Component: [' + component_name + ']\n*** ' + message
+
+
+    def is_valid(self):
+        if self.sanity_check_error_msg:
+            return False
+        else:
+            return True
+
+
+    def error_msg(self):
+        return self.sanity_check_error_msg
 
 
     def parse_archives(self, target_config, archive_location_resolver):
-- 
GitLab