From: vsr Date: Tue, 10 Jan 2006 15:41:18 +0000 (+0000) Subject: Merge improvements from SALOME_3 branch X-Git-Tag: V_3_2_0a1_Debian~5 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=81bdc1a32758116475917379121a837c663b84bc;p=tools%2Finstall.git Merge improvements from SALOME_3 branch --- diff --git a/bin/SALOME_InstallWizard b/bin/SALOME_InstallWizard index 08dae42..dba449b 100755 Binary files a/bin/SALOME_InstallWizard and b/bin/SALOME_InstallWizard differ diff --git a/bin/extract_params.py b/bin/extract_params.py deleted file mode 100644 index cc988dd..0000000 --- a/bin/extract_params.py +++ /dev/null @@ -1,113 +0,0 @@ -#============================================================== -# -#============================================================== -def get_help_info() : - return "\tUsage : \n\tpython install.py [-gui|tui] [-f ] [-t taget_dir] [-tmp tmp_dir]\n" - -#============================================================== -# -#============================================================== -def error_exit (str = ""): - import sys - if len(str): res = "\n" + str + "\n" - else : res = "" - print res + \ - get_help_info() + \ - "\nWrong parameters\n\n"; - sys.exit(1); - - -#============================================================== -# Cheks whether the passed parameter is a key. -#============================================================== -def is_key ( val ): - import re - if val is not None : - return re.match(r'^-[a-zA-Z]', val) - return 0 - -#============================================================== -# -#============================================================== -def extract_parameter ( key, args ) : - import sys - length = len(args); - if ( length == 0 ) : return None - - found = 0; - - for i in range(0, length-1): - if args[i] == key : - if ( is_key ( args[i+1]) ) : - print " No value after key ", key - sys.exit(1); - - value = args[i+1] - if ( i < length - 2 and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key - #(not a list). In this case params are correct. - print "Too much values after key ", key - sys.exit(1); - - found = 1; break; - - if (found) : - return value - - return None - - -#=============================================================== -# extracts list of values following specified 'key' from 'args[]' -#=============================================================== -def extract_list (key, args) : - - lenght = len(args) - if ( args is None or lenght == 0 ): - error_exit() - - list=[] - found = 0 - - for i in range(0, length) : - if args[i] == key : - if (is_key ( args[i+1])) : - error_exit(); - - for i in range (i+1, lenght): - if is_key(args[i]) : break - list.append(args[i]) - found =1; break - - return list; #empty list is returned if no values after key - - -#============================================================== -# Method find the $key in the list and return 1 if success -# and 0 otherwise. -#============================================================== -def find_key (key, argv) : - - if (not is_key(key)) : return 0 - - for simbol in argv : - if simbol == key: - return 1 - return 0 - -#============================================================== -# -#============================================================== -def parse_parameters (args) : - - if find_key('-h', args) : - print get_help_info(); - import sys - sys.exit(0) - - xmlfile = extract_parameter("-f", args) - target_dir = extract_parameter("-t", args) - tmp_dir = extract_parameter("-tmp", args) - if find_key('-tui', args): - is_gui = 0 - else : is_gui = 1 - return [xmlfile, target_dir, tmp_dir, is_gui] diff --git a/config.xml b/config.xml index 8abe206..715571c 100644 --- a/config.xml +++ b/config.xml @@ -4,7 +4,7 @@ copyright="<h5>Copyright (C) 2003-2005 OPEN CASCADE,<br>EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D,<br>LEG, PRINCIPIA R&D, BUREAU VERITAS</h5>" license="<h5>GNU LGPL</h5>" os="DebianSarge"/> - - _setup.py + mv _setup.py setup.py fi -fi -if [ "$found" -eq "1" ] ; then - check_lib_version libcblas.so - if [ "$?" -ne "0" ] ; then - found=0 + if [ "$f77blas_nf" -eq "1" ] ; then + sed -e "s%\(^libraries_list = \[.*\)\('f77blas', \)\(.*\)$%\1\3%g" setup.py > _setup.py + mv _setup.py setup.py fi -fi -if [ "$found" -eq "1" ] ; then - check_lib_version libatlas.so - if [ "$?" -ne "0" ] ; then - found=0 + if [ "$cblas_nf" -eq "1" ] ; then + sed -e "s%\(^libraries_list = \[.*\)\('cblas', \)\(.*\)$%\1\3%g" setup.py > _setup.py + mv _setup.py setup.py fi -fi -# if any library is not found modify build procedure -if [ "$found" -eq "0" ] ; then - cp setup.py setup.py.orig - sed -e "s%^use_dotblas = 1%use_dotblas = 0%g" -e "s%^libraries_list = \['lapack', 'cblas', 'f77blas', 'atlas', 'g2c'\]%libraries_list = \['g2c'\]%g" setup.py.orig > setup.py + if [ "$atlas_nf" -eq "1" ] ; then + sed -e "s%\(^libraries_list = \[.*\)\('atlas', \)\(.*\)$%\1\3%g" setup.py > _setup.py + mv _setup.py setup.py + fi + if [ "$g2c_nf" -eq "1" ] ; then + sed -e "s%\(^libraries_list = \[.*\)\('g2c'\)\(.*\)$%\1\3%g" setup.py > _setup.py + mv _setup.py setup.py + fi + sed -e "s%^use_dotblas = 1%use_dotblas = 0%g" setup.py > _setup.py + mv _setup.py setup.py + sed -e "s%#\(os.path.join('Src', 'blas_lite.c'),\)%\1%g" setup.py > _setup.py + mv _setup.py setup.py + sed -e "s%#\(os.path.join('Src', 'f2c_lite.c'),\)%\1%g" setup.py > _setup.py + mv _setup.py setup.py + sed -e "s%#\(os.path.join('Src', 'zlapack_lite.c'),\)%\1%g" setup.py > _setup.py + mv _setup.py setup.py + sed -e "s%#\(os.path.join('Src', 'dlapack_lite.c')\)%\1%g" setup.py > _setup.py + mv _setup.py setup.py chmod a+x setup.py fi diff --git a/config_files/build.csh b/config_files/build.csh index 9334e9a..a9f0a44 100755 --- a/config_files/build.csh +++ b/config_files/build.csh @@ -1,7 +1,7 @@ #! /bin/csh -f ################################################################################################## # Name : build.csh -# Description: Build and install SALOME2 modules from sources +# Description: Build and install SALOME modules from sources # Author : Vadim SANDLER (VSR), Open CASCADE S.A. # Created : 27.01.2005 ################################################################################################## diff --git a/config_files/common.sh b/config_files/common.sh index 395a2de..f48202c 100755 --- a/config_files/common.sh +++ b/config_files/common.sh @@ -18,7 +18,6 @@ export DELIM="------" export SHRC="salome.sh" export CSHRC="salome.csh" -export DEBUG=1 #this function takes several parameters #first parameter contains descriptor of output file @@ -29,19 +28,21 @@ check_job() { out=$1 shift - echo -e "`pwd` -> $* >> $out" - if [ $DEBUG == 0 ] ; then - $* | tee $out + errfile=/tmp/errlog + if [ -n "$INSTALL_WORK" ] ; then errfile=$INSTALL_WORK/errlog; fi + cmd="`pwd` -> $*" + if [ "$out" != "1" ] ; then cmd="$cmd >> $out" ; fi + echo -e $cmd + if [ "$out" != "1" ] ; then + $* >> $out 2>$errfile else - if [ $out == "1" ] ; then $* - else - $* >> $out 2>&1 - fi fi if [ "$?" -ne "0" ] ; then if [ $out != "1" ] ; then cat $out + cat $errfile >&2 + cat $errfile >> $out fi # VSR : 10/11/05: disable answer mode ==> #echo -n " " >&2 @@ -129,7 +130,8 @@ done # 1. first dump all environment files into the $SHRC file product_sequence="$2" for i in $product_sequence ; do - cat ${install_work}/env_${i}.sh >> ${install_work}/$SHRC 2>/dev/null + env_file=${install_work}/env_${i}.sh + ( test -e $env_file && cat $env_file >> ${install_work}/$SHRC 2>/dev/null ) done # 2. writing global functions to _salome.sh file diff --git a/runInstall b/runInstall index d5cf914..4a4796f 100755 --- a/runInstall +++ b/runInstall @@ -5,353 +5,66 @@ warnings.filterwarnings("ignore", "", DeprecationWarning) import xmllib import sys, os, string, re +from optparse import OptionParser -#============================================================== -# get_help_info -#============================================================== -def get_help_info() : - str = "\nSALOME Installation Wizard\n\n" - str = str + "\tUsage : \n\tInstall [-g|b] [-f ] [-t ] [-tmp ]\n" - str = str + "\n" - str = str + " -g Runs the Installation Wizard in the GUI mode.\n" - str = str + " In this case only is taken into account \n" - str = str + " from the parameters list. This key is used by default.\n" - str = str + "\n" - str = str + " -b Runs the Installation Wizard in the batch mode.\n" - str = str + " All the found parameters are taken in to account.\n" - str = str + "\n" - str = str + " -f The configuration file to be parsed by the Installation Wizard.\n" - str = str + " If this parameter is missed then the script tries to define\n" - str = str + " the Red Hat version and use the corresponding xml. For example,\n" - str = str + " for Red Hat 8.0 config_RedHat_8.0.xml file is supposed to be used\n" - str = str + " by default. If the appropriate xml file is not found, the config.xml\n" - str = str + " is used by default.\n" - str = str + "\n" - str = str + " -t The target directory the products to be installed to.\n" - str = str + " This parameter overloads the target directory described in the\n" - str = str + " configuration file.\n" - str = str + "\n" - str = str + " -tmp The directory which should be used for the temporary files.\n" - str = str + " This parameter overloads the temporary directory described in the\n" - str = str + " configuration file.\n" - str = str + "\n" - str = str + " -h Prints this help information.\n" - return str - -#============================================================== -# message finction -#============================================================== -def message(msg): - print ">>>", msg - -#============================================================== -# error_exit -#============================================================== -def error_exit (str = ""): - import sys - if len(str): res = "\n" + str + "\n" - else : res = "" - print res + \ - get_help_info() - sys.exit(1); - - -#============================================================== -# Cheks whether the passed parameter is a key. -#============================================================== -def is_key ( val ): - import re - if val is not None : - return re.match(r'^-[a-zA-Z]', val) - return 0 - -#============================================================== -# From the list of parameters extracts value following 'key' -#============================================================== -def extract_parameter ( key, args ) : - import sys - length = len(args); - if ( length == 0 ) : return None - - found = 0; - - for i in range(0, length-1): - if args[i] == key : - if ( is_key ( args[i+1]) ) : - print " No value after key ", key - sys.exit(1); - - value = args[i+1] - if ( i < length - 2 and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key - #(not a list). In this case params are correct. - print "Too much values after key ", key - sys.exit(1); - - found = 1; break; - - if (found) : - return value - - return None - - -#=============================================================== -# Extracts list of values following specified 'key' from 'args[]' -#=============================================================== -def extract_list (key, args) : - - lenght = len(args) - if ( args is None or lenght == 0 ): - error_exit() - - list=[] - found = 0 - - for i in range(0, length) : - if args[i] == key : - if (is_key ( args[i+1])) : - error_exit(); - - for i in range (i+1, lenght): - if is_key(args[i]) : break - list.append(args[i]) - found =1; break - - return list; #empty list is returned if no values after key - +opt_parser = None +root_path = None -#============================================================== -# Method find the $key in the list and return 1 if success -# and 0 otherwise. -#============================================================== -def find_key (key, argv) : - - if (not is_key(key)) : return 0 - - for simbol in argv : - if simbol == key: - return 1 - return 0 - -#============================================================== -# Parse the list of parameters -#============================================================== -def parse_parameters (args) : - - if find_key('-h', args) : - print get_help_info(); - import sys - sys.exit(0) - - xmlfile = extract_parameter("-f", args) - target_dir = extract_parameter("-t", args) - tmp_dir = extract_parameter("-tmp", args) - if find_key('-b', args): - is_gui = 0 - else : is_gui = 1 - return [xmlfile, target_dir, tmp_dir, is_gui] - - -#================================================================= -# Checks boolean value: yes/no, true/false, 1/0 -#================================================================= -def check_bool(val): - return str(val).strip() in ["yes","true", "1"] - -#================================================================= -# The first algorithm to create the dependencies list by their level -#================================================================= -def get_next_level(list, products): - - import re - result = [] - expr = "(" + list[0].name - for i in range(1, len(list)): - expr = expr + "|"+ list[i].name - - expr = expr + ")$" - #expr=re.compile(expr) - - for product in products: - deps = re.sub(r'\s+', "", product.dependencies) - if re.search(expr, deps): - result.append(product) - - return result - - -def create_levels(prods): - import copy - - products = copy.deepcopy(prods) - - result = {} - import re - #1. find the products with empty lists of dependencies - list = [] - for product in products: - if len(re.sub(r'\s', "", product.dependencies)) == 0 : - list.append(product) - - if len(list) == 0 : - raise RuntimeError, "Products that depend on nothing are not found" - - # remove the first level products from the common list of products - for product in list : - products.remove(product) - - ind = 0; - result[0] = list - - while (len(products)) : - res = get_next_level(list, products) - if len(res) == 0 : - raise RuntimeError, "Empty list of products is found" - - for product in res : - products.remove(product) - - ind = ind +1 - result[ind] = res - list = res - - str = "" - for i in result.keys(): - for product in result[i]: - str = str + product.name + " " - - return str; - -#================================================================= -# The second algorithm -#================================================================= -def get_dependencies_set(prods) : - import copy - import re - - products = copy.deepcopy(prods) - deps = "" - list = [] - - while (len(products)) : - - tmplist = [] - #find the products with empty list of dependencies - for product in products: - product.dependencies = re.sub(r'\s+$', "", product.dependencies) - product.dependencies = re.sub(r'^\s+', "", product.dependencies) - - if len(product.dependencies) == 0 : - tmplist.append(product); - deps = deps + " " + product.name - - list.append(tmplist) - - #remove the products names from other products dependencies - for item in tmplist: - products.remove(item) - - regexpr1 = "((^|,(\s+)?)"+item.name+"$|^"+item.name+"(\s+)?,(\s+)?)" - regexpr2 = ",(\s+)?"+item.name+"(\s+)?,(\s+)?" - - for product in products: - product.dependencies = re.sub(r'\s+$', "", product.dependencies) - product.dependencies = re.sub(r'^\s+', "", product.dependencies) - - product.dependencies = re.sub(regexpr1, "", product.dependencies) - product.dependencies = re.sub(regexpr2, ",", product.dependencies) - - return deps - -#================================================================= -# The third algorithm (same as SALOME_InstallWizard.cxx uses) -#================================================================= -def get_dependencies(prods) : - list = [] - for product in prods: - if check_bool(product.disable): continue - - deps = product.dependencies.split(",") - for dep in deps: - if dep and not dep in list: - list.append( dep ) - - if product and not product in list: - list.append( product.name ) - - return " ".join( list ) - -#============================================================== -# Creates dir, returns the part of path that existed early. -# Access may be defined. -#============================================================== -def create_dir (directory, access = 0777): - import string, os - dirs = string.split(directory, "/") - existing = ""; dir = "" - root = "" - for item in dirs: - if len(item) == 0: continue - dir = dir + "/"+item - if os.path.exists(dir): - existing = dir - else: - os.mkdir(dir, access ) - #root= existing + "/"+item - if dir == existing + "/"+item : - root = dir - #else : root = existing - - return root +__TAG__SOURCES__ = "install sources" +__TAG__BINARIES__ = "install binaries" +__TAG__NATIVE__ = "use native" +__TAG__PREINSTALL__ = "not install" #============================================================== # class Product #============================================================== class Product : - def __init__(self, theName, + def __init__(self, + theName, theVersion = None, theInstall = None, theSupportred = None, - theDisable = None, theDependencies = None, theInstalldiskspace = None, theTemporarydiskspace = None, theScript = None, thePickUpEnvironment = None): - - - self.name = theName - self.version = theVersion - self.install = theInstall - self.supported = theSupportred - self.disable = theDisable - self.dependencies = theDependencies - self.installdiskspace = theInstalldiskspace - self.temporarydiskspace = theTemporarydiskspace - self.script = theScript - self.pickupEnv = thePickUpEnvironment + self.name = strip(theName) + self.version = strip(theVersion) + self.install = strip(theInstall) + self.supported = strip(theSupportred) + self.dependencies = strip(theDependencies) + self.installdiskspace = strip(theInstalldiskspace) + self.temporarydiskspace = strip(theTemporarydiskspace) + self.script = strip(theScript) + self.pickupEnv = strip(thePickUpEnvironment) #=================================================================== # class Config #=================================================================== class Config : - def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''): - self.version = theVersion - self.caption = theCaption - self.copyright = theCopyright - self.license = theLicense - self.os = theOS - + def __init__(self, + theVersion = None, + theCaption = None, + theCopyright = None, + theLicense = None, + theOS = None): + self.version = strip(theVersion) + self.caption = strip(theCaption) + self.copyright = strip(theCopyright) + self.license = strip(theLicense) + self.os = strip(theOS) #=================================================================== # class Path #=================================================================== class Path : - def __init__(self, theTargetdir=".", theTmpdir="."): - self.targetdir = theTargetdir - self.tmpdir = theTmpdir - + def __init__(self, + theTargetdir = None, + theTmpdir = None): + self.targetdir = strip(theTargetdir) + self.tmpdir = strip(theTmpdir) #=================================================================== # class ConfigParser @@ -368,36 +81,38 @@ class ConfigParser(xmllib.XMLParser): self.currentdata.append(data) def start_product(self, attrs): - aProduct = Product(attrs['name'], - attrs['version'], - attrs['install'], - attrs['supported'], - attrs['disable'], - attrs['dependancies'], - attrs['installdiskspace'], - attrs['temporarydiskspace'], - attrs['script']) - - if attrs.has_key( 'pickupenv' ): - aProduct.pickupEnv = attrs['pickupenv'] - + if not attrs.get('name', '').strip(): return + if check_bool(attrs.get('disable', 'false')): return + aProduct = Product(attrs.get('name'), + attrs.get('version', None), + attrs.get('install', None), + attrs.get('supported', None), + attrs.get('dependancies', None), + attrs.get('installdiskspace', None), + attrs.get('temporarydiskspace', None), + attrs.get('script', None), + attrs.get('pickupenv', None)) self.products.append(aProduct) + pass def end_product(self): pass def start_config(self, attrs): - self.config = Config(attrs['version'], - attrs['caption'], - attrs['copyright'], - attrs['license'], - attrs['os']) + self.config = Config(attrs.get('version', None), + attrs.get('caption', None), + attrs.get('copyright', None), + attrs.get('license', None), + attrs.get('os', None)) + pass + def end_config(self): pass def start_path (self, attrs): - self.path = Path(attrs['targetdir'], - attrs['tempdir']) + self.path = Path(attrs.get('targetdir', None), + attrs.get('tempdir', None)) + pass def end_path(self): pass @@ -408,84 +123,303 @@ class ConfigParser(xmllib.XMLParser): return product return None +#============================================================== +# message: prints diagnostic information +#============================================================== +def message(msg): + if msg.strip(): + print ">>>", msg + pass + +#============================================================== +# warning: prints warning +#============================================================== +def warning(msg): + if msg.strip(): + print "" + print msg + print "" + pass + +#============================================================== +# error_exit : prints (optionally) error string, then prints +# help information and quits +#============================================================== +def error_exit(msg = "", print_help = True): + # print error message + if len(msg.strip()): + print "" + print msg + print "" + # print help information + if print_help: + global opt_parser + if opt_parser: + opt_parser.print_help() + print "" + # cleaning + clean_all() + # quit + sys.exit(1); + pass + +#============================================================== +# clean_all : performs system cleaning before exiting +#============================================================== +def clean_all(): + global root_path + remove_dir(root_path) + pass + +#============================================================== +# parse_parameters : parses command line arguments +#============================================================== +def parse_parameters(): + global opt_parser + opt_parser = OptionParser(add_help_option=False) + help_str = "Runs the Installation Wizard in the GUI mode [default].\n" + help_str += "In this case only -f option is taken into account. " + help_str += "Other options are ignored." + opt_parser.add_option("-g", + "--gui", + action="store_true", + dest="gui", + default=True, + help=help_str) + help_str = "Runs the Installation Wizard in the TUI mode." + opt_parser.add_option("-b", + "--batch", + action="store_false", + dest="gui", + help=help_str) + help_str = "The configuration xml file.\n" + help_str += "If this parameter is missing, then the program tries to define the " + help_str += "Linux platform and use the corresponding xml file. For example, " + help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case." + help_str += "If program fails to define target Linux platform or the corresponding " + help_str += "xml file is not provided with the Installation Wizard, then default " + help_str += "config.xml file is used." + opt_parser.add_option("-f", + "--file", + action="store", + dest="xmlfile", + metavar="FILE", + help=help_str) + help_str = "The target directory the products to be installed to.\n" + help_str += "When used this parameter overrides the default target directory " + help_str += "defined in the configuration xml file." + opt_parser.add_option("-d", + "--target", + action="store", + dest="target_dir", + metavar="DIR", + help=help_str) + help_str = "The directory used for temporary files.\n" + help_str += "When used this parameter overrides the default temporary directory " + help_str += "defined in the configuration xml file." + opt_parser.add_option("-t", + "--tmp", + action="store", + dest="tmp_dir", + metavar="DIR", + help=help_str) + help_str = "Prints this help and quits." + opt_parser.add_option("-v", + "--version", + action="store_true", + help=help_str) + help_str = "Prints version information and quits." + opt_parser.add_option("-h", + "--help", + action="store_true", + help=help_str) + (options, args) = opt_parser.parse_args() + if options.help: + # print help info and quit + print "\nSALOME Installation Wizard\n" + opt_parser.print_help() + print "" + sys.exit(0) + if options.version: + # print version info and quit + print "" + cmd = "./bin/SALOME_InstallWizard --version" + os.system(cmd) + print "" + sys.exit(0) + return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui] + +#================================================================= +# strip : removes spaces at the beginning and at eh end of the +# if it is of string type +#================================================================= +def strip(param): + import types + if type(param) == types.StringType: + return param.strip() + return param + +#================================================================= +# check_bool : checks boolean value: yes/no, true/false, 1/0 +#================================================================= +def check_bool(val): + if str(val).lower().strip() in ["yes","true", "1"]: + return True + if str(val).lower().strip() in ["no","false", "0"]: + return False + try: + val = int(val) + return val != 0 + except: + pass + return False + +#================================================================= +# get_dependencies : extract products dependencies +#================================================================= +def get_dependencies(prods): + list = [] + for product in prods: + deps = product.dependencies.split(",") + for dep in deps: + if dep and not dep in list: + list.append( dep ) + + if product and not product in list: + list.append( product.name ) + + return " ".join( list ) + +#============================================================== +# create_dir : creates a directory with (optional) permissions, +# returns the part of path that existed before +# directory creation; exits with error if access +# is denied +#============================================================== +def create_dir(directory, access = 0777): + import string, os + dirs = string.split(directory, "/") + existing = ""; + dir = "" + root = "" + for subdir in dirs: + if len(subdir) == 0: continue + dir = "%s/%s"%(dir, subdir) + if os.path.exists(dir): + existing = dir + else: + try: + os.mkdir(dir, access) + except: + error_exit("Can't create directory: %s.\nAccess is denied."%directory) + if dir == "%s/%s"%(existing, subdir): + root = dir + return root + +#============================================================== +# substituteVars : performes environment variables substistution +# the given string; if varibale is not defined +# it is substituted by the empty string +#============================================================== +def substituteVars(str): + str = os.path.expanduser(str) + str = os.path.expandvars(str) + return str + #================================================================ -# get the path using file name +# get_program_path : gets program's directory path +# (and performs 'cd' command there) #================================================================ -def get_current_path(file_name): - path = "."; where = string.rfind(file_name,'/'); - if (where != -1): - path = (file_name)[: where] - os.chdir(path); - path = os.getcwd() + "/" - return path +def get_program_path(): + path = os.path.dirname(sys.argv[0]) + if path: + os.chdir(path) + return os.getcwd() #================================================================ -# checks dir existing +# check_dir : checks directory existence #================================================================ def check_dir(dir): - if (os.path.islink(dir)) : - native_dir = os.readlink(dir) - if not os.path.exists(native_dir) : - print "Invalid link " + dir + ". The directory " + native_dir + " a link points to does not exist." - return 0 # problem - else : + if (os.path.islink(dir)): + realpath = os.path.realpath(dir) + if not os.path.exists(realpath): + msg = "Invalid link %s.\nThe directory %s a link points to does not exist."%(dir,realpath) + error_exit(msg, False) + else: if not os.path.exists(dir): - print "Directory " + dir + " does not exist" - return 0 - return 1 + msg = "Directory %s does not exist."%dir + error_exit(msg, False) + pass #=============================================================== -# Checks the disk space. Exit from interpreter if there is no -# enough disk space. +# check_disk_space : checks the disk space; +# quits if there is no enough disk space #=============================================================== -def check_disk_space(products, script_dir, target_dir, tmp_dir): - import re, string, os +def check_disk_space(products, scripts_dir, target_dir, tmp_dir): install_space = 0 temporary_space = 0 - for product in products : - product.install = re.sub(r'^\s+', "", product.install) - product.install = re.sub(r'\s+$', "", product.install) - - if check_bool(product.disable) or product.install == "use native" or product.install == "not install": + for product in products: + if product.install in [__TAG__NATIVE__, __TAG__PREINSTALL__]: continue - spaces = string.split( product.installdiskspace,',') + spaces = string.split(product.installdiskspace, ',') prod_space = spaces[0] - if (len(spaces) == 2 ) and (product.install == "install binaries") : + if (len(spaces) > 1 ) and (product.install == __TAG__SOURCES__): prod_space = spaces[1] install_space = install_space + string.atoi(prod_space) - temporary_space = temporary_space + string.atoi(product.temporarydiskspace) - res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space)) + if product.install == __TAG__SOURCES__: + temporary_space = max(temporary_space, string.atoi(product.temporarydiskspace)) + + res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space)) if res: - print "There is no enough space to install the products." - return 0 + msg = "There is no enough space to install the products." + error_exit(msg, False) - res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space)) + res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", tmp_dir, temporary_space)) if res: - print "There is no enough space for tmp directory." - return 0 - - return 1 + msg = "There is no enough space for temporary directory." + error_exit(msg, False) + pass #=============================================================== -# Removes temporary directory +# remove_dir : removes temporary directory #=============================================================== -def remove_dir( rem_path = "" ): - if len( rem_path ) and os.path.exists( rem_path ): - os.system( "rm -rf " + rem_path ) +def remove_dir(path): + if path and os.path.exists(path): + os.system("rm -rf " + path) pass - + +#============================================================== +# has_binaries : returns True if some product is installed from +# binaries +#=============================================================== +def has_binaries(products): + for product in products: + if product.install == __TAG__BINARIES__: + return True + return False + +#============================================================== +# has_sources : returns True if some product is installed from +# sources +#=============================================================== +def has_sources(products): + for product in products: + if product.install == __TAG__SOURCES__: + return True + return False + #================================================================ # main #================================================================ if __name__ == "__main__": - - cur_dir = get_current_path(sys.argv[0]) - - [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters(sys.argv) + # get program dir + cur_dir = get_program_path() + # parse command line + [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters() - # define xml file ----------------- - if (xml_file is None) : + # define xml file to be used + if (xml_file is None): plt_name = "" plt_ver = "" xml_file_name = "config.xml" @@ -504,45 +438,42 @@ if __name__ == "__main__": plt_name = "Debian" plt_ver = open("/etc/debian_version").readline().strip() _xml_file_name = "config_%s_%s.xml"%(plt_name, plt_ver) - if plt_name and plt_ver and os.path.exists(cur_dir + _xml_file_name): + if plt_name and plt_ver and os.path.exists("%s/%s"%(cur_dir, _xml_file_name)): xml_file_name = _xml_file_name else: - print "" - print "Not supported Linux platform!" - print "Trying to use default configuration!" - print "" + msg = "Not supported Linux platform!\n" + msg += "Trying to use default configuration file!" + warning(msg) - xml_file = cur_dir + xml_file_name + xml_file = "%s/%s"%(cur_dir, xml_file_name) if not xml_file or not os.path.exists(xml_file): - msg = "Configuration file %s is not found!"%xml_file - msg += "\nTry to run with -f option." + msg = "Configuration file %s is not found!"%xml_file error_exit(msg) if not os.access(xml_file, os.R_OK): - print "There is no read access for %s file!"%xml_file - sys.exit(1) + msg = "There is no read access for %s file!"%xml_file + error_exit(msg) #---- GUI ---------------- + if is_gui : env = os.environ if not env.has_key("PATH") : env["PATH"] = "" if not env.has_key("LD_LIBRARY_PATH") : - env["LD_LIBRARY_PATH"]= "" + env["LD_LIBRARY_PATH"] = "" - env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"] - env["PATH"] = ".:"+ env["PATH"] + env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"] + env["PATH"] = ".:" + env["PATH"] - sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&")) - - + cmd = "./bin/SALOME_InstallWizard %s &"%xml_file + sys.exit(os.system(cmd)) #----- TUI --------------------- - #print xml_file, target_dir, tmp_dir, is_gui - - message("Parsing xml config file: " + xml_file) + # parse XML file ----------- + message("Parsing XML configuration file: %s"%xml_file) filehandle = open(xml_file) data = filehandle.read() filehandle.close() @@ -550,103 +481,114 @@ if __name__ == "__main__": parser.feed(data) parser.close() - # definitions : - # map - what_to_do = { "install sources" : "install_source", - "install binaries" : "install_binary", - "use native" : "try_native", - "not install" : "try_preinstalled"} - # define tmp dir ----------- - if tmp_dir is None: - tmp_dir = parser.path.tmpdir - if tmp_dir is None or tmp_dir == "": - tmp_dir = "/tmp" - import random - tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000)) - root_path = "" - if not os.path.exists(tmp_dir): - message("Creating temporary directory: " + tmp_dir); root_path = create_dir(tmp_dir, 0755) ; - if not os.path.exists(tmp_dir): - error_exit("Invalid temporary directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n") - - if not os.access(tmp_dir, os.W_OK) : - str = "There is no write permissions for directory " + tmp_dir + ". Use -tmp key to set temporary directory or correct xml file" - error_exit(str) - - # define target dir -------- + # actions map + what_to_do = { __TAG__SOURCES__ : "install_source", + __TAG__BINARIES__ : "install_binary", + __TAG__NATIVE__ : "try_native", + __TAG__PREINSTALL__ : "try_preinstalled"} + # source directory map + bin_dir = "" + if parser.config.os: + bin_dir += "/%s"%parser.config.os + subdir = { __TAG__SOURCES__ : "SOURCES", + __TAG__BINARIES__ : "BINARIES" + bin_dir, + __TAG__NATIVE__ : "", + __TAG__PREINSTALL__ : ""} + + # check scripts directory ----------- + scripts_dir = "%s/%s"%(cur_dir, "config_files") + check_dir(scripts_dir) + + # check products archives directories ----------- + has_bin = has_binaries(parser.products) + has_src = has_sources(parser.products) + source_dir = "%s/%s"%(cur_dir, "Products") + + if has_src or has_bin: + check_dir(source_dir) + + if has_src: + check_dir("%s/%s"%(source_dir,subdir[__TAG__SOURCES__])) + + if has_bin: + check_dir("%s/%s"%(source_dir,subdir[__TAG__BINARIES__])) + + # check/create target dir ----------- if target_dir is None: target_dir = parser.path.targetdir + target_dir = substituteVars(target_dir) + + message("Creating target directory: " + target_dir) + create_dir(target_dir, 0755) if not os.path.exists(target_dir): - message("Creating target directory: " + target_dir); create_dir(target_dir, 0755) - if not os.path.exists(target_dir): - error_exit("Invalid target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n") + error_exit("Invalid target directory: " + target_dir) if not os.access(target_dir, os.W_OK) : - str = "There is no write permissions for directory " + target_dir + ". Use -t key to set target directory or correct xml file." - error_exit(str) - - # define products dir ------------ - source_dir = cur_dir + "Products" ; - if not check_dir(source_dir): - remove_dir(root_path) - sys.exit(1) - - subdir = {"install sources" : "SOURCES", - "install binaries" : "BINARIES/"+parser.config.os, - "use native" : "", - "not install" : ""} - - - # define scripts dir ------------ - scripts_dir = cur_dir + "config_files/" - if not check_dir(scripts_dir): - remove_dir(root_path) - sys.exit(1) - os.chdir(scripts_dir) + error_exit("There is no write permissions for the directory: " + target_dir) + + # check/create temporary dir ----------- + if tmp_dir is None: + tmp_dir = parser.path.tmpdir + if not tmp_dir: + tmp_dir = "/tmp" + tmp_dir = substituteVars(tmp_dir) + import random + tmp_dir = "%s/INSTALLWORK%d"%(tmp_dir, random.randint(10000,100000)) - #list_of_dep = create_levels(parser.products) - #list_of_dep = get_dependencies_set(parser.products) - list_of_dep = get_dependencies(parser.products) + message("Creating temporary directory: " + tmp_dir) + root_path = create_dir(tmp_dir, 0755) + + if not os.path.exists(tmp_dir): + error_exit("Invalid temporary directory: " + tmp_dir) + if not os.access(tmp_dir, os.W_OK) : + error_exit("There is no write permissions for the directory: " + tmp_dir) + + # check available disk space message("Checking available disk space") - if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) : - - message("Starting...") - # install products - for product in parser.products : + check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) - if check_bool(product.disable): continue + # change current directory + os.chdir(scripts_dir) - message("Processing " + product.name + "...") - cmd = scripts_dir + product.script + " " + \ - what_to_do[product.install]+ " " + \ - tmp_dir + " " + \ - source_dir + "/" + subdir[product.install] + " " + \ - target_dir + " " + \ - '"' + list_of_dep + '"' + " " + \ - product.name + # get dependencies list + list_of_dep = get_dependencies(parser.products) + # starting + message("Starting ...") + + # install products + for product in parser.products: + message("... processing %s ..."%product.name) + cmd = '%s/%s %s %s %s/%s %s "%s" %s'%(scripts_dir, + product.script, + what_to_do[product.install], + tmp_dir, + source_dir, + subdir[product.install], + target_dir, + list_of_dep, + product.name) + res = os.system(cmd) + + # pickup environment + message("Creating environment files") + for product in parser.products : + if check_bool(product.pickupEnv): + cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s'%(scripts_dir, + product.script, + tmp_dir, + source_dir, + subdir[product.install], + target_dir, + list_of_dep, + product.name) res = os.system(cmd) - #if res : break; # try_preinstalled can return 1 - - # pickup environment - message("Creating environment files") - for product in parser.products : - - if check_bool(product.disable): continue - - if check_bool(product.pickupEnv): - cmd = scripts_dir + product.script + " " + \ - "pickup_env " + \ - tmp_dir + " " + \ - source_dir + "/" + subdir[product.install] + " " + \ - target_dir + " " + \ - '"' + list_of_dep + '"' + " " + \ - product.name - - res = os.system(cmd) + # clean temporary directory message("Cleaning temporary directory") - remove_dir(root_path) + clean_all() + # finishing message("Finished!") + pass diff --git a/src/SALOME_InstallWizard.cxx b/src/SALOME_InstallWizard.cxx index f85b34b..3968afc 100644 --- a/src/SALOME_InstallWizard.cxx +++ b/src/SALOME_InstallWizard.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef WNT #include @@ -56,17 +57,17 @@ QString tmpDirName() { return QString( "/INSTALLWORK" ) + QString::number( getp // ================================================================ /*! - * QProcessThread + * ProcessThread * Class for executing systen commands */ // ================================================================ static QMutex myMutex(false); static QWaitCondition myWC; -class QProcessThread: public QThread +class ProcessThread: public QThread { typedef QPtrList ItemList; public: - QProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); } + ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); } void addCommand( QCheckListItem* item, const QString& cmd ) { myItems.append( item ); @@ -78,9 +79,9 @@ public: virtual void run() { while ( hasCommands() ) { - ___MESSAGE___( "QProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() ); + ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() ); int result = system( myCommands[ 0 ] ) / 256; // return code is * 256 - ___MESSAGE___( "QProcessThread::run - Result : " << result ); + ___MESSAGE___( "ProcessThread::run - Result : " << result ); QCheckListItem* item = myItems.first(); myCommands.pop_front(); myItems.removeFirst(); @@ -124,8 +125,11 @@ class WarnDialog: public QDialog } void accept() { return; } void reject() { return; } - void closeEvent( QCloseEvent* e) { if ( !myCloseFlag ) return; QDialog::closeEvent( e ); } - + void closeEvent( QCloseEvent* e ) + { if ( !myCloseFlag ) return; + e->accept(); + QDialog::closeEvent( e ); + } ~WarnDialog() { myDlg = 0; } public: static void showWarnDlg( QWidget* parent, bool show ) { @@ -151,6 +155,48 @@ public: }; WarnDialog* WarnDialog::myDlg = 0; +// ================================================================ +/*! + * InstallInfo + * Installation progress info window class + */ +// ================================================================ +class InstallInfo : public QTextEdit +{ +public: + InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {} + void setFinished( const bool f ) { finished = f; } +protected: + QPopupMenu* createPopupMenu( const QPoint& ) + { + int para1, col1, para2, col2; + getSelection(¶1, &col1, ¶2, &col2); + bool allSelected = hasSelectedText() && + para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2); + QPopupMenu* popup = new QPopupMenu( this ); + int id = popup->insertItem( tr( "&Copy" ) ); + popup->setItemEnabled( id, hasSelectedText() ); + popup->connectItem ( id, this, SLOT( copy() ) ); + id = popup->insertItem( tr( "Select &All" ) ); + popup->setItemEnabled( id, (bool)text().length() && !allSelected ); + popup->connectItem ( id, this, SLOT( selectAll() ) ); + if ( finished ) { + QWidget* p = parentWidget(); + while ( p && !p->inherits( "SALOME_InstallWizard" ) ) + p = p->parentWidget(); + if ( p && p->inherits( "SALOME_InstallWizard" ) ) { + popup->insertSeparator(); + id = popup->insertItem( tr( "&Save Log" ) ); + popup->setItemEnabled( id, (bool)text().length() ); + popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) ); + } + } + return popup; + } +private: + bool finished; +}; + // ================================================================ /*! * DefineDependeces [ static ] @@ -368,7 +414,7 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName) connect(shellProcess, SIGNAL( wroteToStdin() ), this, SLOT( wroteToStdin() ) ); // create validation thread - myThread = new QProcessThread( this ); + myThread = new ProcessThread( this ); } // ================================================================ /*! @@ -687,7 +733,7 @@ void SALOME_InstallWizard::setupProgressPage() QGridLayout* layout = new QGridLayout( widget ); layout->setMargin( 0 ); layout->setSpacing( 6 ); // installation progress view box - installInfo = new QTextEdit( widget ); + installInfo = new InstallInfo( widget ); installInfo->setReadOnly( true ); installInfo->setTextFormat( RichText ); installInfo->setUndoRedoEnabled ( false ); @@ -747,7 +793,7 @@ void SALOME_InstallWizard::setupReadmePage() readme = new QTextEdit( readmePage ); readme->setReadOnly( true ); readme->setTextFormat( PlainText ); - readme->setFont( QFont( "Fixed", 10 ) ); + readme->setFont( QFont( "Fixed", 12 ) ); readme->setUndoRedoEnabled ( false ); QWhatsThis::add( readme, tr( "Displays README information" ) ); QToolTip::add ( readme, tr( "Displays README information" ) ); @@ -797,16 +843,16 @@ void SALOME_InstallWizard::showChoiceInfo() text += "
"; } if ( !myOS.isEmpty() ) { - text += tr( "Target platform" ) + ": " + myOS + "
"; + text += tr( "Reference Linux platform" ) + ": " + myOS + "
"; text += "
"; } - text += tr( "Products to be used" ) + ":
    "; + text += tr( "Native products to be used" ) + ":
      "; QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() ); while( item ) { if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { if ( productsView->isNative( item ) ) { - text += "
    • " + item->text() + " " + tr( "as native" ) + "
      "; + text += "
    • " + item->text() + "
      "; nbProd++; } } @@ -824,11 +870,11 @@ void SALOME_InstallWizard::showChoiceInfo() if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { if ( productsView->isBinaries( item ) ) { - text += "
    • " + item->text() + " " + tr( "as binaries" ) + "
      "; + text += "
    • " + item->text() + " " + item->text(1) + " " + tr( "as binaries" ) + "
      "; nbProd++; } else if ( productsView->isSources( item ) ) { - text+= "
    • " + item->text() + " " + tr( "as sources" ) + "
      "; + text+= "
    • " + item->text() + " " + item->text(1) + " " + tr( "as sources" ) + "
      "; nbProd++; } } @@ -850,7 +896,7 @@ void SALOME_InstallWizard::showChoiceInfo() // VSR: Temporary folder is used always now and it is not necessary to disable it --> // if ( tempSize > 0 ) // VSR: <---------------------------------------------------------------------------- - text += tr( "Temp directory:" ) + " " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "
      "; + text += tr( "Temporary directory:" ) + " " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "
      "; text += "
      "; choices->setText( text ); } @@ -907,7 +953,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) QMessageBox::warning( this, tr( "Warning" ), tr( "The directory %1 doesn't exist.\n" - "Do you want to create directory?" ).arg( fi.absFilePath() ), + "Create directory?" ).arg( fi.absFilePath() ), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton ) == QMessageBox::Yes; @@ -926,7 +972,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( !fi.isDir() ) { QMessageBox::warning( this, tr( "Warning" ), - tr( "The directory %1 is not a directory.\n" + tr( "%1 is not a directory.\n" "Please, enter valid target directory path" ).arg( fi.absFilePath() ), QMessageBox::Ok, QMessageBox::NoButton, @@ -973,7 +1019,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( system( script ) ) { QMessageBox::critical( this, tr( "Out of space" ), - tr( "There is not available disk space for installing of selected products" ), + tr( "There is no available disk space for installing of selected products" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -984,7 +1030,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( moreMode ) { QMessageBox::warning( this, tr( "Warning" ), - tr( "Please, enter valid temp directory path" ), + tr( "Please, enter valid temporary directory path" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1015,7 +1061,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( system( tscript ) ) { QMessageBox::critical( this, tr( "Out of space" ), - tr( "There is not available disk space for the temporary files" ), + tr( "There is no available disk space for the temporary files" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1028,11 +1074,12 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) while( item ) { if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { - if ( !productsView->isNone( item ) ) { + // VSR : 29/01/05 : Check installation script even if product is not being installed + // if ( !productsView->isNone( item ) ) { if ( item->text(2).isEmpty() || item->text(2).isNull() ) { QMessageBox::warning( this, tr( "Error" ), - tr( "You don't have a defined script for %1").arg(item->text(0)), + tr( "The installation script for %1 is not defined.").arg(item->text(0)), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1045,10 +1092,10 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) return false; } else { QFileInfo fi( QString("./config_files/") + item->text(2) ); - if ( !fi.exists() ) { + if ( !fi.exists() || !fi.isExecutable() ) { QMessageBox::warning( this, tr( "Error" ), - tr( "%1 required for %2 doesn't exist.").arg("./config_files/" + item->text(2)).arg(item->text(0)), + tr( "The script %1 required for %2 doesn't exist or doesn't have execute permissions.").arg("./config_files/" + item->text(2)).arg(item->text(0)), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1061,7 +1108,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) return false; } } - } + // } // collect native products if ( productsView->isNative( item ) ) { if ( natives.find( item->text(0) ) == natives.end() ) @@ -1077,9 +1124,9 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) } else { QMessageBox::warning( this, - tr( "Warning" ), + tr( "Error" ), tr( "%1 is required for %2 %3 installation.\n" - "Please, add this product in config.xml file.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)), + "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1109,7 +1156,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) QMessageBox::warning( this, tr( "Warning" ), tr( "%The product %1 %2 required for installation.\n" - "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)), + "This product is missing in the configuration file %4.").arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1366,6 +1413,7 @@ void SALOME_InstallWizard::launchScript() passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); + installInfo->setFinished( true ); if ( isMinimized() ) showNormal(); raise(); @@ -1410,15 +1458,15 @@ void SALOME_InstallWizard::onLaunchSalome() QCheckListItem* item = findItem( "KERNEL-Bin" ); if ( item ) { QFileInfo fi( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ); - QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ); + QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.sh" ); if ( fienv.exists() ) { if ( fi.exists() ) { QString script; script += "cd " + targetFolder->text() + "/KERNEL_" + item->text(1) + "; "; - script += "source salome.csh; "; + script += "source salome.sh; "; script += "cd bin/salome; "; script += "runSalome > /dev/null"; - script = "(csh -c '" + script + "')"; + script = "(bash -c '" + script + "')"; ___MESSAGE___( "script: " << script.latin1() ); if ( !system( script.latin1() ) ) return; @@ -1575,6 +1623,7 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle) // progress page progressView->clear(); installInfo->clear(); + installInfo->setFinished( false ); passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); @@ -1667,6 +1716,17 @@ void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ ) // ================================================================ void SALOME_InstallWizard::onStart() { + if ( nextButton()->text() == tr( "&Stop" ) ) { + shellProcess->kill(); + while( shellProcess->isRunning() ); + return; + } + progressView->clear(); + installInfo->clear(); + installInfo->setFinished( false ); + passedParams->clear(); + passedParams->setEnabled( false ); + QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); // clear list of products to install ... toInstall.clear(); // ... and fill it for new process @@ -1682,7 +1742,10 @@ void SALOME_InstallWizard::onStart() if ( !toInstall.isEmpty() ) { clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory // disable button - setNextEnabled( false ); + //setNextEnabled( false ); + nextButton()->setText( tr( "&Stop" ) ); + QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) ); + QToolTip::add ( nextButton(), tr( "Aborts installation process" ) ); // disable button setBackEnabled( false ); // enable script parameters line edit @@ -1742,14 +1805,22 @@ void SALOME_InstallWizard::productInstalled( ) passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); + installInfo->setFinished( true ); // enable button setNextEnabled( true ); - nextButton()->setText( tr( "&Next >" ) ); - QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); - QToolTip::add ( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + nextButton()->setText( tr( "&Start" ) ); + QWhatsThis::add( nextButton(), tr( "Starts installation process" ) ); + QToolTip::add ( nextButton(), tr( "Starts installation process" ) ); + // reconnect Next button - to use it as Start button disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); - connect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); + connect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); + //nextButton()->setText( tr( "&Next >" ) ); + //QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + //QToolTip::add ( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); + //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); + //connect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); // enable button setBackEnabled( true ); } @@ -2005,6 +2076,41 @@ void SALOME_InstallWizard::polish() InstallWizard::polish(); } // ================================================================ +/*! + * SALOME_InstallWizard::saveLog + * Save installation log to file + */ +// ================================================================ +void SALOME_InstallWizard::saveLog() +{ + QString txt = installInfo->text(); + if ( txt.length() <= 0 ) + return; + QDateTime dt = QDateTime::currentDateTime(); + QString fileName = dt.toString("ddMMyy-hhmm"); + fileName.prepend("install-"); fileName.append(".html"); + fileName = QFileDialog::getSaveFileName( fileName, + QString( "HTML files (*.htm *.html)" ), + this, 0, + tr( "Save Log file" ) ); + if ( !fileName.isEmpty() ) { + QFile f( fileName ); + if ( f.open( IO_WriteOnly ) ) { + QTextStream stream( &f ); + stream << txt; + f.close(); + } + else { + QMessageBox::critical( this, + tr( "Error" ), + tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ), + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton ); + } + } +} +// ================================================================ /*! * SALOME_InstallWizard::updateCaption * Updates caption according to the current page number diff --git a/src/SALOME_InstallWizard.hxx b/src/SALOME_InstallWizard.hxx index dd9e4d7..37800cd 100644 --- a/src/SALOME_InstallWizard.hxx +++ b/src/SALOME_InstallWizard.hxx @@ -97,10 +97,11 @@ class QProcess; class QCheckBox; class QSplitter; class QMyCheckBox; -class QProcessThread; +class ProcessThread; class ProductsView; class ProgressView; class HelpWindow; +class InstallInfo; typedef QMap MapProducts; @@ -153,6 +154,9 @@ class SALOME_InstallWizard: public InstallWizard QString getOS() { return myOS; } // get InstallWizard's name QString getIWName() { return myIWName; } + + // save install log to file + void saveLog(); protected: // updates caption according to the current page number @@ -235,63 +239,63 @@ class SALOME_InstallWizard: public InstallWizard void readFromStderr(); private: - QString myIWName; // Installation Wizard's name - QString myVersion; // version info - QString myCaption; // application name - QString myCopyright; // copyright info - QString myLicense; // license info - QString myOS; // operation system + QString myIWName; // Installation Wizard's name + QString myVersion; // version info + QString myCaption; // application name + QString myCopyright; // copyright info + QString myLicense; // license info + QString myOS; // operation system - HelpWindow* helpWindow; // help window - QProcess* shellProcess; // shell process (install script) - MapProducts productsMap; // products info (name, dependancies, disk space ) - QStringList toInstall; // list of products being installed - QString xmlFileName; // xml file - bool moreMode; // advanced mode flag - QWidget* previousPage; // previous page - QString tmpCreated; // created temporary directory - bool exitConfirmed; // flag: "Exit confirmed" + HelpWindow* helpWindow; // help window + QProcess* shellProcess; // shell process (install script) + MapProducts productsMap; // products info (name, dependancies, disk space ) + QStringList toInstall; // list of products being installed + QString xmlFileName; // xml file + bool moreMode; // advanced mode flag + QWidget* previousPage; // previous page + QString tmpCreated; // created temporary directory + bool exitConfirmed; // flag: "Exit confirmed" // Widgets // --> introduction page - QWidget* introPage; // page itself - QLabel* logoLab; // logo pixmap - QLabel* versionLab; // vesrsion info - QLabel* copyrightLab; // copyright info - QLabel* licenseLab; // license info - QLabel* info; // program info + QWidget* introPage; // page itself + QLabel* logoLab; // logo pixmap + QLabel* versionLab; // vesrsion info + QLabel* copyrightLab; // copyright info + QLabel* licenseLab; // license info + QLabel* info; // program info // --> products page - QWidget* productsPage; // page itself - QLineEdit* targetFolder; // target directory for installing of products - QPushButton* targetBtn; // browse target directory button - QLineEdit* tempFolder; // directory for the temporary files: /tmp by default - QPushButton* tempBtn; // browse temp directory button - QLabel* requiredSize; // label - QLabel* requiredTemp; // label - QPushButton* moreBtn; // button - QWidget* moreBox; // container for the mode widgets - ProductsView* productsView; // products list view - QTextBrowser* productsInfo; // products info box - QCheckBox* prerequisites; // checkbox - QMyCheckBox* selectSrcBtn; // check box - QMyCheckBox* selectBinBtn; // check box - QPushButton* unselectBtn; // button + QWidget* productsPage; // page itself + QLineEdit* targetFolder; // target directory for installing of products + QPushButton* targetBtn; // browse target directory button + QLineEdit* tempFolder; // directory for the temporary files: /tmp by default + QPushButton* tempBtn; // browse temp directory button + QLabel* requiredSize; // label + QLabel* requiredTemp; // label + QPushButton* moreBtn; // button + QWidget* moreBox; // container for the mode widgets + ProductsView* productsView; // products list view + QTextBrowser* productsInfo; // products info box + QCheckBox* prerequisites; // checkbox + QMyCheckBox* selectSrcBtn; // check box + QMyCheckBox* selectBinBtn; // check box + QPushButton* unselectBtn; // button // --> prestart page - QWidget* prestartPage; // page itself - QTextEdit* choices; // choice text view + QWidget* prestartPage; // page itself + QTextEdit* choices; // choice text view // --> progress page - QWidget* progressPage; // page itself - QSplitter* splitter; // splitter window - QTextEdit* installInfo; // information about running installation scripts - QLabel* parametersLab; // answer field's label - QLineEdit* passedParams; // user can pass data to running script - QTextEdit* installProgress;// contains information about progress of installing selected products - ProgressView* progressView; // displays information about progress of installing selected products + QWidget* progressPage; // page itself + QSplitter* splitter; // splitter window + InstallInfo* installInfo; // information about running installation scripts + QLabel* parametersLab; // answer field's label + QLineEdit* passedParams; // user can pass data to running script + QTextEdit* installProgress;// contains information about progress of installing selected products + ProgressView* progressView; // displays information about progress of installing selected products // --> readme page - QWidget* readmePage; // page itself - QTextEdit* readme; // Readme information window - QPushButton* runSalomeBtn; // buttnon + QWidget* readmePage; // page itself + QTextEdit* readme; // Readme information window + QPushButton* runSalomeBtn; // buttnon - QProcessThread* myThread; // validation thread + ProcessThread* myThread; // validation thread }; #endif diff --git a/src/globals.h b/src/globals.h index cb6868b..1a7c369 100644 --- a/src/globals.h +++ b/src/globals.h @@ -13,10 +13,11 @@ // ======================== #include +#include #ifdef QT_DEBUG -#define ___MESSAGE___( x ) cout << x << endl; +#define ___MESSAGE___( x ) std::cout << x << std::endl; #else diff --git a/src/main.cxx b/src/main.cxx index 63cfd19..e828213 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -12,13 +12,21 @@ #include #include +#define __IW_VERSION__ 0x010000 + // ================================================================ /*! * MessageOutput * Qt's messages handler funcion */ // ================================================================ -void MessageOutput( QtMsgType type, const char *msg ) +void MessageOutput( QtMsgType type, +#ifdef QT_DEBUG + const char* msg +#else + const char* +#endif + ) { switch ( type ) { case QtDebugMsg: @@ -42,10 +50,30 @@ void MessageOutput( QtMsgType type, const char *msg ) int main( int argc, char **argv ) { qInstallMsgHandler( MessageOutput ); + + QString xmlFileName; + for( int i = 1; i < argc; i++ ) { + QString a = QString( argv[i] ); + if ( a == "--version" || a == "-v" ) { + printf("SALOME Installation Wizard version %d.%d.%d ", + ( __IW_VERSION__ >> 16 ) & 0xFF, + ( __IW_VERSION__ >> 8 ) & 0xFF, + ( __IW_VERSION__ ) & 0xFF ); + printf("(Qt version %d.%d.%d)\n", + ( QT_VERSION >> 16 ) & 0xFF, + ( QT_VERSION >> 8 ) & 0xFF, + ( QT_VERSION ) & 0xFF ); + return 0; + } + if ( xmlFileName.isEmpty() ) + xmlFileName = a; + } + if ( xmlFileName.isEmpty() ) + xmlFileName = "config.xml"; + QApplication a( argc, argv ); - a.setFont( QFont("Helvetica", 9 ) ); - QString xmlFileName( argc == 2 ? argv[1] : "config.xml" ); - + a.setFont( QFont( "Sans", 12 ) ); + int result = -1; QFile xmlfile(xmlFileName); if ( xmlfile.exists() ) {