From 491007bf2f9be94dbfa2764f3a11a3d4536a162b Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@cd1c1023-2f26-0410-ae45-c471fc1f0318> Date: Thu, 14 Feb 2008 17:16:56 +0000 Subject: [PATCH] Spritz: - completed configuration files interface - some misc bug fixes Entropy: - moved the package masking parser to entropy.py/EquoInterface - fixed some issues in equo query orphans and moved some equo conf functions to its EquoInterface class git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@1212 cd1c1023-2f26-0410-ae45-c471fc1f0318 --- TODO | 1 - client/text_configuration.py | 101 ++++++------ client/text_query.py | 22 ++- libraries/entropy.py | 279 +++++++++++++++++++++++++++++++--- libraries/entropyConstants.py | 11 +- libraries/entropyTools.py | 2 + libraries/maskingparser.py | 221 --------------------------- spritz/src/spritz.glade | 4 + spritz/src/spritz.py | 67 ++++++-- spritz/src/views.py | 28 +++- 10 files changed, 394 insertions(+), 342 deletions(-) delete mode 100644 libraries/maskingparser.py diff --git a/TODO b/TODO index e26ded645..27d8b3265 100644 --- a/TODO +++ b/TODO @@ -12,7 +12,6 @@ TODO list: - find a way to better handle real smartapps deps (need split PDEPEND?) Spritz: - - handle config files updates interface (*) - handle multi repos in "available" menu (*) - add masking interface (*) - add branch switching menu (for upgrades) (*) diff --git a/client/text_configuration.py b/client/text_configuration.py index 6bc8cb8fa..9293e70c6 100644 --- a/client/text_configuration.py +++ b/client/text_configuration.py @@ -72,7 +72,7 @@ def update(cmd = None): while 1: print_info(brown(" @@ ")+darkgreen("Scanning filesystem...")) scandata = Equo.FileUpdates.scanfs(dcache = cache_status) - if (cache_status): + if cache_status: for x in scandata: print_info("("+blue(str(x))+") "+red(" file: ")+etpConst['systemroot']+scandata[x]['destination']) cache_status = True @@ -100,7 +100,8 @@ def update(cmd = None): # automerge files asking one by one for key in keys: if not os.path.isfile(etpConst['systemroot']+scandata[key]['source']): - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + Equo.FileUpdates.remove_from_cache(key) + scandata = Equo.FileUpdates.scandata continue print_info(darkred("Configuration file: ")+darkgreen(etpConst['systemroot']+scandata[key]['destination'])) if cmd == -3: @@ -109,28 +110,19 @@ def update(cmd = None): continue print_info(darkred("Moving ")+darkgreen(etpConst['systemroot']+scandata[key]['source'])+darkred(" to ")+brown(etpConst['systemroot']+scandata[key]['destination'])) - # old file backup - if etpConst['filesbackup'] and os.path.isfile(etpConst['systemroot']+scandata[key]['destination']): - bcount = 0 - backupfile = etpConst['systemroot']+os.path.dirname(scandata[key]['destination'])+"/._equo_backup."+unicode(bcount)+"_"+os.path.basename(scandata[key]['destination']) - while os.path.lexists(backupfile): - bcount += 1 - backupfile = etpConst['systemroot']+os.path.dirname(scandata[key]['destination'])+"/._equo_backup."+unicode(bcount)+"_"+os.path.basename(scandata[key]['destination']) - try: - shutil.copy2(etpConst['systemroot']+scandata[key]['destination'],backupfile) - except IOError: - pass + Equo.FileUpdates.merge_file(key) + scandata = Equo.FileUpdates.scandata - shutil.move(etpConst['systemroot']+scandata[key]['source'],etpConst['systemroot']+scandata[key]['destination']) - # remove from cache - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) break elif cmd in (-7,-9): for key in keys: if not os.path.isfile(etpConst['systemroot']+scandata[key]['source']): - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + + Equo.FileUpdates.remove_from_cache(key) + scandata = Equo.FileUpdates.scandata + continue print_info(darkred("Configuration file: ")+darkgreen(etpConst['systemroot']+scandata[key]['destination'])) if cmd == -7: @@ -138,11 +130,9 @@ def update(cmd = None): if rc == "No": continue print_info(darkred("Discarding ")+darkgreen(etpConst['systemroot']+scandata[key]['source'])) - try: - os.remove(etpConst['systemroot']+scandata[key]['source']) - except: - pass - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + + Equo.FileUpdates.remove_file(key) + scandata = Equo.FileUpdates.scandata break @@ -151,20 +141,27 @@ def update(cmd = None): # do files exist? if not os.path.isfile(etpConst['systemroot']+scandata[cmd]['source']): - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + + Equo.FileUpdates.remove_from_cache(cmd) + scandata = Equo.FileUpdates.scandata + continue if not os.path.isfile(etpConst['systemroot']+scandata[cmd]['destination']): print_info(darkred("Automerging file: ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) - shutil.move(etpConst['systemroot']+scandata[key]['source'],etpConst['systemroot']+scandata[key]['destination']) - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + + Equo.FileUpdates.merge_file(cmd) + scandata = Equo.FileUpdates.scandata + continue # end check diff = showdiff(etpConst['systemroot']+scandata[cmd]['destination'],etpConst['systemroot']+scandata[cmd]['source']) if (not diff): print_info(darkred("Automerging file ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) - shutil.move(etpConst['systemroot']+scandata[cmd]['source'],etpConst['systemroot']+scandata[cmd]['destination']) - scandata = Equo.FileUpdates.remove_from_cache(scandata,key) + + Equo.FileUpdates.merge_file(cmd) + scandata = Equo.FileUpdates.scandata + continue print_info(darkred("Selected file: ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) @@ -182,37 +179,28 @@ def update(cmd = None): comeback = True break elif action == 1: - print_info(darkred("Replacing ")+darkgreen(etpConst['systemroot']+scandata[cmd]['destination'])+darkred(" with ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) + print_info(darkred("Replacing ") + darkgreen(etpConst['systemroot'] + \ + scandata[cmd]['destination']) + darkred(" with ") + \ + darkgreen(etpConst['systemroot'] + scandata[cmd]['source'])) - # old file backup - if etpConst['filesbackup'] and os.path.isfile(etpConst['systemroot']+scandata[cmd]['destination']): - bcount = 0 - backupfile = etpConst['systemroot']+os.path.dirname(scandata[cmd]['destination'])+"/._equo_backup."+unicode(bcount)+"_"+os.path.basename(scandata[cmd]['destination']) - while os.path.lexists(backupfile): - bcount += 1 - backupfile = etpConst['systemroot']+os.path.dirname(scandata[cmd]['destination'])+"/._equo_backup."+unicode(bcount)+"_"+os.path.basename(scandata[cmd]['destination']) - try: - shutil.copy2(etpConst['systemroot']+scandata[cmd]['destination'],backupfile) - except IOError: - pass + Equo.FileUpdates.merge_file(cmd) + scandata = Equo.FileUpdates.scandata - shutil.move(etpConst['systemroot']+scandata[cmd]['source'],etpConst['systemroot']+scandata[cmd]['destination']) - scandata = Equo.FileUpdates.remove_from_cache(scandata,cmd) comeback = True break elif action == 2: - print_info(darkred("Deleting file ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) - try: - os.remove(etpConst['systemroot']+scandata[cmd]['source']) - except: - pass - scandata = Equo.FileUpdates.remove_from_cache(scandata,cmd) + print_info(darkred("Deleting file ") + darkgreen(etpConst['systemroot'] + scandata[cmd]['source'])) + + Equo.FileUpdates.remove_file(cmd) + scandata = Equo.FileUpdates.scandata + comeback = True break elif action == 3: - print_info(darkred("Editing file ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) + print_info(darkred("Editing file ") + darkgreen(etpConst['systemroot']+scandata[cmd]['source'])) + if os.getenv("EDITOR"): os.system("$EDITOR "+etpConst['systemroot']+scandata[cmd]['source']) elif os.access("/bin/nano",os.X_OK): @@ -229,12 +217,15 @@ def update(cmd = None): print_error(" Cannot find a suitable editor. Can't edit file directly.") comeback = True break - print_info(darkred("Edited file ")+darkgreen(etpConst['systemroot']+scandata[cmd]['source'])+darkred(" - showing differencies:")) - diff = showdiff(etpConst['systemroot']+scandata[cmd]['destination'],etpConst['systemroot']+scandata[cmd]['source']) - if (not diff): - print_info(darkred("Automerging file ")+darkgreen(scandata[cmd]['source'])) - shutil.move(etpConst['systemroot']+scandata[cmd]['source'],etpConst['systemroot']+scandata[cmd]['destination']) - scandata = Equo.FileUpdates.remove_from_cache(scandata, cmd) + + print_info(darkred("Edited file ") + darkgreen(etpConst['systemroot'] + scandata[cmd]['source']) + darkred(" - showing differencies:")) + diff = showdiff(etpConst['systemroot'] + scandata[cmd]['destination'],etpConst['systemroot'] + scandata[cmd]['source']) + if not diff: + print_info(darkred("Automerging file ") + darkgreen(scandata[cmd]['source'])) + + Equo.FileUpdates.merge_file(cmd) + scandata = Equo.FileUpdates.scandata + comeback = True break @@ -242,7 +233,7 @@ def update(cmd = None): elif action == 4: # show diffs again - diff = showdiff(etpConst['systemroot']+scandata[cmd]['destination'],etpConst['systemroot']+scandata[cmd]['source']) + diff = showdiff(etpConst['systemroot'] + scandata[cmd]['destination'], etpConst['systemroot'] + scandata[cmd]['source']) continue if (comeback): diff --git a/client/text_query.py b/client/text_query.py index b1ca367cc..807c41664 100644 --- a/client/text_query.py +++ b/client/text_query.py @@ -394,13 +394,14 @@ def searchOrphans(): for currentdir,subdirs,files in os.walk(xdir): for filename in files: # filter python compiled objects? - if filename.endswith(".pyo") or filename.startswith(".pyc") or filename == '.keep': + if filename.endswith(".pyo") or filename.endswith(".pyc") or filename == '.keep': continue - mask = [x for x in etpConst['filesystemdirsmask'] if x.startswith(x)] - if (not mask): + filename = os.path.join(currentdir,filename) + mask = [x for x in etpConst['filesystemdirsmask'] if filename.startswith(x)] + if not mask: if (not etpUi['quiet']): - print_info(red(" @@ ")+blue("Looking: ")+bold(file[:50]+"..."), back = True) - foundFiles.add(file) + print_info(red(" @@ ")+blue("Looking: ")+bold(filename[:50]+"..."), back = True) + foundFiles.add(filename) totalfiles = len(foundFiles) if (not etpUi['quiet']): print_info(red(" @@ ")+blue("Analyzed directories: ")+' '.join(etpConst['filesystemdirs'])) @@ -419,15 +420,12 @@ def searchOrphans(): atom = clientDbconn.retrieveAtom(idpackage) txt = "["+str(count)+"/"+length+"] " print_info(red(" @@ ")+blue("Intersecting content of package: ")+txt+bold(atom), back = True) - content = clientDbconn.retrieveContent(idpackage) - _content = set() - for x in content: + for x in clientDbconn.retrieveContent(idpackage): if x.startswith("/usr/lib64"): x = "/usr/lib"+x[len("/usr/lib64"):] - _content.add(x) + content.add(x) # remove from foundFiles - del content - foundFiles.difference_update(_content) + foundFiles -= content if (not etpUi['quiet']): print_info(red(" @@ ")+blue("Intersection completed. Showing statistics: ")) print_info(red(" @@ ")+blue("Number of total files: ")+bold(str(totalfiles))) @@ -437,7 +435,7 @@ def searchOrphans(): # order foundFiles = list(foundFiles) foundFiles.sort() - if (not etpUi['quiet']): + if not etpUi['quiet']: print_info(red(" @@ ")+blue("Writing file to disk: ")+bold("/tmp/equo-orphans.txt")) f = open("/tmp/equo-orphans.txt","w") for x in foundFiles: diff --git a/libraries/entropy.py b/libraries/entropy.py index 8ab94761d..b78c589ef 100644 --- a/libraries/entropy.py +++ b/libraries/entropy.py @@ -90,9 +90,12 @@ class EquoInterface(TextInterface): self.xcache = xcache if self.openclientdb: self.openClientDatabase() - self.FileUpdates = self.__FileUpdates() + self.FileUpdates = self.FileUpdatesInterfaceLoader() self.repoDbCache = {} + # masking parser + self.MaskingParser = self.PackageMaskingParserInterfaceLoader() + # are we running on a livecd? (/proc/cmdline has "cdroot") if self.entropyTools.islive(): self.xcache = False @@ -179,6 +182,14 @@ class EquoInterface(TextInterface): NOTE: DO NOT USE THIS DIRECTLY, BUT USE EquoInterface.openRepositoryDatabase ''' def loadRepositoryDatabase(self, repositoryName, xcache = True, indexing = True): + + # load the masking parser + if etpConst['packagemasking'] == None: + etpConst['packagemasking'] = self.MaskingParser.parse() + # merge universal keywords + for x in etpConst['packagemasking']['keywords']['universal']: + etpConst['keywords'].add(x) + if repositoryName.endswith(".tbz2"): xcache = False dbfile = etpRepositories[repositoryName]['dbpath']+"/"+etpConst['etpdatabasefile'] @@ -2039,13 +2050,17 @@ class EquoInterface(TextInterface): ''' Configuration files (updates, not entropy related) interface :: begin ''' - def __FileUpdates(self): + def FileUpdatesInterfaceLoader(self): conn = FileUpdatesInterface(EquoInstance = self) return conn ''' Configuration files (updates, not entropy related) interface :: end ''' + def PackageMaskingParserInterfaceLoader(self): + conn = PackageMaskingParser(EquoInstance = self) + return conn + ''' Real package actions (install/remove) interface ''' @@ -3353,17 +3368,51 @@ class FileUpdatesInterface: except: raise exceptionTools.IncorrectParameter("IncorrectParameter: a valid Entropy Instance is needed") + self.scandata = None + + def merge_file(self, key): + self.scanfs(dcache = True) + self.do_backup(key) + shutil.move(etpConst['systemroot'] + self.scandata[key]['source'], etpConst['systemroot'] + self.scandata[key]['destination']) + self.remove_from_cache(key) + + def remove_file(self, key): + self.scanfs(dcache = True) + try: + os.remove(etpConst['systemroot'] + self.scandata[key]['source']) + except OSError: + pass + self.remove_from_cache(key) + + def do_backup(self, key): + self.scanfs(dcache = True) + if etpConst['filesbackup'] and os.path.isfile(etpConst['systemroot']+self.scandata[key]['destination']): + bcount = 0 + backupfile = etpConst['systemroot'] + os.path.dirname(self.scandata[key]['destination']) + "/._equo_backup." + unicode(bcount) + "_" + os.path.basename(self.scandata[key]['destination']) + while os.path.lexists(backupfile): + bcount += 1 + backupfile = etpConst['systemroot'] + os.path.dirname(self.scandata[key]['destination']) + "/._equo_backup." + unicode(bcount) + "_" + os.path.basename(self.scandata[key]['destination']) + try: + shutil.copy2(etpConst['systemroot'] + self.scandata[key]['destination'],backupfile) + except IOError: + pass + ''' @description: scan for files that need to be merged @output: dictionary using filename as key ''' def scanfs(self, dcache = True): - if (dcache): + if dcache: + + if self.scandata != None: + return self.scandata + # can we load cache? try: z = self.load_cache() if z != None: + self.scandata = z.copy() return z except: pass @@ -3432,6 +3481,7 @@ class FileUpdatesInterface: self.Entropy.dumpTools.dumpobj(etpCache['configfiles'],scandata) except IOError: pass + self.scandata = scandata.copy() return scandata def load_cache(self): @@ -3462,15 +3512,12 @@ class FileUpdatesInterface: @attention: please be sure that filepath is properly formatted before using this function ''' def add_to_cache(self, filepath): - try: - scandata = self.load_cache() - except: - scandata = self.scanfs(dcache = False) - keys = scandata.keys() + self.scanfs(dcache = True) + keys = self.scandata.keys() try: for key in keys: - if scandata[key]['source'] == filepath[len(etpConst['systemroot']):]: - del scandata[key] + if self.scandata[key]['source'] == filepath[len(etpConst['systemroot']):]: + del self.scandata[key] except: pass # get next counter @@ -3481,19 +3528,17 @@ class FileUpdatesInterface: index = 0 index += 1 mydata = self.generate_dict(filepath) - scandata[index] = mydata.copy() - try: - self.Entropy.dumpTools.dumpobj(etpCache['configfiles'],scandata) - except IOError: - pass + self.scandata[index] = mydata.copy() + self.Entropy.dumpTools.dumpobj(etpCache['configfiles'],self.scandata) - def remove_from_cache(self, sd, key): + def remove_from_cache(self, key): + self.scanfs(dcache = True) try: - del sd[key] + del self.scandata[key] except: pass - self.Entropy.dumpTools.dumpobj(etpCache['configfiles'],sd) - return sd + self.Entropy.dumpTools.dumpobj(etpCache['configfiles'],self.scandata) + return self.scandata def generate_dict(self, filepath): @@ -5520,6 +5565,7 @@ class TriggerInterface: def trigger_ebuild_postinstall(self): stdfile = open("/dev/null","w") oldstderr = sys.stderr + oldstdout = sys.stdout sys.stderr = stdfile myebuild = [self.pkgdata['xpakdir']+"/"+x for x in os.listdir(self.pkgdata['xpakdir']) if x.endswith(".ebuild")] @@ -5532,10 +5578,13 @@ class TriggerInterface: header = red(" ##") ) try: - if not os.path.isfile(self.pkgdata['unpackdir']+"/portage/"+portage_atom+"/temp/environment"): # if environment is not yet created, we need to run pkg_setup() + if not os.path.isfile(self.pkgdata['unpackdir']+"/portage/"+portage_atom+"/temp/environment"): + # if environment is not yet created, we need to run pkg_setup() + sys.stdout = stdfile rc = self.portageTools.portage_doebuild(myebuild, mydo = "setup", tree = "bintree", cpv = portage_atom, portage_tmpdir = self.pkgdata['unpackdir']) if rc == 1: self.Entropy.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"[POST] ATTENTION Cannot properly run Gentoo postinstall (pkg_setup()) trigger for "+str(portage_atom)+". Something bad happened.") + sys.stdout = oldstdout rc = self.portageTools.portage_doebuild(myebuild, mydo = "postinst", tree = "bintree", cpv = portage_atom, portage_tmpdir = self.pkgdata['unpackdir']) if rc == 1: self.Entropy.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"[POST] ATTENTION Cannot properly run Gentoo postinstall (pkg_postinst()) trigger for "+str(portage_atom)+". Something bad happened.") @@ -5553,6 +5602,7 @@ class TriggerInterface: def trigger_ebuild_preinstall(self): stdfile = open("/dev/null","w") oldstderr = sys.stderr + oldstdout = sys.stdout sys.stderr = stdfile myebuild = [self.pkgdata['xpakdir']+"/"+x for x in os.listdir(self.pkgdata['xpakdir']) if x.endswith(".ebuild")] @@ -5565,9 +5615,11 @@ class TriggerInterface: header = red(" ##") ) try: + sys.stdout = stdfile rc = self.portageTools.portage_doebuild(myebuild, mydo = "setup", tree = "bintree", cpv = portage_atom, portage_tmpdir = self.pkgdata['unpackdir']) # create mysettings["T"]+"/environment" if rc == 1: self.Entropy.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"[PRE] ATTENTION Cannot properly run Gentoo preinstall (pkg_setup()) trigger for "+str(portage_atom)+". Something bad happened.") + sys.stdout = oldstdout rc = self.portageTools.portage_doebuild(myebuild, mydo = "preinst", tree = "bintree", cpv = portage_atom, portage_tmpdir = self.pkgdata['unpackdir']) if rc == 1: self.Entropy.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"[PRE] ATTENTION Cannot properly run Gentoo preinstall (pkg_preinst()) trigger for "+str(portage_atom)+". Something bad happened.") @@ -6044,6 +6096,193 @@ timeout=10 ) return "(hd0,0)" +class PackageMaskingParser: + + def __init__(self, EquoInstance): + + self.Entropy = EquoInstance + try: + self.Entropy.instanceTest() + except: + raise exceptionTools.IncorrectParameter("IncorrectParameter: a valid Entropy Instance is needed") + + def parse(self): + + self.etpMaskFiles = { + 'keywords': etpConst['confdir']+"/packages/package.keywords", # keywording configuration files + 'unmask': etpConst['confdir']+"/packages/package.unmask", # unmasking configuration files + 'mask': etpConst['confdir']+"/packages/package.mask", # masking configuration files + } + self.etpMtimeFiles = { + 'keywords_mtime': etpConst['dumpstoragedir']+"/keywords.mtime", # keywording configuration files mtime + 'unmask_mtime': etpConst['dumpstoragedir']+"/unmask.mtime", # unmasking configuration files mtime + 'mask_mtime': etpConst['dumpstoragedir']+"/mask.mtime", # masking configuration files mtime + } + + data = {} + for item in self.etpMaskFiles: + data[item] = eval('self.'+item+'_parser')() + return data + + + ''' + parser of package.keywords file + ''' + def keywords_parser(self): + + self.__validateEntropyCache(self.etpMaskFiles['keywords'],self.etpMtimeFiles['keywords_mtime']) + + data = { + 'universal': set(), + 'packages': {}, + 'repositories': {}, + } + if os.path.isfile(self.etpMaskFiles['keywords']): + f = open(self.etpMaskFiles['keywords'],"r") + content = f.readlines() + f.close() + # filter comments and white lines + content = [x.strip() for x in content if not x.startswith("#") and x.strip()] + for line in content: + keywordinfo = line.split() + # skip wrong lines + if len(keywordinfo) > 3: + sys.stderr.write(">> "+line+" << is invalid!!") + continue + if len(keywordinfo) == 1: # inversal keywording, check if it's not repo= + # repo=? + if keywordinfo[0].startswith("repo="): + sys.stderr.write(">> "+line+" << is invalid!!") + continue + # atom? is it worth it? it would take a little bit to parse uhm... >50 entries...!? + #kinfo = keywordinfo[0] + if keywordinfo[0] == "**": keywordinfo[0] = "" # convert into entropy format + data['universal'].add(keywordinfo[0]) + continue # needed? + if len(keywordinfo) in (2,3): # inversal keywording, check if it's not repo= + # repo=? + if keywordinfo[0].startswith("repo="): + sys.stderr.write(">> "+line+" << is invalid!!") + continue + # add to repo? + items = keywordinfo[1:] + if keywordinfo[0] == "**": keywordinfo[0] = "" # convert into entropy format + reponame = [x for x in items if x.startswith("repo=") and (len(x.split("=")) == 2)] + if reponame: + reponame = reponame[0].split("=")[1] + if reponame not in data['repositories']: + data['repositories'][reponame] = {} + # repository unmask or package in repository unmask? + if keywordinfo[0] not in data['repositories'][reponame]: + data['repositories'][reponame][keywordinfo[0]] = set() + if len(items) == 1: + # repository unmask + data['repositories'][reponame][keywordinfo[0]].add('*') + else: + if "*" not in data['repositories'][reponame][keywordinfo[0]]: + item = [x for x in items if not x.startswith("repo=")] + data['repositories'][reponame][keywordinfo[0]].add(item[0]) + else: + # it's going to be a faulty line!!?? + if len(items) == 2: # can't have two items and no repo= + sys.stderr.write(">> "+line+" << is invalid!!") + continue + # add keyword to packages + if keywordinfo[0] not in data['packages']: + data['packages'][keywordinfo[0]] = set() + data['packages'][keywordinfo[0]].add(items[0]) + return data + + + def unmask_parser(self): + self.__validateEntropyCache(self.etpMaskFiles['unmask'],self.etpMtimeFiles['unmask_mtime']) + + data = set() + if os.path.isfile(self.etpMaskFiles['unmask']): + f = open(self.etpMaskFiles['unmask'],"r") + content = f.readlines() + f.close() + # filter comments and white lines + content = [x.strip() for x in content if not x.startswith("#") and x.strip()] + for line in content: + # FIXME: need validation? probably not since atomMatch handles it all + # and doesn't care about badly formatted atoms + data.add(line) + return data + + def mask_parser(self): + self.__validateEntropyCache(self.etpMaskFiles['mask'],self.etpMtimeFiles['mask_mtime']) + + data = set() + if os.path.isfile(self.etpMaskFiles['mask']): + f = open(self.etpMaskFiles['mask'],"r") + content = f.readlines() + f.close() + # filter comments and white lines + content = [x.strip() for x in content if not x.startswith("#") and x.strip()] + for line in content: + # FIXME: need validation? probably not since atomMatch handles it all + # and doesn't care about badly formatted atoms + data.add(line) + return data + + ''' + internal functions + ''' + + def __removeRepoCache(self): + if os.path.isdir(etpConst['dumpstoragedir']): + for repoid in etpRepositoriesOrder: + self.Entropy.repository_move_clear_cache(repoid) + else: + os.makedirs(etpConst['dumpstoragedir']) + + def __saveFileMtime(self,toread,tosaveinto): + + if not os.path.isfile(toread): + currmtime = 0.0 + else: + currmtime = os.path.getmtime(toread) + + if not os.path.isdir(etpConst['dumpstoragedir']): + os.makedirs(etpConst['dumpstoragedir']) + + f = open(tosaveinto,"w") + f.write(str(currmtime)) + f.flush() + f.close() + + + def __validateEntropyCache(self,maskfile,mtimefile): + + if os.getuid() != 0: # can't validate if running as user, thus cache shouldn't be loaded either + return + + # handle on-disk cache validation + # in this case, repositories cache + # if package.keywords is changed, we must destroy cache + if not os.path.isfile(mtimefile): + # we can't know if package.keywords has been updated + # remove repositories caches + self.__removeRepoCache() + self.__saveFileMtime(maskfile,mtimefile) + else: + # check mtime + try: + f = open(mtimefile,"r") + mtime = float(f.readline().strip()) + # compare with current mtime + try: + currmtime = os.path.getmtime(maskfile) + except OSError: + currmtime = 0.0 + if mtime != currmtime: + self.__removeRepoCache() + self.__saveFileMtime(maskfile,mtimefile) + except: + self.__removeRepoCache() + self.__saveFileMtime(maskfile,mtimefile) + class Callable: def __init__(self, anycallable): diff --git a/libraries/entropyConstants.py b/libraries/entropyConstants.py index d9e2aa747..4cb87dc57 100644 --- a/libraries/entropyConstants.py +++ b/libraries/entropyConstants.py @@ -26,7 +26,6 @@ import gc import sys import os import stat -import maskingparser import exceptionTools @@ -626,7 +625,7 @@ def initConfig_entropyConstants(rootdir): 'securityurl': "http://packages.sabayonlinux.org/security/security-advisories.tar.bz2", # packages keywords/mask/unmask settings - 'packagemasking': {}, # package masking information dictionary filled by maskingparser.py + 'packagemasking': None, # package masking information dictionary filled by the masking parser # packages whose need their other installs (different tag), to be removed 'conflicting_tagged_packages': { @@ -887,14 +886,6 @@ def initConfig_entropyConstants(rootdir): url += etpConst['product']+"/handlers/" etpRemoteSupport[servername] = url - # generate masking dictionary - myparser = maskingparser.parser(etpConst,etpCache) - etpConst['packagemasking'] = myparser.parse() - # merge universal keywords - for x in etpConst['packagemasking']['keywords']['universal']: - etpConst['keywords'].add(x) - del myparser - gc.collect() initConfig_clientConstants() diff --git a/libraries/entropyTools.py b/libraries/entropyTools.py index b8922f0b8..5ac446771 100644 --- a/libraries/entropyTools.py +++ b/libraries/entropyTools.py @@ -148,6 +148,8 @@ def get_remote_data(url): return False def islive(): + if not os.path.isfile("/proc/cmdline"): + return False f = open("/proc/cmdline") cmdline = f.readline().strip().split() f.close() diff --git a/libraries/maskingparser.py b/libraries/maskingparser.py deleted file mode 100644 index 967e7fc3a..000000000 --- a/libraries/maskingparser.py +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/python -''' - # DESCRIPTION: - # Parser of /etc/entropy/packages/* files - - Copyright (C) 2007-2008 Fabio Erculiani - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -''' -import os - -''' - This function parses files in etpMaskFiles and returns collected data to caller (dict) -''' - -class parser: - - def __init__(self,etpConst,etpCache): - - self.etpConst = etpConst - self.etpCache = etpCache - - - def parse(self): - - self.etpMaskFiles = { - 'keywords': self.etpConst['confdir']+"/packages/package.keywords", # keywording configuration files - 'unmask': self.etpConst['confdir']+"/packages/package.unmask", # unmasking configuration files - 'mask': self.etpConst['confdir']+"/packages/package.mask", # masking configuration files - } - self.etpMtimeFiles = { - 'keywords_mtime': self.etpConst['dumpstoragedir']+"/keywords.mtime", # keywording configuration files mtime - 'unmask_mtime': self.etpConst['dumpstoragedir']+"/unmask.mtime", # unmasking configuration files mtime - 'mask_mtime': self.etpConst['dumpstoragedir']+"/mask.mtime", # masking configuration files mtime - } - - data = {} - for item in self.etpMaskFiles: - data[item] = eval('self.'+item+'_parser')() - return data - - - ''' - parser of package.keywords file - ''' - def keywords_parser(self): - - self.__validateEntropyCache(self.etpMaskFiles['keywords'],self.etpMtimeFiles['keywords_mtime']) - - data = { - 'universal': set(), - 'packages': {}, - 'repositories': {}, - } - if os.path.isfile(self.etpMaskFiles['keywords']): - f = open(self.etpMaskFiles['keywords'],"r") - content = f.readlines() - f.close() - # filter comments and white lines - content = [x.strip() for x in content if not x.startswith("#") and x.strip()] - for line in content: - keywordinfo = line.split() - # skip wrong lines - if len(keywordinfo) > 3: - print ">> "+line+" << is invalid!!" - continue - if len(keywordinfo) == 1: # inversal keywording, check if it's not repo= - # repo=? - if keywordinfo[0].startswith("repo="): - print ">> "+line+" << is invalid!!" - continue - # atom? is it worth it? it would take a little bit to parse uhm... >50 entries...!? - #kinfo = keywordinfo[0] - if keywordinfo[0] == "**": keywordinfo[0] = "" # convert into entropy format - data['universal'].add(keywordinfo[0]) - continue # needed? - if len(keywordinfo) in (2,3): # inversal keywording, check if it's not repo= - # repo=? - if keywordinfo[0].startswith("repo="): - print ">> "+line+" << is invalid!!" - continue - # add to repo? - items = keywordinfo[1:] - if keywordinfo[0] == "**": keywordinfo[0] = "" # convert into entropy format - reponame = [x for x in items if x.startswith("repo=") and (len(x.split("=")) == 2)] - if reponame: - reponame = reponame[0].split("=")[1] - if reponame not in data['repositories']: - data['repositories'][reponame] = {} - # repository unmask or package in repository unmask? - if keywordinfo[0] not in data['repositories'][reponame]: - data['repositories'][reponame][keywordinfo[0]] = set() - if len(items) == 1: - # repository unmask - data['repositories'][reponame][keywordinfo[0]].add('*') - else: - if "*" not in data['repositories'][reponame][keywordinfo[0]]: - item = [x for x in items if not x.startswith("repo=")] - data['repositories'][reponame][keywordinfo[0]].add(item[0]) - else: - # it's going to be a faulty line!!?? - if len(items) == 2: # can't have two items and no repo= - print ">> "+line+" << is invalid!!" - continue - # add keyword to packages - if keywordinfo[0] not in data['packages']: - data['packages'][keywordinfo[0]] = set() - data['packages'][keywordinfo[0]].add(items[0]) - return data - - - def unmask_parser(self): - self.__validateEntropyCache(self.etpMaskFiles['unmask'],self.etpMtimeFiles['unmask_mtime']) - - data = set() - if os.path.isfile(self.etpMaskFiles['unmask']): - f = open(self.etpMaskFiles['unmask'],"r") - content = f.readlines() - f.close() - # filter comments and white lines - content = [x.strip() for x in content if not x.startswith("#") and x.strip()] - for line in content: - # FIXME: need validation? probably not since atomMatch handles it all - # and doesn't care about badly formatted atoms - data.add(line) - return data - - def mask_parser(self): - self.__validateEntropyCache(self.etpMaskFiles['mask'],self.etpMtimeFiles['mask_mtime']) - - data = set() - if os.path.isfile(self.etpMaskFiles['mask']): - f = open(self.etpMaskFiles['mask'],"r") - content = f.readlines() - f.close() - # filter comments and white lines - content = [x.strip() for x in content if not x.startswith("#") and x.strip()] - for line in content: - # FIXME: need validation? probably not since atomMatch handles it all - # and doesn't care about badly formatted atoms - data.add(line) - return data - - ''' - internal functions - ''' - - def __removeRepoCache(self): - if os.path.isdir(self.etpConst['dumpstoragedir']): - content = os.listdir(self.etpConst['dumpstoragedir']) - for item in content: - if item.startswith(self.etpCache['dbMatch']+self.etpConst['dbnamerepoprefix']) and item.endswith(".dmp"): - os.remove(self.etpConst['dumpstoragedir']+"/"+item) - elif item.startswith(self.etpCache['atomMatch']) and item.endswith(".dmp"): - os.remove(self.etpConst['dumpstoragedir']+"/"+item) - elif item.startswith(self.etpCache['world_update']) and item.endswith(".dmp"): - os.remove(self.etpConst['dumpstoragedir']+"/"+item) - elif item.startswith(self.etpCache['world_available']) and item.endswith(".dmp"): - os.remove(self.etpConst['dumpstoragedir']+"/"+item) - elif item.startswith(self.etpCache['check_package_update']) and item.endswith(".dmp"): - os.remove(self.etpConst['dumpstoragedir']+"/"+item) - else: - os.makedirs(self.etpConst['dumpstoragedir']) - - def __saveFileMtime(self,toread,tosaveinto): - - if not os.path.isfile(toread): - currmtime = 0.0 - else: - currmtime = os.path.getmtime(toread) - - if not os.path.isdir(self.etpConst['dumpstoragedir']): - os.makedirs(self.etpConst['dumpstoragedir']) - - f = open(tosaveinto,"w") - f.write(str(currmtime)) - f.flush() - f.close() - - - def __validateEntropyCache(self,maskfile,mtimefile): - - if os.getuid() != 0: # can't validate if running as user, thus cache shouldn't be loaded either - return - - # handle on-disk cache validation - # in this case, repositories cache - # if package.keywords is changed, we must destroy cache - if not os.path.isfile(mtimefile): - # we can't know if package.keywords has been updated - # remove repositories caches - self.__removeRepoCache() - self.__saveFileMtime(maskfile,mtimefile) - else: - # check mtime - try: - f = open(mtimefile,"r") - mtime = float(f.readline().strip()) - # compare with current mtime - try: - currmtime = os.path.getmtime(maskfile) - except OSError: - currmtime = 0.0 - if mtime != currmtime: - self.__removeRepoCache() - self.__saveFileMtime(maskfile,mtimefile) - except: - self.__removeRepoCache() - self.__saveFileMtime(maskfile,mtimefile) diff --git a/spritz/src/spritz.glade b/spritz/src/spritz.glade index c6218ae53..a68860239 100644 --- a/spritz/src/spritz.glade +++ b/spritz/src/spritz.glade @@ -2949,6 +2949,7 @@ True GTK_RELIEF_NORMAL True + @@ -3025,6 +3026,7 @@ True GTK_RELIEF_NORMAL True + @@ -3085,6 +3087,7 @@ True GTK_RELIEF_NORMAL True + @@ -3159,6 +3162,7 @@ True GTK_RELIEF_NORMAL True + diff --git a/spritz/src/spritz.py b/spritz/src/spritz.py index e2cb3f3b8..d1320c8d6 100644 --- a/spritz/src/spritz.py +++ b/spritz/src/spritz.py @@ -110,7 +110,7 @@ class SpritzController(Controller): task.start() def __runEditor(self, data): - os.system(data['cmd']) + os.system(data['cmd']+"&> /dev/null") delete = data['delete'] if delete and os.path.isfile(data['file']): try: @@ -122,22 +122,52 @@ class SpritzController(Controller): selection = self.filesView.view.get_selection() model, iterator = selection.get_selected() if model != None and iterator != None: - destination = model.get_value( iterator, 1 ) - source = model.get_value( iterator, 0 ) + identifier = model.get_value( iterator, 0 ) + destination = model.get_value( iterator, 2 ) + source = model.get_value( iterator, 1 ) source = os.path.join(os.path.dirname(destination),source) - return source, destination - return None,None + return identifier, source, destination + return 0,None,None + def on_filesDelete_clicked( self, widget ): + identifier, source, dest = self.__get_Edit_filename() + if not identifier: + return True + self.Equo.FileUpdates.remove_file(identifier) + self.filesView.populate(self.Equo.FileUpdates.scandata) + + def on_filesMerge_clicked( self, widget ): + identifier, source, dest = self.__get_Edit_filename() + if not identifier: + return True + self.Equo.FileUpdates.merge_file(identifier) + self.filesView.populate(self.Equo.FileUpdates.scandata) + + def on_mergeFiles_clicked( self, widget ): + self.Equo.FileUpdates.scanfs(dcache = True) + keys = self.Equo.FileUpdates.scandata.keys() + for key in keys: + self.Equo.FileUpdates.merge_file(key) + # it's cool watching it runtime + self.filesView.populate(self.Equo.FileUpdates.scandata) + + def on_deleteFiles_clicked( self, widget ): + self.Equo.FileUpdates.scanfs(dcache = True) + keys = self.Equo.FileUpdates.scandata.keys() + for key in keys: + self.Equo.FileUpdates.remove_file(key) + # it's cool watching it runtime + self.filesView.populate(self.Equo.FileUpdates.scandata) def on_filesEdit_clicked( self, widget ): - source, dest = self.__get_Edit_filename() - if source == None: + identifier, source, dest = self.__get_Edit_filename() + if not identifier: return True self.runEditor(source) def on_filesViewChanges_clicked( self, widget ): - source, dest = self.__get_Edit_filename() - if source == None: + identifier, source, dest = self.__get_Edit_filename() + if not identifier: return True randomfile = self.Equo.entropyTools.getRandomTempFile()+".diff" diffcmd = "diff -Nu "+dest+" "+source+" > "+randomfile @@ -681,18 +711,25 @@ class SpritzApplication(SpritzController,SpritzGUI): def setupEditor(self): - paths = self.Equo.entropyTools.collectLinkerPaths() pathenv = os.getenv("PATH") - for path in paths: - pathenv += ":"+path + if os.path.isfile("/etc/profile.env"): + f = open("/etc/profile.env") + env_file = f.readlines() + for line in env_file: + line = line.strip() + if line.startswith("export PATH='"): + line = line[len("export PATH='"):] + line = line.rstrip("'") + for path in line.split(":"): + pathenv += ":"+path + break os.environ['PATH'] = pathenv self.fileEditor = '/usr/bin/xterm -e $EDITOR' de_session = os.getenv('DESKTOP_SESSION') path = os.getenv('PATH').split(":") - # FIXME: disabled for now because it needs a properly configured environment - #if os.access("/usr/bin/xdg-open",os.X_OK): - # self.fileEditor = "/usr/bin/xdg-open" + if os.access("/usr/bin/xdg-open",os.X_OK): + self.fileEditor = "/usr/bin/xdg-open" if de_session.find("kde") != -1: for item in path: itempath = os.path.join(item,'kwrite') diff --git a/spritz/src/views.py b/spritz/src/views.py index c1754724e..fae6b54c5 100644 --- a/spritz/src/views.py +++ b/spritz/src/views.py @@ -575,31 +575,37 @@ class EntropyFilesView: def setup_view( self ): """ Create Notebook list for single page """ - model = gtk.TreeStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING ) + model = gtk.TreeStore( gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING ) self.view.set_model( model ) + cell0 = gtk.CellRendererText() + column0 = gtk.TreeViewColumn( "", cell0, markup = 0 ) + column0.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED ) + column0.set_fixed_width( 2 ) + self.view.append_column( column0 ) + cell1 = gtk.CellRendererText() - column1 = gtk.TreeViewColumn( _( "Proposed" ), cell1, markup = 0 ) + column1 = gtk.TreeViewColumn( _( "Proposed" ), cell1, markup = 1 ) column1.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED ) - column1.set_fixed_width( 220 ) + column1.set_fixed_width( 250 ) column1.set_resizable( True ) self.view.append_column( column1 ) cell2 = gtk.CellRendererText() - column2 = gtk.TreeViewColumn( _( "Destination" ), cell2, markup = 1 ) + column2 = gtk.TreeViewColumn( _( "Destination" ), cell2, markup = 2 ) column2.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED ) - column2.set_fixed_width( 330 ) + column2.set_fixed_width( 300 ) column2.set_resizable( True ) self.view.append_column( column2 ) cell3 = gtk.CellRendererText() - column3 = gtk.TreeViewColumn( _( "Rev." ), cell3, text=2 ) + column3 = gtk.TreeViewColumn( _( "Rev." ), cell3, text=3 ) column3.set_resizable( True ) column3.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED ) column3.set_fixed_width( 30 ) self.view.append_column( column3 ) model.set_sort_column_id( 0, gtk.SORT_ASCENDING ) - #self.view.get_selection().set_mode( gtk.SELECTION_MULTIPLE ) + self.view.get_selection().set_mode( gtk.SELECTION_SINGLE ) return model def populate( self, scandata ): @@ -607,7 +613,13 @@ class EntropyFilesView: keys = scandata.keys() keys.sort() for key in keys: - self.model.append(None,[os.path.basename(scandata[key]['source']),scandata[key]['destination'],scandata[key]['revision']]) + self.model.append(None,[ + key, + os.path.basename(scandata[key]['source']), + scandata[key]['destination'], + scandata[key]['revision'] + ] + ) class CategoriesView: def __init__( self, treeview,qview):