From 767ef9fbc7d33ea0100d7fbae13089f4efc67c43 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@cd1c1023-2f26-0410-ae45-c471fc1f0318> Date: Sun, 11 Nov 2007 13:40:39 +0000 Subject: [PATCH] - fixed a various range of bugs - implemented external triggers support - implemented xterm title printouts git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@654 cd1c1023-2f26-0410-ae45-c471fc1f0318 --- TODO | 4 +-- client/equo | 1 + client/equoTools.py | 32 ++++++++++++++++------- client/triggerTools.py | 53 ++++++++++++++++++++++++++++++++++++-- libraries/databaseTools.py | 49 ++++++++++++++++++++++++++--------- libraries/entropyTools.py | 1 + libraries/outputTools.py | 16 +++++------- server/trigger | 34 ++++++++++++------------ 8 files changed, 136 insertions(+), 54 deletions(-) diff --git a/TODO b/TODO index 08d055166..951e337cd 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,5 @@ TODO list: CLIENT: - - add external triggerable hooks support - - include more triggers - use depgraph generation function to generate dependencies - installPackages should pull conflicts depends too - find a way to better handle real smartapps deps @@ -12,6 +10,6 @@ Project Status: - reagent: complete. Stabilization mode. - activator: complete. Stabilization mode. ============ -- equo (client): 92% +- equo (client): 94% - EAPI1+ info: http://www.pkgcore.org/trac/pkgcore/doc/doc/extended-atom-syntax.rst diff --git a/client/equo b/client/equo index cb40f243d..71a7fd84c 100644 --- a/client/equo +++ b/client/equo @@ -141,6 +141,7 @@ elif (options[0] == "--info"): sys.exit(0) try: + rc = 0 # sync mirrors tool if (options[0] == "update") or (options[0] == "repoinfo") or (options[0] == "status"): if options[0] == "update": diff --git a/client/equoTools.py b/client/equoTools.py index 4f54419ea..40aff444f 100644 --- a/client/equoTools.py +++ b/client/equoTools.py @@ -2069,7 +2069,10 @@ def worldUpdate(ask = False, pretend = False, verbose = False, onlyfetch = False mdbconn = openRepositoryDatabase(matchresults[1]) matchatom = mdbconn.retrieveAtom(matchresults[0]) mdbconn.closeDB() - updateList.add((matchatom,matchresults)) + # compare versions + unsatisfied, satisfied = filterSatisfiedDependencies((matchatom,)) + if unsatisfied: + updateList.add((matchatom,matchresults)) else: fineList.add(idpackage) @@ -2110,7 +2113,7 @@ def worldUpdate(ask = False, pretend = False, verbose = False, onlyfetch = False time.sleep(5) # run removePackages with --nodeps - removePackages(atomsdata = removedList, ask = ask, verbose = verbose, deps = False, systemPackagesCheck = False) + removePackages(atomsdata = removedList, ask = ask, verbose = verbose, deps = False, systemPackagesCheck = False, configFiles = True) else: print_info(red(" @@ ")+blue("Calculation complete.")) @@ -2461,11 +2464,13 @@ def installPackages(packages = [], atomsdata = [], ask = False, pretend = False, # running tasks totalqueue = str(len(runQueue)) + totalremovalqueue = str(len(removalQueue)) currentqueue = 0 currentremovalqueue = 0 clientDbconn = openClientDatabase() for idpackage in removalQueue: + currentremovalqueue += 1 infoDict = {} infoDict['removeatom'] = clientDbconn.retrieveAtom(idpackage) infoDict['removecontent'] = clientDbconn.retrieveContent(idpackage) @@ -2480,7 +2485,7 @@ def installPackages(packages = [], atomsdata = [], ask = False, pretend = False, steps.append("remove") steps.append("postremove") for step in steps: - rc = stepExecutor(step,infoDict) + rc = stepExecutor(step,infoDict,str(currentremovalqueue)+"/"+totalremovalqueue) if (rc != 0): clientDbconn.closeDB() dirscleanup() @@ -2534,10 +2539,11 @@ def installPackages(packages = [], atomsdata = [], ask = False, pretend = False, steps.append("showmessages") #print "steps for "+pkgatom+" -> "+str(steps) + print_info(red(" @@ ")+bold("(")+blue(str(currentqueue))+"/"+red(totalqueue)+bold(") ")+">>> "+darkgreen(pkgatom)) for step in steps: - rc = stepExecutor(step,actionQueue[pkgatom]) + rc = stepExecutor(step,actionQueue[pkgatom],str(currentqueue)+"/"+totalqueue) if (rc != 0): clientDbconn.closeDB() dirscleanup() @@ -2694,7 +2700,9 @@ def removePackages(packages = [], atomsdata = [], ask = False, pretend = False, for idpackage in plainRemovalQueue: removalQueue.append(idpackage) + currentqueue = 0 for idpackage in removalQueue: + currentqueue += 1 infoDict = {} infoDict['removeidpackage'] = idpackage infoDict['removeatom'] = clientDbconn.retrieveAtom(idpackage) @@ -2709,7 +2717,7 @@ def removePackages(packages = [], atomsdata = [], ask = False, pretend = False, steps.append("remove") steps.append("postremove") for step in steps: - rc = stepExecutor(step,infoDict) + rc = stepExecutor(step,infoDict,str(currentqueue)+"/"+str(len(removalQueue))) if (rc != 0): clientDbconn.closeDB() return -1,rc @@ -2807,15 +2815,17 @@ def dependenciesTest(quiet = False, ask = False, pretend = False): @description: execute the requested step (it is only used by the CLI client) @input: step -> name of the step to execute infoDict -> dictionary containing all the needed information collected by installPackages() -> actionQueue[pkgatom] + loopString -> used to print to xterm title bar something like "10/900 - equo" @output: -1,"description" for error ; 0,True for no errors ''' -def stepExecutor(step,infoDict): +def stepExecutor(step,infoDict, loopString = None): clientDbconn = openClientDatabase() output = 0 if step == "fetch": - print_info(red(" ## ")+blue("Fetching package: ")+red(os.path.basename(infoDict['download']))) + print_info(red(" ## ")+blue("Fetching archive: ")+red(os.path.basename(infoDict['download']))) + xtermTitle(loopString+' Fetching archive: '+os.path.basename(infoDict['download'])) output = fetchFileOnMirrors(infoDict['repository'],infoDict['download'],infoDict['checksum']) if output < 0: print_error(red("Package cannot be fetched. Try to run: '")+bold("equo update")+red("' and this command again. Error "+str(output))) @@ -2824,10 +2834,11 @@ def stepExecutor(step,infoDict): output = matchChecksum(infoDict) elif step == "install": + compatstring = '' if (etpConst['gentoo-compat']): - print_info(red(" ## ")+blue("Installing package: ")+red(os.path.basename(infoDict['download']))+" ## w/Gentoo compatibility") - else: - print_info(red(" ## ")+blue("Installing package: ")+red(os.path.basename(infoDict['download']))) + compatstring = " ## w/Gentoo compatibility" + print_info(red(" ## ")+blue("Installing package: ")+red(os.path.basename(infoDict['atom']))+compatstring) + xtermTitle(loopString+' Installing package: '+os.path.basename(infoDict['atom'])+compatstring) output = installPackage(infoDict) if output != 0: if output == 512: @@ -2841,6 +2852,7 @@ def stepExecutor(step,infoDict): if (etpConst['gentoo-compat']): gcompat = " ## w/Gentoo compatibility" print_info(red(" ## ")+blue("Removing installed package: ")+red(infoDict['removeatom'])+gcompat) + xtermTitle(loopString+' Removing installed package: '+os.path.basename(infoDict['removeatom'])+gcompat) output = removePackage(infoDict) if output != 0: errormsg = red("An error occured while trying to remove the package. Check if you have enough disk space on your hard disk. Error "+str(output)) diff --git a/client/triggerTools.py b/client/triggerTools.py index 3897e710a..da28de862 100644 --- a/client/triggerTools.py +++ b/client/triggerTools.py @@ -42,7 +42,10 @@ INITSERVICES_DIR="/var/lib/init.d/" def postinstall(pkgdata): functions = set() - + + if pkgdata['trigger']: + functions.add('call_ext_postinstall') + # fonts configuration if pkgdata['category'] == "media-fonts": functions.add("fontconfig") @@ -118,6 +121,9 @@ def preinstall(pkgdata): functions = set() + if pkgdata['trigger']: + functions.add('call_ext_preinstall') + # prepare content mycnt = set(pkgdata['content']) @@ -135,7 +141,10 @@ def preinstall(pkgdata): def postremove(pkgdata): functions = set() - + + if pkgdata['trigger']: + functions.add('call_ext_postremove') + # opengl configuration if (pkgdata['category'] == "x11-drivers") and (pkgdata['name'].startswith("nvidia-") or pkgdata['name'].startswith("ati-")): functions.add("openglsetup_xorg") @@ -185,6 +194,10 @@ def postremove(pkgdata): def preremove(pkgdata): functions = set() + + if pkgdata['trigger']: + functions.add('call_ext_preremove') + # prepare content mycnt = set(pkgdata['removecontent']) @@ -196,6 +209,42 @@ def preremove(pkgdata): return functions +######################################################## +#### +## External triggers support functions +# + +def call_ext_preinstall(pkgdata): + rc = call_ext_generic(pkgdata,'preinstall') + return rc + +def call_ext_postinstall(pkgdata): + rc = call_ext_generic(pkgdata,'postinstall') + return rc + +def call_ext_preremove(pkgdata): + rc = call_ext_generic(pkgdata,'preremove') + return rc + +def call_ext_postremove(pkgdata): + rc = call_ext_generic(pkgdata,'postremove') + return rc + +def call_ext_generic(pkgdata, stage): + + triggerfile = etpConst['entropyunpackdir']+"/trigger-"+str(entropyTools.getRandomNumber()) + while os.path.isfile(tmptriggerfile): + triggerfile = etpConst['entropyunpackdir']+"/trigger-"+str(entropyTools.getRandomNumber()) + f = open(triggerfile,"w") + for x in pkgdata['trigger']: + f.write(x) + f.close() + + execfile(triggerfile) + + os.remove(triggerfile) + return my_ext_status + ######################################################## #### ## Public functions diff --git a/libraries/databaseTools.py b/libraries/databaseTools.py index c818b9dfd..76f143927 100644 --- a/libraries/databaseTools.py +++ b/libraries/databaseTools.py @@ -1149,14 +1149,26 @@ class etpDatabase: ) ) - # is it a system package? - if etpData['systempackage']: - self.cursor.execute( - 'INSERT into systempackages VALUES ' - '(?)' - , ( idpackage, - ) - ) + try: + # is it a system package? + if etpData['systempackage']: + self.cursor.execute( + 'INSERT into systempackages VALUES ' + '(?)' + , ( idpackage, + ) + ) + except: + # FIXME: temp workaround, create systempackages table + self.createSystemPackagesTable() + # is it a system package? + if etpData['systempackage']: + self.cursor.execute( + 'INSERT into systempackages VALUES ' + '(?)' + , ( idpackage, + ) + ) # create new protect if it doesn't exist try: @@ -1383,8 +1395,11 @@ class etpDatabase: self.cursor.execute('DELETE FROM messages WHERE idpackage = '+idpackage) except: pass - # systempackage - self.cursor.execute('DELETE FROM systempackages WHERE idpackage = '+idpackage) + try: + # systempackage + self.cursor.execute('DELETE FROM systempackages WHERE idpackage = '+idpackage) + except: + pass try: # counter self.cursor.execute('DELETE FROM counters WHERE idpackage = '+idpackage) @@ -2601,7 +2616,12 @@ class etpDatabase: cache = self.fetchInfoCache(idpackage,'isSystemPackage') if cache != None: return cache - self.cursor.execute('SELECT idpackage FROM systempackages WHERE idpackage = "'+str(idpackage)+'"') + try: + self.cursor.execute('SELECT idpackage FROM systempackages WHERE idpackage = "'+str(idpackage)+'"') + except: # FIXME: remove this for 1.0 + self.createSystemPackagesTable() + self.cursor.execute('SELECT idpackage FROM systempackages WHERE idpackage = "'+str(idpackage)+'"') + result = self.cursor.fetchone() rslt = False if result: @@ -3128,7 +3148,12 @@ class etpDatabase: self.cursor.execute('CREATE TABLE needed ( idpackage INTEGER, idneeded INTEGER );') self.cursor.execute('CREATE TABLE neededreference ( idneeded INTEGER PRIMARY KEY, library VARCHAR );') self.commitChanges() - + + def createSystemPackagesTable(self): + dbLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_VERBOSE,"createSystemPackagesTable: called.") + self.cursor.execute('CREATE TABLE systempackages ( idpackage INTEGER );') + self.commitChanges() + def createProtectTable(self): dbLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_VERBOSE,"createProtectTable: called.") self.cursor.execute('DROP TABLE IF EXISTS configprotect;') diff --git a/libraries/entropyTools.py b/libraries/entropyTools.py index 584f80cd9..0ca304fb0 100644 --- a/libraries/entropyTools.py +++ b/libraries/entropyTools.py @@ -1109,6 +1109,7 @@ def umountProc(): return True def askquestion(prompt): + xtermTitle("Entropy got a question for you") responses, colours = ["Yes", "No"], [green, red] print darkgreen(prompt), try: diff --git a/libraries/outputTools.py b/libraries/outputTools.py index a15c49619..62fc5d326 100644 --- a/libraries/outputTools.py +++ b/libraries/outputTools.py @@ -161,13 +161,11 @@ def xtermTitle(mystr, raw=False): if dotitles and "TERM" in os.environ and sys.stderr.isatty(): myt=os.environ["TERM"] legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode","gnome"] - for term in legal_terms: - if myt.startswith(term): - if not raw: - mystr = "\x1b]0;%s\x07" % mystr - sys.stderr.write(mystr) - sys.stderr.flush() - break + if myt in legal_terms: + if not raw: + mystr = "\x1b]0;%s\x07" % mystr + sys.stderr.write(mystr) + sys.stderr.flush() default_xterm_title = None @@ -264,9 +262,7 @@ def print_generic(msg): # here we'll wrap any nice formatting def writechar(char): sys.stdout.write(char); sys.stdout.flush() -# function that reads user input printing a request like this: -# Your name: where "Your name:" is request -# the user input is returned def readtext(request): + xtermTitle("Entropy needs your attention") text = raw_input(request) return text \ No newline at end of file diff --git a/server/trigger b/server/trigger index 2f344c6b4..f9f5ed3ec 100644 --- a/server/trigger +++ b/server/trigger @@ -8,19 +8,16 @@ @ postinstall(): triggered after injecting data into the database and copying files on the system @ postremove(): triggered after removing files from the system and from the database - - You are allowed to not specify one or more of them. - - Each function must have as input arguments pkgdata = None. Where pkgdata is a python dict containing package information - >>> databaseTools.etpDatabase.getPackageData(idpackage) - - Each function must return 0 in case of success and >0 in case of issues. Entropy will show the error code to the user. + - You must always specify them. + - Each function can only print errors and ONLY in case of critical ones, return != 0 that will be grabbed by the trigger (setting ext_status) How it works: - - this file will be stored inside the .tbz2 injected entropy database - - entropy database will be extracted and placed into the unpack directory + - this file will be stored inside the entropy database - trigger code will be extracted and saved into a file with the name trigger inside the package unpack directory - will be issued: stage = 'postinstall' # this can be postinstall, preinstall, postremove, preremove execfile(etpConst['entropyunpackdir']+...+"trigger") - - code will have access to all the entropy functions and modules. it will be executed inside triggerTools + - code will have access to the entropy package dictionary and will be executed inside triggerTools (postinstall(),preinstall(),postremove(),preremove()) Example of pkgdata: { @@ -65,29 +62,32 @@ ''' space for real triggers ''' -def ext_postinstall(): - print printhello()+" postinstall" +def ext_postinstall(pkgdata): + print my_ext_printhello()+" postinstall" return 0 -def ext_preinstall(): - print printhello()+" preinstall" +def ext_preinstall(pkgdata): + print my_ext_printhello()+" preinstall" return 0 -def ext_postremove(): - print printhello()+" postremove" +def ext_postremove(pkgdata): + print my_ext_printhello()+" postremove" return 0 -def ext_preremove(): - print printhello()+" preremove" +def ext_preremove(pkgdata): + print my_ext_printhello()+" preremove" return 0 ''' space for private functions + Important: function must be declared globally and have suffix my_ext_ ''' -def printhello(): +global my_ext_printhello +def my_ext_printhello(): return "hello!" ''' run the selected function ''' -eval("ext_"+stage)() \ No newline at end of file +global my_ext_status +my_ext_status = eval("ext_"+stage)(pkgdata) \ No newline at end of file