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 <xml-file>] [-t <target-dir>] [-tmp <tmp-dir>]\n"
- str = str + "\n"
- str = str + " -g Runs the Installation Wizard in the GUI mode.\n"
- str = str + " In this case only <xmlfile> 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 <xml-file> 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 <target-dir> 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 <tmp-dir> 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
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
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
+# <param> 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"
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 <xmlfile> 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()
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
#include <qwaitcondition.h>
#include <qmutex.h>
#include <qstringlist.h>
+#include <qpopupmenu.h>
#ifdef WNT
#include <iostream.h>
// ================================================================
/*!
- * QProcessThread
+ * ProcessThread
* Class for executing systen commands
*/
// ================================================================
static QMutex myMutex(false);
static QWaitCondition myWC;
-class QProcessThread: public QThread
+class ProcessThread: public QThread
{
typedef QPtrList<QCheckListItem> 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 );
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 <errno> * 256
- ___MESSAGE___( "QProcessThread::run - Result : " << result );
+ ___MESSAGE___( "ProcessThread::run - Result : " << result );
QCheckListItem* item = myItems.first();
myCommands.pop_front();
myItems.removeFirst();
}
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 ) {
};
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 ]
connect(shellProcess, SIGNAL( wroteToStdin() ), this, SLOT( wroteToStdin() ) );
// create validation thread
- myThread = new QProcessThread( this );
+ myThread = new ProcessThread( this );
}
// ================================================================
/*!
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 );
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" ) );
text += "<br>";
}
if ( !myOS.isEmpty() ) {
- text += tr( "Target platform" ) + ": <b>" + myOS + "</b><br>";
+ text += tr( "Reference Linux platform" ) + ": <b>" + myOS + "</b><br>";
text += "<br>";
}
- text += tr( "Products to be used" ) + ":<ul>";
+ text += tr( "Native products to be used" ) + ":<ul>";
QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
while( item ) {
if ( productsMap.contains( item ) ) {
if ( item->childCount() > 0 ) {
if ( productsView->isNative( item ) ) {
- text += "<li><b>" + item->text() + "</b> " + tr( "as native" ) + "<br>";
+ text += "<li><b>" + item->text() + "</b><br>";
nbProd++;
}
}
if ( productsMap.contains( item ) ) {
if ( item->childCount() > 0 ) {
if ( productsView->isBinaries( item ) ) {
- text += "<li><b>" + item->text() + "</b> " + tr( "as binaries" ) + "<br>";
+ text += "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as binaries" ) + "<br>";
nbProd++;
}
else if ( productsView->isSources( item ) ) {
- text+= "<li><b>" + item->text() + "</b> " + tr( "as sources" ) + "<br>";
+ text+= "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as sources" ) + "<br>";
nbProd++;
}
}
// VSR: Temporary folder is used always now and it is not necessary to disable it -->
// if ( tempSize > 0 )
// VSR: <----------------------------------------------------------------------------
- text += tr( "Temp directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
+ text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
text += "<br>";
choices->setText( text );
}
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;
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,
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 );
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 );
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 );
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 );
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 );
return false;
}
}
- }
+ // }
// collect native products
if ( productsView->isNative( item ) ) {
if ( natives.find( item->text(0) ) == natives.end() )
}
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 );
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 );
passedParams->clear();
passedParams->setEnabled( false );
QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
+ installInfo->setFinished( true );
if ( isMinimized() )
showNormal();
raise();
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;
// progress page
progressView->clear();
installInfo->clear();
+ installInfo->setFinished( false );
passedParams->clear();
passedParams->setEnabled( false );
QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
// ================================================================
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
if ( !toInstall.isEmpty() ) {
clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
// disable <Next> button
- setNextEnabled( false );
+ //setNextEnabled( false );
+ nextButton()->setText( tr( "&Stop" ) );
+ QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) );
+ QToolTip::add ( nextButton(), tr( "Aborts installation process" ) );
// disable <Back> button
setBackEnabled( false );
// enable script parameters line edit
passedParams->clear();
passedParams->setEnabled( false );
QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
+ installInfo->setFinished( true );
// enable <Next> 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 <Back> button
setBackEnabled( true );
}
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