]> SALOME platform Git repositories - tools/sat.git/commitdiff
Salome HOME
new option noboolean as implicit False
authorChristian Van Wambeke <chvw@orange.fr>
Sat, 26 May 2018 06:51:25 +0000 (08:51 +0200)
committerChristian Van Wambeke <chvw@orange.fr>
Sat, 26 May 2018 06:51:25 +0000 (08:51 +0200)
commands/patch.py
commands/source.py
src/loggingSat.py
src/options.py
src/returnCode.py
src/salomeTools.py

index a057bd04f99f49db66827d837b22b68f92622428..3b3c2abe9690dc874875950bafb2bbdbd423b58c 100644 (file)
@@ -18,7 +18,7 @@
 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
 import os
-import subprocess as sP
+import pprint as PP
 
 import src.debug as DBG
 import src.returnCode as RCO
@@ -75,9 +75,9 @@ class Command(_BaseCommand):
 
     # Print some informations
     logger.info("Patching sources of the application %s" % \
-                UTS.blue(config.VARS.application))
+                UTS.label(config.VARS.application))
 
-    logger.info("  workdir = %s" % UTS.blue(config.APPLICATION.workdir))
+    logger.info("  workdir = %s" % UTS.info(config.APPLICATION.workdir))
 
     # Get the products list with products informations regarding the options
     products_infos = self.get_products_list(options, config)
@@ -90,112 +90,87 @@ class Command(_BaseCommand):
     # The loop on all the products on which to apply the patches
     good_result = 0
     for tmp, product_info in products_infos:
-        # Apply the patch
-        rc = apply_patch(config, product_info, max_product_name_len, logger)
-        logger.info(str(rc))
-        if rc.isOk():
-            good_result += 1
+      # Apply the patch
+      rc = apply_patch(config, product_info, max_product_name_len, logger)
+      if rc.isOk():
+        good_result += 1
     
     # Display the results (how much passed, how much failed, etc...)
-
     if good_result == len(products_infos):
-        status = "OK"
+      status = "OK"
     else:
-        status = "KO"
+      status = "KO"
     
     # write results
     msg = ("Patching sources of the application: <%s> (%d/%d)") % \
-                  (status, good_result, len(products_infos))
-    logger.info(msg)    
-
+           (status, good_result, len(products_infos))
+    logger.info(msg) 
     return RCO.ReturnCode(status, msg)
      
 
 def apply_patch(config, product_info, max_product_name_len, logger):
-    """The method called to apply patches on a product
-
-    :param config: (Config) The global configuration
-    :param product_info: (Config) 
-      The configuration specific to the product to be patched
-    :param logger: (Logger: 
-      The logger instance to use for the display and logging
-    :return: (RCO.ReturnCode)
-    """
-
-    # if the product is native, do not apply patch
-    if PROD.product_is_native(product_info):
-        # display and log
-        logger.info('%s: ' % UTS.label(product_info.name))
-        logger.info(' ' * (max_product_name_len - len(product_info.name)))
-        logger.info("\n")
-        msg = _("The %s product is native. Do not apply any patch") % product_info.name
-        logger.info(msg + "\n")
-        return RCO.ReturnCode("OK", msg)     
-
-    if not "patches" in product_info or len(product_info.patches) == 0:
-        # display and log
-        logger.info('%s: ' % UTS.label(product_info.name))
-        logger.info(' ' * (max_product_name_len - len(product_info.name)))
-        logger.info("\n")
-        msg = _("No patch for the %s product") % product_info.name
-        logger.info(msg + "\n")
-        return RCO.ReturnCode("OK", msg) 
-    else:
-        # display and log
-        logger.info('%s: ' % UTS.label(product_info.name))
-        logger.info(' ' * (max_product_name_len - len(product_info.name)))
-        logger.info("\n")
-
-    if not os.path.exists(product_info.source_dir):
-        msg = _("No sources found for the %s product") % product_info.name
-        logger.error(UTS.red(msg))
-        return RCO.ReturnCode("KO", msg)
-
-    # At this point, there one or more patches and the source directory exists
-    retcode = []
-    res = []
-    # Loop on all the patches of the product
-    for patch in product_info.patches:
-        details = []
-        
-        # Check the existence and apply the patch
-        if os.path.isfile(patch):
-            patch_cmd = "patch -p1 < %s" % patch
-            
-            # Write the command in the terminal if verbose level is at 5
-            logger.info("    >%s\n" % patch_cmd)
-            
-            # Write the command in the log file (can be seen using 'sat log')
-            logger.logTxtFile.write("\n    >%s\n" % patch_cmd)
-            logger.logTxtFile.flush()
-            
-            # Call the command
-            res_cmd = SP.call(patch_cmd, shell=True, cwd=product_info.source_dir, 
-                              stdout=logger.logTxtFile, stderr=SP.STDOUT )
-                         
-            res_cmd = (res_cmd == 0)       
-        else:
-            res_cmd = False
-            details.append("  " + UTS.red(_("Not a valid patch: %s\n")) % patch)
-
-        res.append(res_cmd)
-        
-        if res_cmd:
-            message = _("Apply patch %s") % UTS.blue(patch)
-        else:
-            message = _("Failed to apply patch %s") % UTS.red(patch)
-
-        if config.USER.output_verbose_level >= 3:
-            retcode.append("  %s" % message)
-        else:
-            retcode.append("%s: %s" % (product_info.name, message))
-        
-        if len(details) > 0:
-            retcode.extend(details)
-
-    if False in res: 
+  """The method called to apply patches on a product
+
+  :param config: (Config) The global configuration
+  :param product_info: (Config) 
+    The configuration specific to the product to be patched
+  :param logger: (Logger: 
+    The logger instance to use for the display and logging
+  :return: (RCO.ReturnCode)
+  """
+
+  # if the product is native, do not apply patch
+  msg = '%s: ' % UTS.label(product_info.name)
+  if PROD.product_is_native(product_info):
+    # display and log
+    msg += _("The product is native. Do not apply any patch")
+    logger.info(msg)
+    return RCO.ReturnCode("OK", msg)     
+
+  if not "patches" in product_info or len(product_info.patches) == 0:
+    # display and log
+    msg += _("No patch for the product")
+    logger.info(msg)
+    return RCO.ReturnCode("OK", msg) 
+  else:
+    # display and log after action
+    pass
+
+  if not os.path.exists(product_info.source_dir):
+    msg += _("No sources found for the product")
+    logger.error(UTS.red(msg))
+    return RCO.ReturnCode("KO", msg)
+
+  # At this point, there one or more patches and the source directory exists
+  retcodes = []
+  rc = "OK"
+  # Loop on all the patches of the product
+  for patch in product_info.patches:
+    details = []
+    # Check the existence and apply the patch
+    if not os.path.isfile(patch):
+      msg += _("Patch file %s not found") % UTS.info(patch)
+      logger.error(msg)
+      continue
+    
+    cmd = """
+set -x
+patch -p1 < %s
+""" % patch         
+    # Call the command
+    res = UTS.Popen(cmd, cwd=product_info.source_dir, logger=logger)
+    if not res.isOk():
       rc = "KO"
+      resPatch = RCO.ReturnCode("KO", _("Failed to apply patch %s") % UTS.red(patch))
     else:
-      rc = "OK"
-    
-    return RCO.ReturnCode(rc, "\n".join(retcode))
+      resPatch = RCO.ReturnCode("OK", _("Apply patch %s") % UTS.info(patch))
+    retcodes.append(resPatch)
+  
+  res = RCO.ReturnCodeFromList(retcodes)
+  if res.isOk(): 
+    logger.info(msg + "...<OK>")
+    logger.trace(msg + "...<OK> %s" % res.getWhy())
+  else: 
+    logger.info(msg + "...<KO> %s" % res.getWhy())
+  return res
+
index 94c7681a1966c22fed7590cd042b6016c74ba788..7756f5857472270486b0af964530a5c2b07a422a 100644 (file)
@@ -167,7 +167,7 @@ def get_source_from_git(product_info,
         repo_git = product_info.git_info.repo    
         
     # Display informations
-    msg =  " %s:%s tag:%s ..."  % (coflag, repo_git, product_info.git_info.tag)
+    msg =  " %s:%s tag:%s ..."  % (coflag, UTS.info(repo_git), product_info.git_info.tag)
     logger.info(msg)
     
     # Call the system function that do the extraction in git mode
@@ -188,24 +188,21 @@ def get_source_from_archive(product_info, source_dir, logger):
     :return: (bool) True if it succeed, else False
     """
     # check archive exists
-    if not os.path.exists(product_info.archive_info.archive_name):
-        raise Exception(_("Archive not found: '%s'") % \
-                               product_info.archive_info.archive_name)
+    archName = product_info.archive_info.archive_name
+    if not os.path.exists(archName):
+        raise Exception(_("Archive not found: '%s'") % archName)
 
-    logger.info('arc:%s ... ' % UTS.info(product_info.archive_info.archive_name))
+    logger.info(' arc:%s ...' % UTS.info(archName))
     # Call the system function that do the extraction in archive mode
-    retcode, NameExtractedDirectory = SYSS.archive_extract(
-                                    product_info.archive_info.archive_name,
-                                    source_dir.dir(), logger)
+    retcode = SYSS.archive_extract(archName, source_dir.dir(), logger)
+    nameDirectory = retcode.getValue() # where extracted
     
     # Rename the source directory if 
     # it does not match with product_info.source_dir
-    if (NameExtractedDirectory.replace('/', '') != 
-            os.path.basename(product_info.source_dir)):
-        shutil.move(os.path.join(os.path.dirname(product_info.source_dir), 
-                                 NameExtractedDirectory), 
-                    product_info.source_dir)
-    
+    baseDir = os.path.basename(product_info.source_dir)
+    if (nameDirectory.replace('/', '') != baseDir):
+      iniDir = os.path.join(os.path.dirname(product_info.source_dir), nameDirectory)
+      shutil.move(iniDir, product_info.source_dir)  
     return retcode
 
 def get_source_from_dir(product_info, source_dir, logger):
@@ -229,7 +226,7 @@ def get_source_from_dir(product_info, source_dir, logger):
         logger.error(msg)
         return False
     
-    logger.info('DIR: %s ... ' % UTS.info(product_info.dir_info.dir))
+    logger.info(' DIR: %s ...' % UTS.info(product_info.dir_info.dir))
     retcode = UTS.Path(product_info.dir_info.dir).copy(source_dir) 
     return retcode
     
@@ -275,17 +272,13 @@ def get_source_from_cvs(user,
     coflag = 'cvs'
     if checkout: coflag = coflag.upper()
 
-    msg = '%s:%s' % (coflag, cvs_line)
-    msg += " " * (pad + 50 - len(cvs_line))
+    msg = " %s:%s" % (coflag, cvs_line)
     msg += " src:%s" % product_info.cvs_info.source
-    msg += " " * (pad + 1 - len(product_info.cvs_info.source))
     msg += " tag:%s" % product_info.cvs_info.tag
                  
     # at least one '.' is visible
-    msg += " %s. " % ("." * (10 - len(product_info.cvs_info.tag)))
-                 
+    msg += " %s ..." % msg
     logger.info(msg)
-
     # Call the system function that do the extraction in cvs mode
     retcode = SYSS.cvs_extract(protocol, user,
                                  product_info.cvs_info.server,
@@ -320,8 +313,7 @@ def get_source_from_svn(user,
     coflag = 'svn'
     if checkout: coflag = coflag.upper()
 
-    logger.info('%s:%s ... ' % (coflag, product_info.svn_info.repo))
-
+    logger.info(' %s:%s ...' % (coflag, product_info.svn_info.repo))
     # Call the system function that do the extraction in svn mode
     retcode = SYSS.svn_extract(user, 
                                product_info.svn_info.repo, 
index 5a6048de754ff24c1797eaa73d4fa179f7c6c63e..70670d88d8579af8d5fa0107d53967c90ef20fed 100755 (executable)
@@ -66,6 +66,7 @@ _TRACE = LOGI.INFO - 2 # trace level is just below STEP
 LOGI.STEP = _STEP # only for coherency,
 LOGI.TRACE = _TRACE # only for coherency,
 
+_knownLevels = "CRITICAL ERROR WARNING INFO STEP TRACE DEBUG".upper().split()
 
 #################################################################
 # utilities methods
@@ -206,6 +207,7 @@ class LoggerSat(LOGI.Logger):
     LOGI.addLevelName(_STEP, "STEP")
     LOGI.addLevelName(_TRACE, "TRACE")
     self.dateLogger = "NoDateLogger"
+    self.dateHour = None # datehour of main command
     self.isClosed = False
     self.idCommandHandlers = 0 # incremented, 0 for main command 1, 2, etc. for micro command
     self.STEP = _STEP
@@ -292,7 +294,12 @@ class LoggerSat(LOGI.Logger):
     log_dir_out = os.path.join(log_dir, "OUT") # files txt
     UTS.ensure_path_exists(log_dir)
     UTS.ensure_path_exists(log_dir_out)
-    datehour = config.VARS.datehour
+    if self.idCommandHandlers == 0:
+      datehour = config.VARS.datehour
+      self.dateHour = datehour # save dateHour for micro commands
+    else:
+      datehour = self.dateHour # micro commands have same datehour for naming files
+
     cmd = config.VARS.command
     fullNameCmd = cmdInstance.getFullNameStr()
     hostname = config.VARS.hostname
index 4e1a8abb2bbf19676e604f39f831517eb98e29da..8bb831eb544870686eaac0a5e4f51bebb66bef25 100644 (file)
@@ -85,7 +85,8 @@ class Options(object):
         # in a list that contains dicts
         self.options = []
         # The list of available option type
-        self.availableOptions = "boolean string int float long list list2 level".split()
+        self.availableOptions = "noboolean boolean string int float long list list2 level".split()
+        self.noArgOptions = "noboolean boolean".split()
         self.default = None
         self.results = {}
 
@@ -192,11 +193,11 @@ class Options(object):
         longNameOption = []
         for option in self.options:
             shortNameOption = shortNameOption + option['shortName']
-            if option['shortName'] != "" and option['optionType'] != "boolean":
+            if option['shortName'] != "" and option['optionType'] not in self.noArgOptions:
                 shortNameOption = shortNameOption + ":"
 
             if option['longName'] != "":
-                if option['optionType'] != "boolean":
+                if option['optionType'] not in self.noArgOptions:
                     longNameOption.append(option['longName'] + "=")
                 else:
                     longNameOption.append(option['longName'])
@@ -206,7 +207,7 @@ class Options(object):
         try:
           optlist, args = getopt.getopt(argList, shortNameOption, longNameOption)
         except Exception as e:
-          msg = str(e) + " on %s\n\n" % argList + self.get_help()
+          msg = str(e) + " on '%s'\n\n" % " ".join(argList) + self.get_help()
           raise Exception(msg)
 
         # instantiate and completing the optResult that will be returned
@@ -221,6 +222,8 @@ class Options(object):
                         option['result'] = opt[1]
                     elif optionType == "boolean":
                         option['result'] = True
+                    elif optionType == "noboolean":
+                        option['result'] = False
                     elif optionType == "int":
                         option['result'] = int(opt[1])
                     elif optionType == "float":
@@ -232,16 +235,11 @@ class Options(object):
                             option['result'] = list()
                         option['result'].append(opt[1])
                     elif optionType == "level": #logger logging levels
-                        option['result'] = opt[1]
-                        # TODO test in (lowercase) debug info warning error critical
+                        option['result'] = self.filterLevel(opt[1])
                     elif optionType == "list2":
                         if option['result'] is None:
                             option['result'] = list()
-                        if opt[1].find(",") == -1:
-                            option['result'].append(opt[1])
-                        else:
-                            elts = filter(lambda l: len(l) > 0, opt[1].split(","))
-                            option['result'].extend(elts)
+                        option['result'] = self.filterList2(opt[1])
 
             optResult.__setattr__(option['destName'], option['result'])
             # free the option in order to be able to make 
@@ -251,6 +249,26 @@ class Options(object):
         self.results = {"optlist": optlist, "optResult": optResult, "args": args, "argList": argList}
         DBG.write("results", self.results)
         return optResult, args
+        
+    def filterLevel(self, aLevel):
+      """filter level logging values"""
+      import src.loggingSat as LOG
+      aLev = aLevel.upper()
+      knownLevels = LOG._knownLevels
+      maxLen = max([len(i) for i in knownLevels])
+      for i in range(maxLen):
+        for lev in knownLevels:
+          if aLev == lev[:i]:
+            DBG.write("filterLevel", "%s -> %s" % (aLevel, lev), True) 
+            return lev
+      msg = "Unknown level '%s', accepted are:\n%s" % (aLev, ",".join(knownLevels))
+      raise Exception(msg)
+      
+    def filterList2(self, aStr):
+      """filter a list as 'KERNEL,YACS,etc.'"""
+      aList = aStr.strip().split(",")
+      return aList
+      
 
     def __repr__(self): 
         """
index de6fe230bb49d43db328f04e6cd3147cf3238698..c2441b39bb5a39bc14ce20eb668c027dbddd5574 100644 (file)
@@ -212,3 +212,20 @@ class ReturnCode(object):
       return self
     else:
       raise Exception(self.getWhy())
+
+def ReturnCodeFromList(aListOfReturnCodes):
+  """
+  Create ReturnCode from list of ReturnCode
+  
+  convenience over "+" operand
+  """
+  res = "OK"
+  whyes = []
+  for rc in aListOfReturnCodes:
+    if not rc.isOk():
+      res = "KO"
+    whyes.append(str(rc))
+  reswhy = "\n  ".join(whyes)
+  return ReturnCode(res, "\n  " + reswhy)
+    
+    
\ No newline at end of file
index 3365d44d91157472e3c207dbb09c911a83d45034..bed28dc7426091f936ded92c70a5a7c3519d8579 100755 (executable)
@@ -486,18 +486,27 @@ class Sat(object):
         (internal use only)
         """
         parser = Options()
+        
         parser.add_option('h', 'help', 'boolean', 'help', 
                           _("shows global help or help on a specific command."))
+        
         parser.add_option('o', 'overwrite', 'list', "overwrite", 
                           _("overwrites a configuration parameters."))
-        parser.add_option('g', 'debug', 'boolean', 'debug_mode', 
-                          _("run salomeTools in debug mode."))
-        parser.add_option('v', 'verbose', 'int', "output_verbose_level", 
-                          _("change output verbose level (default is 3)."))
+        
+        parser.add_option('v', 'verbose', 'level', "output_verbose_level", 
+                          _("change console output verbose level (default is INFO)."))
+        
+        parser.add_option('d', 'devel', 'noboolean', "development mode", 
+                          _("""\
+development mode (more verbose error/exception messages) 
+(default is production mode)."""))
+        
         parser.add_option('b', 'batch', 'boolean', "batch", 
                           _("batch mode (no question)."))
-        parser.add_option('t', 'all_in_terminal', 'boolean', "all_in_terminal", 
-                          _("all traces in the terminal (for example compilation logs)."))
+                          
+        parser.add_option('t', 'terminal_all_log', "noboolean", 'terminal_all_log',
+                          _("all log traces in the terminal (for example compilation logs)."))
+
         parser.add_option('l', 'logs_paths_in_file', 'string', "logs_paths_in_file", 
                           _("put the command result and paths to log files."))
         return parser
@@ -506,8 +515,8 @@ class Sat(object):
     def parseArguments(self, arguments):
         args = self.assumeAsList(arguments)
         genericOptions, remaindersArgs = self.parser.parse_args(args)
-        DBG.write("Sat generic options", genericOptions)
-        DBG.write("Sat remainders arguments", remaindersArgs)
+        DBG.write("Sat generic options", genericOptions, True)
+        DBG.write("Sat remainders arguments", remaindersArgs, True)
         return genericOptions, remaindersArgs