#-*- coding: utf-8 -*- # Copyright 2010 Calculate Ltd. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __version__ = "2.2.25" __app__ = "calculate-assemble" import os import re import sys import traceback from os import path from cl_template import template,iniParser from cl_utils import process,pathJoin,getRunCommands,getTupleVersion,isMount,\ isFstabMount,childMounts,_toUNICODE,cmpVersion, \ listDirectory, readFile, removeDir, getPkgInstalled, \ getTupleVersion, isPkgInstalled from subprocess import STDOUT,PIPE from cl_print import color_print from cl_datavars import DataVars from cl_distr import IsoDistributive, DirectoryDistributive, \ DistributiveError, PartitionDistributive, \ DistributiveRepository, ArchiveDistributive from cl_vars_share import varsShare from cl_lang import lang lang().setLanguage(sys.modules[__name__]) from server.utils import dialogYesNo import cl_install import cl_overriding import random from shutil import copyfile import time def DEBUG(msg): if "DEBUG" in os.environ: sys.stderr.write("%s\n"%msg) sys.stderr.flush() class printNoColor: def colorPrint(self,attr,fg,bg,string): sys.stdout.write(string) class AssembleError(Exception): """Installation Error""" assemble_errors = "" def installExit(self,*args,**kwars): raise AssembleError(self.__class__.assemble_errors) def overprintERROR(self,error): self.__class__.assemble_errors += str(error) + "\n" def getAssembleErrors(self): return self.__class__.assemble_errors def popAssembleErrors(self): res = self.__class__.assemble_errors self.__class__.assemble_errors = "" return res def getOverrideMethods(self): return self.installExit, self.overprintERROR cl_overriding.exit, cl_overriding.printERROR = \ AssembleError().getOverrideMethods() class DataVarsAssemble(DataVars): """Variable class for assemble""" def importAssemble(self, **args): '''Get variables for assemble''' # section name in calculate.env envSection = 'assemble' # import assemble variables self.importData(envSection, ('cl_vars_assemble','cl_fill_assemble')) class cl_assemble(color_print): """Primary class for assemble actions""" # action list for update distributive # step - step name # args - variable get by clVars and paste to command # command - executed command # condition - check this package name merged in emerge.log # message - Alternate message # progname - check by 'which' existing this program # hideout - hide stdout # foraction - perform only for cl_action == value DEFAULT_FORACTION = ('make','syncupdate','update') ACTION_LIST = \ [ # emerge -e system first {'command':'emerge -e system', 'message':_("First execute '%s'")%'emerge -e system', 'step':'firstsystem', 'foraction':('make',)}, # emerge -e system second {'command':'emerge -e system', 'message':_("Second execute '%s'")%'emerge -e system', 'step':'secondsystem', 'foraction':('make',)}, # emerge world {'command':'emerge -e world', 'step':'rebuildworld', 'foraction':('make',)}, {'step':'stagecomplete', 'foraction':('make',)}, # update prepareTemplates {'command':"prepareTemplates()", 'foraction':('syncupdate','update','applytemplates'), 'hideout':True, 'message':_("Configuring with %s templates")% "assemble" }, {'command':"_migratePortage()", 'foraction':('syncupdate',), 'step':"migrate", 'hideout':True, 'message':_("Checking portage repository") }, {'command':'eix-sync', 'progname':'eix-sync', 'message':_("Updating portages"), 'hideout':True, 'step':"eixsync", 'foraction':('syncupdate',)}, # try install perl {'command':'emerge -u perl', 'step':'updateperl', 'condition':'dev-lang/perl', 'checkcommand':'emerge -uOp perl' }, # update perl {'command':'perl-cleaner all', 'step':'fixperl', 'condition':'dev-lang/perl', 'progname':'perl-cleaner'}, # install meta package {'command':'emerge --noreplace calculate-meta', 'step':'meta'}, # update packages with fix newuse #{'command':'emerge -D --newuse world', # 'step':'newuse'}, # update world {'command':'emerge -uDN world', 'step':'update'}, # depclean {'command':'emerge --depclean', 'step':'depclean'}, # module rebuild {'command':'modulesRebuild()', 'step':'module', 'condition':'sys-kernel/.*source.*', 'message':_("Executing '%s'")%'module-rebuild -X rebuild', 'progname':'module-rebuild'}, # xorg module rebuild {'command':'emerge @x11-module-rebuild', 'step':'x11module', 'condition':'x11-base/xorg-server*'}, # revdep-rebuild {'command':'revdepRebuild()', 'step':'revdep', 'condition':'.', 'message':_("Executing '%s'")%'revdep-rebuild -i', 'progname':'revdep-rebuild'}, # emerge @preserved-rebuild {'command':'emerge @preserved-rebuild', 'step':'presrebuild', 'condition':'.' }, # prelink all packages {'command':'prelink -afmR', 'step':'prelink', 'hideout':True, 'condition':'.', 'progname':'prelink'}, # get propreitary drivers {'command':'fetchDrivers()', 'step':'fetchdrivers', 'message':_("Fetching %s")%'video drivers'}, # emerge all nvidia-drivers #{'command':'makeNvidiaDrivers()', # 'step':'nvidia', # 'hideout':True, # 'message':_("Assembling %s")%'nvidia-drivers'}, # binary cleaning {'command':'binaryCleaning()', 'step':'binclean', 'message':_("Cleaning the binary repository"), 'hideout':True }, # creating mask,unmask list {'command':'createMaskUnmaskList()', 'step':'maskunmask', 'message':_("Creating mask/unmask/use lists"), 'hideout':True }, # update eix base {'command':'eix-update', 'step':'eixupdate', 'hideout':True, 'progname':'eix-update'}, {'command':'eselect news read new', 'step':'readnews', 'message':_("Reading news"), 'progname':'eselect'}] reVerSplit = re.compile(r"^(.*?)-(([^-]+?)(?:-(r\d+))?)(?:.(tbz2))?$",re.S) def __init__(self): self.clVars = None self.startMessage = "" self.lenStartMessage = 0 self.clTempl = None self.force = False self.mainAction = None self.assembleEnvFile = '/etc/calculate/assemble.env' self.assemblePath = None def setNoColor(self): self.color = False def initVars(self): """Primary initialization of variables""" self.clVars = DataVarsAssemble() self.clVars.importAssemble() self.clVars.flIniFile() def applyConfigureTemplates(self,directory,message=None): """Apply templates for root of system.""" if message: self.printMessageForTest(message) self.clVars.Set("cl_chroot_path",directory, True) self.clTempl = template(self.clVars) dirsFiles = self.clTempl.applyTemplates() self.clTempl.closeFiles() if self.clTempl.getError(): raise AssembleError(self.clTempl.getError()) else: return dirsFiles def printMessageForTest(self, message, lenMsg=False): """Print waiting message and OK or Error by func result""" self.printByResult(True) message = "%s ..." % message self.printSUCCESS(message,printBR=False) self.startMessage = message if lenMsg: self.lenStartMessage = lenMsg else: self.lenStartMessage = self.lenString(self.startMessage) def printSkip(self, string, offsetL=0, printBR=True): """print skip""" self._printSysOut = sys.stdout self.printLine((('', string),), (('blueBr','['), ('yellowBr',' skipped '), ('blueBr',']'), ), offsetL, printBR) def printOnlyNotOK(self, string, offsetL=0, printBR=True): """Print for error""" self._printSysOut = sys.stdout self.printLine((('', string),), (('blueBr','['), ('redBr',' !! '), ('blueBr',']'), ), offsetL, printBR) def printByResult(self,result=True,failMessage=None,skip=False): if self.startMessage: offset = 3 if skip: self.printSkip(" ", self.lenStartMessage + offset) elif result: self.printOnlyOK(" ", self.lenStartMessage + offset) else: self.printOnlyNotOK(" ", self.lenStartMessage + offset) if failMessage: self.printERROR(failMessage) self.startMessage = "" self.lenStartMessage = 0 def setAction(self,action): if action == "break": self.clVars.Set("cl_action","break",True) elif action == "make": self.clVars.Set("cl_action","make",True) elif action == "update": self.clVars.Set("cl_action","update",True) elif action == "syncupdate": self.clVars.Set("cl_action","syncupdate",True) elif action == "dependence": self.clVars.Set("cl_action","dependence",True) elif action == "applytemplates": self.clVars.Set("cl_action","applytemplates",True) else: self.clVars.Set("cl_action","configure",True) def __profileShortname(self,profilename): return profilename.rpartition('/profiles/')[2] def printInfo(self): self.printSUCCESS(_("Preparing for assemble") + " Calculate Linux") self.defaultPrint("%s\n"%_("System information")) subname = self.clVars.Get('os_assemble_linux_subname') subname = (" %s"%subname) if subname else "" self.printSUCCESS(_("System profile")+": %s"% self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))) self.printSUCCESS(_("System to be built")+": %s"% self.clVars.Get('os_assemble_linux_name')+subname) if self.clVars.Get('os_assemble_linux_ver'): self.printSUCCESS(_("System version")+": %s"% self.clVars.Get('os_assemble_linux_ver')) self.printSUCCESS(_("Hardware type")+": %s"% self.clVars.Get('os_assemble_arch_machine')) if path.isdir(self.clVars.Get('os_assemble_root_dev')): self.printSUCCESS(_("Directory for assembling: %s")% self.clVars.Get('os_assemble_root_dev')) else: self.printSUCCESS(_("Partition for assemble: %s")% self.clVars.Get('os_assemble_root_dev')) self.printSUCCESS(_("File system: %s")% self.clVars.Get('os_assemble_root_format')) if self.clVars.Get('cl_assemble_sync'): self.printSUCCESS(_("Portage mirror: %s")% self.clVars.Get('cl_assemble_sync')) self.printSUCCESS(_("Stage for assembling: %s")% (self.clVars.Get('cl_assemble_image') or _("none"))) if self.clVars.Get('cl_assemble_image_type') == "stage" and \ self.clVars.Get('cl_assemble_branch') == '': self.printSUCCESS(_("Portage snapshot for assemble: %s")% (self.clVars.Get('cl_assemble_snapshot_portage') or _("none"))) self.defaultPrint("%s\n"%_("Checking up before assemble")) self.defaultPrint("\n") def printConfInfo(self): self.defaultPrint("%s\n"%_("System information")) subname = self.clVars.Get('os_assemble_linux_subname') subname = (" %s"%subname) if subname else "" self.printSUCCESS(_("System profile")+": %s"% self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))) self.printSUCCESS(_("System to be built")+": %s"% self.clVars.Get('os_assemble_linux_name')+subname) if self.clVars.Get('os_assemble_linux_ver'): self.printSUCCESS(_("System version")+": %s"% self.clVars.Get('os_assemble_linux_ver')) self.printSUCCESS(_("Hardware type")+": %s"% self.clVars.Get('os_assemble_arch_machine')) self.printSUCCESS(_("Partition for assemble: %s")% self.clVars.Get('os_assemble_root_dev')) self.printSUCCESS(_("The system is being assembled in: %s")% self.clVars.Get('cl_assemble_path')) self.defaultPrint("\n") def _checkAlreadyAssembling(self,printERROR=True): section = self.__sectionName() if not section in self.clVars.Get('cl_assemble_distro'): if printERROR: self.printERROR( _("System with '%s' profile not ready for assemble")% self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))) self.printERROR( _("Your system must be configured before you do this")+".") self.printERROR(_("Execute with option")+' "--configure".') if self.clVars.Get('cl_assemble_distro'): self.defaultPrint("\n"+_("Systems prepared for assemble")+ ":\n") for system in self.clVars.Get('cl_assemble_distro'): self.printSUCCESS(self.__profileShortname(system)) self.removeDistroInfo() return False return True def preassembleCheckups(self): if re.match(r'^i.86$',self.clVars.Get('os_arch_machine'),re.S): if self.clVars.Get('os_assemble_arch_machine') in ('x86_64','ia64'): self.printERROR( _("Unable to assemble the system %(what)s from %(from)s")% {'what':self.clVars.Get('os_assemble_arch_machine'), 'from':self.clVars.Get('os_arch_machine')}) return False dev = self.clVars.Get('os_assemble_root_dev') mp = isFstabMount(dev) if mp: self.printERROR( _("'%(dev)s' is used as '%(mp)s' on your current system")% {'dev':dev,'mp':mp}) return False if self._checkAlreadyAssembling(printERROR=False): dev = self.readEnv('os_assemble_root_dev') or dev mp = isMount(dev) self.printERROR( _("Distribution with profile %(profile)s is being assembled" " in '%(dir)s' now")% {'profile':self.__profileShortname( self.clVars.Get('os_assemble_system_profile')), 'dir':mp}) return False mp = isMount(dev) if mp: self.printERROR(_("'%(dev)s' already mounted to '%(mp)s'")% {'dev':dev,'mp':mp}) return False if not self.clVars.Get('cl_assemble_image'): self.printERROR(_("Base stage not found. Try " "to change '--source'.")) return False return True def _askUser(self,force,question): """Ask user about continue""" if not force: dialogMessage = question + " (yes/no)" try: dialogRes = dialogYesNo(dialogMessage) except KeyboardInterrupt: self.defaultPrint("\n") raise KeyboardInterrupt if dialogRes in (None,False): return False return True # configure helper functions def _unpackPortage(self): """Unpack portage""" stageName = self.clVars.Get('cl_assemble_snapshot_portage') self.printMessageForTest(_("Unpacking portages")) if stageName: portageSources = ArchiveDistributive(stageName) portageTarget = DirectoryDistributive( path.join(self.assemblePath,"usr")) portageTarget.installFrom(portageSources) self.printByResult(True) else: self.printByResult(skip=True) def _formatAndUnpackStage(self): """Format partition for assemble and unpack stage""" self.printMessageForTest(_("Formatting the partition")) self.saveVars('os_assemble_root_dev') self.targetDistr.performFormat() self.printMessageForTest(_("Unpacking the stage image to target")) self.saveVars('os_assemble_root_dev') self.targetDistr.installFrom(self.sourceDistr) self.assemblePath = \ self.targetDistr.convertToDirectory().getDirectory() self.clVars.Set('cl_assemble_path', self.assemblePath, True) self.saveVars('os_assemble_linux_shortname', 'os_assemble_linux_ver', 'os_assemble_arch_machine', 'cl_assemble_image', 'os_assemble_root_dev', 'cl_assemble_path', 'cl_assemble_sync', 'cl_assemble_branch', 'cl_assemble_buildpkg_set', 'cl_assemble_pkgdir') def _getTarget(self): rootPartdev = self.clVars.Get('os_assemble_root_dev') formatId = PartitionDistributive.formatId fileSystem = self.clVars.Get('os_assemble_root_format') if rootPartdev.startswith('/dev'): return PartitionDistributive(rootPartdev, mdirectory=self.clVars.Get('cl_assemble_path'), check=True, fileSystem=fileSystem, isFormat=True, systemId=formatId.get(fileSystem,"83"), flagRemoveDir=False, rootLabel="%s-%s"% (self.clVars.Get('os_assemble_linux_shortname'), self.clVars.Get('os_assemble_linux_ver'))) else: return DirectoryDistributive(rootPartdev, mdirectory=self.clVars.Get('cl_assemble_path')) def _prepareMount(self): """Mount /proc,/sys, remote, /dev to chroot""" mountResources = (("/dev",None,None), ("/dev/shm",None,None), ("/dev/pts",None,None), (None,"-t proc","/proc"), (None,"-t sysfs","/sys"), ("/var/calculate/remote",None,None)) for source,opts,target in mountResources: opts = opts or "-o bind" target = target or source self.printMessageForTest(_("Mounting %s")%(source or target)) target = pathJoin(self.assemblePath,target) if not path.exists(target): os.makedirs(target,mode=0755) if source == isMount(target): continue args = ["mount"]+opts.split()+[str(source).lower(),target] mountProcess = process(*args) if mountProcess.failed(): raise AssembleError(_("Failed to mount %(from)s to %(to)s")% {'from':source,'to':target}) if self.targetDistr: DirectoryDistributive(target,parent=self.targetDistr) self.printByResult(True) def _migratePortage(self): if self.clVars.Get('cl_assemble_branch'): if not isPkgInstalled('dev-vcs/git'): self.printMessageForTest(_("Installing %s")%'dev-vcs/git') self.runChroot("emerge -1 git") portagePath = pathJoin(self.assemblePath,'usr/portage') gitConfig = pathJoin(portagePath, '.git/config') # check for repository contains .git and # this git from cl_assemble_sync url reUrl = re.compile('url\s*=\s*(.*)') gitUrl = reUrl.search(readFile(gitConfig)) # need remove portage and reget from sync address self.printMessageForTest(_("Fetching portages")) if not gitUrl or \ gitUrl.group(1).strip() != self.clVars.Get('cl_assemble_sync'): if path.exists(portagePath): removeDir(portagePath) getPortage = "git clone --depth 1 -n {gitrep} {portage}".format( gitrep=self.clVars.Get('cl_assemble_sync'), portage='/usr/portage') self.runChroot(getPortage) else: getPortage = "cd {portage};git fetch".format( gitrep=self.clVars.Get('cl_assemble_sync'), portage='/usr/portage') self.runChroot(getPortage) updateBranch= "cd {portage};git checkout {branch}".format( portage='/usr/portage', branch=self.clVars.Get('cl_assemble_branch')) self.runChroot(updateBranch) portagePkg = getPkgInstalled('sys-apps/portage', prefix=self.assemblePath) portageMinVer = getTupleVersion('2.2.0_alpha72') if portagePkg and \ getTupleVersion(portagePkg[0]['PVR']) < portageMinVer: self.printMessageForTest(_("Installing %s")%"portage") emergePortage = \ 'ebuild /usr/portage/sys-apps/portage/portage-9999.ebuild manifest' self.runChroot(emergePortage) emergePortage = \ 'ACCEPT_KEYWORDS="**" emerge \\1: command += " -G %s"%",".join(groups[1:]) if comment: command += " -c '%s'"%comment if shell: command += " -s %s"%shell self.runChroot(command) try: os.makedirs(pathJoin(prefix,home),mode=mode) os.chown(pathJoin(prefix,home),chown[0],chown[1]) except (OSError,IOError),e: raise AssembleError( _("Failed to create the home directory for %s") %username) def groupAdd(self,groupid,groupname): """Check exists group and create new""" if self.runChroot("groupmems -l -g %s" %groupname,raiseError=False).failed(): self.printMessageForTest( _("Creating %(name)s (%(id)d) group")% {'name':groupname,'id':groupid}) self.runChroot("groupadd -g %d %s"%(groupid,groupname)) self.printByResult(True) def _removeFiles(self,*files,**kwarg): """Remove files specified by files list""" prefix = kwarg.get("prefix","/") errormsg = kwarg.get("errormsg",None) try: rmFile = "" for fileName in files: rmFile = pathJoin(prefix,fileName) if path.lexists(rmFile): os.unlink(rmFile) except (OSError,IOError),e: if errormsg is None: raise AssembleError(_("Cannot remove '%s'")%rmFile) else: raise AssembleError(errormsg) def _getCommand(self,commandlist): def decodeCmd(x): x = x.rpartition(";")[2] if " " in x: return '"%s"'%x else: return x return " ".join(map(decodeCmd,commandlist)) def setSyncMirror(self,mirror): """Set sync mirror""" reMirror = re.compile("^(rsync:|git:)?/?/?([^:]+)$",re.S) res = reMirror.search(mirror) if res: if res.groups()[0] == "git:": self.clVars.Set('cl_assemble_sync',"git://%s"%res.groups()[1],True) else: self.clVars.Set('cl_assemble_sync',"//%s"%res.groups()[1],True) return True else: return False def runChroot(self,command,raiseError=True,showProcess=False,joinErr=False): """Run command in chroot specified by cl_assemble_path""" try: if showProcess: IOval = None else: IOval = PIPE if joinErr: ERRval = STDOUT else: ERRval = IOval envdict = {'CHROOT':"on"} envdict.update(os.environ) needAsk = self.clVars.Get('cl_assemble_ask_set') == "on" if "emerge " in command: command = "env-update &>/dev/null;" \ "source /etc/profile &>/dev/null;%s"%command if showProcess and needAsk: command = command.replace("emerge ","emerge -a ") commandLine = ["chroot",self.clVars.Get('cl_assemble_path'), "/bin/bash","-c",command] curarch = self.clVars.Get('os_arch_machine') buildarch = self.clVars.Get('os_assemble_arch_machine') if curarch != buildarch: if buildarch == "i686": commandLine = ["linux32"] + commandLine if showProcess and needAsk: chrootCommand = process(*commandLine,stderr=ERRval, stdin=None,stdout=IOval,envdict=envdict) else: chrootCommand = process(*commandLine,stderr=ERRval, stdout=IOval,envdict=envdict) DEBUG(self._getCommand(chrootCommand.command)) if raiseError and chrootCommand.failed(): raise AssembleError( _("An error occurred when executing the command")+ ":\n %s"%self._getCommand(chrootCommand.command)) except KeyboardInterrupt: chrootCommand.kill() self.defaultPrint("\b\b") raise AssembleError( _("Interrupted when executing the command")+ ":\n %s"%self._getCommand(chrootCommand.command)) return chrootCommand def configureSystem(self,force,nounmount): """Unpack stage or cls|css and prepare for assemble""" self.msgOperationComplete = "" self.msgOperationFailed = \ _("Failed to prepare the system for assemble") if not self._pidCheck(): return False res = self.make(self.configureFunc,force,nounmount) if res: self.printSUCCESS( _("System prepared for assemble in %s")% self.clVars.Get('cl_assemble_path')+"!") self.printSUCCESS(_("For furhter build, use the 'cl-make' command")) return res def breakFunc(self,force): mp = self.clVars.Get('cl_assemble_path') rootPartdev = self.clVars.Get('os_assemble_root_dev') if not self._checkAlreadyAssembling(): return False self.printSUCCESS(_("Assemble interrupted") + " Calculate Linux") self.printConfInfo() if not self._askUser(force, _("Interrupt system assemble")): self.printERROR(_("Assemble resumed")) return False if mp: mps = filter(lambda x:x!=mp,map(lambda x:x[1],childMounts(mp))) for target in sorted(mps, reverse=True): self.printMessageForTest(_("Unmounting %s")%(target[len(mp):])) umountProcess = process("umount",target) if umountProcess.failed(): raise AssembleError(_("Cannot unmount %s")%target) self.printByResult(True) self.targetDistr = PartitionDistributive(rootPartdev, mdirectory='/mnt/builder',flagRemoveDir=False) dd = DirectoryDistributive(mp,parent=self.targetDistr) return True def checkDependence(self): rootPartdev = self.clVars.Get('os_assemble_root_dev') mp = isMount(rootPartdev) if not self._checkAlreadyAssembling(): return False self.printSUCCESS(_("Checking dependencies of %s assemble") % "Calculate Linux") self.printConfInfo() command = "emerge -puNv %s %s"%(self.clVars.Get('cl_assemble_meta'), "world") self.printSUCCESS(_("Checking dependencies")+ " ...") if self.runChroot(command, showProcess=True, raiseError=False).success(): self.printSUCCESS(_("Distribution with profile %(profile)s " "is ready for compilation")% {'profile':self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))}+"!") return True else: self.printSUCCESS(_("Distribution with profile %(profile)s " "has unresolved dependencies")% {'profile':self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))}) return False def breakAssembling(self,force): self.msgOperationComplete = \ _("System assemble resumed")+"!" self.msgOperationFailed = \ _("Failed to interrupt assemble correctly") if not self._pidCheck(): return False return self.make(self.breakFunc,force) def _pidCheck(self): """Check pid for run""" if str(os.getpid()) != self.clVars.Get('cl_assemble_pid'): self.printERROR(_("Already assembling")+" "+ self._getNameByAction() + " " + _("of distribution with profile '%(profile)s'")% {'profile':self.__profileShortname( self.clVars.Get('os_assemble_system_profile'))}) return False else: self.saveVars('cl_assemble_pid') return True def makeSystem(self,force): self.msgOperationComplete = \ _("System successfully assembled")+"!" self.msgOperationFailed = \ _("System assemble failed") if not self._pidCheck(): return False return self.make(self.makeFunc,force,True,False) def updateSystem(self,force,withsync=True): if self.clVars.Get('cl_action') == "applytemplates": self.msgOperationComplete = \ _("Templates successfully applied")+"!" self.msgOperationFailed = \ _("Failed to apply templates") else: self.msgOperationComplete = \ _("System successfully assembled")+"!" self.msgOperationFailed = \ _("System assemble failed") if not self._pidCheck(): return False stepWorld = filter(lambda x:x, self.clVars.Get('cl_assemble_step_world').split(',')) imageType = self.clVars.Get('cl_assemble_image_type') if imageType == 'stage' and \ not filter(lambda x:x in ("stagecomplete","finish"),stepWorld): self.printERROR( _("Unable to update the distribution: assemble not completed")) self.printERROR(_("Use '%s' for assemble")%'cl-make -m') return False return self.make(self.makeFunc,force,False,withsync) def _getNameByAction(self): act = self.clVars.Get('cl_assemble_make') if act == "configure": return _("for configuration") elif act == "break": return _("for breaking the assemble") elif act == "system": return _("for compilation of system packages") elif act != "": return _("for package compilation") else: return "" def makeFunc(self,force,forcesystem=False,makeSync=True): rootPartdev = self.clVars.Get('os_assemble_root_dev') mp = isMount(rootPartdev) if not self._checkAlreadyAssembling(): return False if forcesystem: self.printSUCCESS(_("Compiling %s assemble") % "Calculate Linux") else: self.printSUCCESS(_("Updating %s assemble") % "Calculate Linux") self.printConfInfo() self.defaultPrint("%s\n"%_("Checking up before compilation")) if self.clVars.Get('cl_assemble_make') == 'configure': self.printWARNING(_("WARNING") +": " + _("assemble configuration was not completed")) # if assembling completed (finish in cl_assemble_step_world) if "finish" in self.clVars.Get('cl_assemble_step_world'): # cancel if action make if forcesystem: return True elif self.clVars.Get('cl_action') != "applytemplates": # print warning and drop force option self.printWARNING(_("WARNING") +": " + _("assemble already finished")) # if base stage is stage4(iso) display warning for make if self.clVars.Get('cl_assemble_image_type') == 'iso' and \ forcesystem: self.printERROR(_("WARNING") +": " + _("system packages will be recompiled")) self.defaultPrint("\n") self._displayCompileAll(self.clVars.Get('cl_action'), self.clVars.Get('cl_assemble_step_world')) self.defaultPrint("\n") if not self._askUser(force, _("Continue compiling system packages")): self.printERROR(_("Compilation interrupted")) return False self.mainAction = self.clVars.Get('cl_action') if self.mainAction in ('make','update','syncupdate'): if not force: self.clVars.Set('cl_assemble_ask_set', 'on', True) self.assemblePath = self.clVars.Get('cl_assemble_path') if "finish" in self.clVars.Get('cl_assemble_step_world'): self.writeVar('cl_assemble_step_world','stagecomplete',True) if self.clVars.Get('cl_assemble_make') == 'configure': self.writeVar('cl_assemble_make','',True) makeComplete = False baseType = self.clVars.Get('cl_assemble_image_type') getMake = lambda : self.clVars.Get('cl_assemble_make') while not makeComplete: if getMake() in ("world",""): self._compileAll(self.mainAction) self.writeVar('cl_assemble_make','') makeComplete = True else: self.writeVar('cl_assemble_make','') return True def _printCheckExecute(self,command,checkBuild=False,msg=None, hideOut=False): if self.clVars.Get('cl_assemble_make') \ and command.startswith("emerge"): origCommand = command if self.clVars.Get('cl_assemble_skipfirst_set') == "on": command = "emerge --resume --skipfirst" else: command = "emerge --resume" msg = (_("Resuming '%(orig)s' by '%(exec)s'")% {'orig':origCommand, 'exec':command}) else: msg = msg or (_("Executing '%s'")%command) self.writeVar('cl_assemble_make','world') if checkBuild == False or (type(checkBuild) == str \ and not self.__isPackageBuilded(re.compile(checkBuild))): self.printMessageForTest(msg) self.printByResult(True,skip=True) else: if hideOut: self.printMessageForTest(msg) else: self.printSUCCESS("-"*76) self.printSUCCESS(msg + " ...") self.printSUCCESS("-"*76) if re.search(r"^\w+\(\)$",command,re.S): getattr(self,command[:-2])() else: self.runChroot(command, showProcess=not hideOut) self.printByResult(True) self.writeVar('cl_assemble_make','') def __isAnyPackageBuilded(self): """Any package was builded (detect by log)""" logFile = pathJoin(self.clVars.Get('cl_assemble_path'), '/var/log/emerge.log') reEmerge = re.compile(r"^\d+:\s*>>>\s*emerge",re.S) if not os.access(logFile,os.R_OK): return False return bool(filter(reEmerge.search,open(logFile,"r"))) def __isPackageBuilded(self,package): """'package' was builded (detect by log)""" logFile = pathJoin(self.clVars.Get('cl_assemble_path'), '/var/log/emerge.log') reEmerge = re.compile(r"^\d+:\s*>>>\s*emerge[^/]+\s+(\S+/\S+)") if not os.access(logFile,os.R_OK): return False packageWithVer = map(lambda x:x.groups()[0], filter(lambda x:x, map(reEmerge.search, open(logFile,"r")))) if type(package) == re._pattern_type: return bool(filter(package.search,packageWithVer)) else: return bool(filter(lambda x:package in x,packageWithVer)) def _checkChrootProgram(self,progname): """Check existing program by name""" if self.runChroot("which %s"%progname,raiseError=False).failed(): return False return True def _compileAll(self,actionName): dontRepeatCompleted = bool(actionName == "make") """World compiling""" # try perform each action from action list for action in self.ACTION_LIST: # if specified "progname" check by which in chroot this prog if "progname" in action: if not self._checkChrootProgram(action["progname"]): continue if not actionName in action.get('foraction',self.DEFAULT_FORACTION): continue if "command" in action: command = action["command"] if "args" in action: command = command % tuple(map(lambda x:self.clVars.Get(x), action["args"])) if dontRepeatCompleted and action["step"] in \ self.clVars.Get('cl_assemble_step_world'): continue checkBuild = action.get("condition",True) if "checkcommand" in action: process = \ self.runChroot(action["checkcommand"],raiseError=False) checkBuild = bool(re.search(action.get("condition","."), process.read(),re.S)) self._printCheckExecute(command,checkBuild=checkBuild, msg=action.get("message",""), hideOut=action.get("hideout",False)) if "step" in action: self._appendToStep("world",action["step"]) self._appendToStep("world","finish") def _displayCompileAll(self,actionName,stepWorld): dontRepeatCompleted = bool(actionName == "make") """World compiling""" # try perform each action from action list self.defaultPrint(_("The following actions will be performed")+":\n") showLegend=False for action in self.ACTION_LIST: if not "command" in action: continue # if specified "progname" check by which in chroot this prog if not actionName in action.get('foraction',self.DEFAULT_FORACTION): continue command = action["command"] if "args" in action: command = command % tuple(map(lambda x:self.clVars.Get(x), action["args"])) suffix = "" if "condition" in action and not "checkcommand" in action: suffix += "*" showLegend = True if dontRepeatCompleted and action["step"] in stepWorld: suffix += " (%s)" % _("done") self.printSUCCESS(action.get("message", _("Executing '%s'")%command)+ suffix) if showLegend: self.defaultPrint( _("Actions marked with '*' will be performed when needed")+ ".\n") def __sectionName(self): """Get section name of assemble.env by shortname and arch""" return self.clVars.Get( 'os_assemble_system_profile').rpartition('/profiles/')[2] def writeVar(self,varname,varvalue,setvar=True): """Write variable to assemble env file""" assembleEnv = iniParser(self.assembleEnvFile) if setvar: self.clVars.Set(varname,varvalue,True) return assembleEnv.setVar(self.__sectionName(),{varname:varvalue}) def readEnv(self,varname): """Read variable from assemble env file""" assembleEnv = iniParser(self.assembleEnvFile) return _toUNICODE(assembleEnv.getVar(self.__sectionName(), varname)).encode('utf-8') def saveVars(self,*varsname): """Save vars with it current values""" assembleEnv = iniParser(self.assembleEnvFile) return assembleEnv.setVar(self.__sectionName(), dict(map(lambda x:(x,self.clVars.Get(x)),varsname))) def _cleanEnv(self,assembleEnv): """Clean env, remove empty section, remove empty file""" # if file hasn't any section if not assembleEnv.getAllSectionNames(): if not assembleEnv.getAllSectionNames(): if not assembleEnv.getAllSectionNames(): os.unlink(self.assembleEnvFile) # if env has empty section, then remove it elif self.__sectionName() in assembleEnv.getAllSectionNames() and \ not assembleEnv.getAreaVars(self.__sectionName()): assembleEnv.delArea(self.__sectionName()) def removeDistroInfo(self): assembleEnv = iniParser(self.assembleEnvFile) assembleEnv.delArea(self.__sectionName()) self._cleanEnv(assembleEnv) def removeVars(self,*varsname): """Remove vars specified by varsname""" res = True assembleEnv = iniParser(self.assembleEnvFile) for var in varsname: res = res and assembleEnv.delVar(self.__sectionName(),var) self._cleanEnv(assembleEnv) return bool(res) def _getStepCount(self,stepname): """Get value of variable as number""" val = self.clVars.Get("cl_assemble_step_%s"%stepname) if val.isdigit(): return int(val) else: return 0 def _appendToStep(self,stepname,newaction): """Append action to step""" curval = self.clVars.Get('cl_assemble_step_%s'%stepname) curval = filter(lambda x:x,map(lambda x:x.strip(),curval.split(','))) if newaction in curval: return curval if curval: curval.append(newaction) else: curval = [newaction] return self.writeVar("cl_assemble_step_%s"%stepname,",".join(curval)) def _incStepClearMake(self,stepname): """Increase make step, specified by stepname, and clear make""" self.writeVar('cl_assemble_make','') return self.writeVar("cl_assemble_step_%s"%stepname, str(self._getStepCount(stepname) + 1)) def make(self,logicFunc,*argv): """Make iso image by variables""" self.sourceDistr = None self.targetDistr = None error = None try: try: if not logicFunc(*argv): return False except KeyboardInterrupt: raise KeyboardInterrupt except (EOFError), e: error = e except (AssembleError,DistributiveError),e: error = e except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.defaultPrint("\b\b") self.printByResult(False) self.printWARNING(_("System assemble interrupted")) error = _("System assemble manually interrupted") try: if self.clTempl: self.clTempl.closeFiles() if error or logicFunc == self.breakFunc: self.printByResult(False) if self.targetDistr: self.removeDistroInfo() if self.targetDistr.childs: self.printMessageForTest( _("Releasing the partition for assemble")) assemblePath = self.clVars.Get('cl_assemble_path') self.targetDistr.close() if path.exists(assemblePath): try: os.rmdir(assemblePath) except OSError,e: pass self.printByResult(True) if self.sourceDistr and self.sourceDistr.childs: self.printMessageForTest(_("Releasing source data")) self.sourceDistr.close() self.printByResult(True) except (AssembleError,DistributiveError),e: if error: error = "%s\n%s" % (str(error),_("Unmounting error")) else: error = _("Unmounting error") except KeyboardInterrupt,e: self.defaultPrint("\b\b") error = _("Unmounting error") try: if error: self.printByResult(False) if error: map(self.printERROR,filter(lambda x: x,str(error).split('\n'))) self.printERROR(self.msgOperationFailed) #self.removeVars('cl_assemble_pid') return False if self.msgOperationComplete: self.printSUCCESS(self.msgOperationComplete) #self.removeVars('cl_assemble_pid') except KeyboardInterrupt,e: return False return True def revdepRebuild(self): """Run revdep-rebuild and check result""" cmd = self.runChroot("revdep-rebuild -i", showProcess=True) if not self.assemblePath: self.assemblePath = \ self.clVars.Get('cl_assemble_path') statusFile = path.join(self.assemblePath, "var/cache/revdep-rebuild/6_status.rr") if path.exists(statusFile) and \ open(statusFile,'r').read().strip() != '0': raise AssembleError( _("An error occurred when executing the command")+ ":\n %s"%self._getCommand(cmd.command)) def modulesRebuild(self): """Run revdep-rebuild and check result""" if not self.assemblePath: self.assemblePath = \ self.clVars.Get('cl_assemble_path') modulesFile = path.join(self.assemblePath, "var/lib/module-rebuild/moduledb") # if file exists and not empty if path.exists(modulesFile) and open(modulesFile,'r').read().strip(): cmd = self.runChroot("module-rebuild -X rebuild", showProcess=True) if cmd.failed(): raise AssembleError( _("An error occurred when executing the command")+ ":\n %s"%self._getCommand(cmd.command)) def setProfile(self,newprofile,isconfigure): """Set profile for assembling system""" newprofile = newprofile or "" # if $ at end of newprofile then it be at end of profile name if newprofile.endswith("$"): newprofile = newprofile[:-1] reProfile = re.compile('(^|/)%s$'% "/([^/]+/)*".join(newprofile.strip('/').split('/')),re.S|re.I) else: reProfile = re.compile('(^|/)%s(/|$)'% "/([^/]+/)*".join(newprofile.strip('/').split('/')),re.S|re.I) allProfile = self.clVars.Get('cl_assemble_distro') if isconfigure: allProfile = self.clVars.Get('cl_assemble_profile') allProfile = list(set(allProfile)) likeProfile = filter(reProfile.search,allProfile) if likeProfile > 2: if newprofile in likeProfile: likeProfile = [newprofile] if len(likeProfile) != 1: if isconfigure: typeProfileList = _("profile symlink targets") else: typeProfileList = _("distributions for assemble") if newprofile != 'list': if not likeProfile: self.printERROR(_("wrong value for '--profile'")) self.printERROR( _("specify '-p list' to print all available %s")% typeProfileList ) return False else: self.printERROR( _("The specified value of '--profile' is ambiguous. " "Please specify the profile with more precision.")) self.defaultPrint(_("Select profile from")+":\n") else: likeProfile = allProfile if likeProfile: self.defaultPrint( (_("Available %s")%typeProfileList)+":\n") elif not isconfigure: self.printERROR(_("No distribution to assemble")) map(self.printSUCCESS,sorted(likeProfile)) return False else: newprofile = likeProfile[0] newprofile = self._shortToLongProfileName(newprofile) self.clVars.Set('os_assemble_system_profile',newprofile,True) return True def getValidSource(self): """Get valid sources""" distRep = DistributiveRepository( self.clVars.Get('cl_assemble_image_path')) return distRep._getAvailableShortnames() def setName(self,name): """Set name for assembling system""" reRight = re.compile( r"^([%(alnum)s]+)(?:/([%(alnum)s ]+)(?:/([%(alnum)s]*))?)?$"% {'alnum':"A-Za-z0-9"}) res = reRight.search(name) if res: shortname,name,subname = res.groups() if not shortname is None: self.clVars.Set('os_assemble_linux_shortname',shortname,True) if not name is None: self.clVars.Set('os_assemble_linux_name',name,True) if not subname is None: self.clVars.Set('os_assemble_linux_subname',subname,True) return True return False def _shortToLongProfileName(self,newprofile): """Convert short profile name to full name""" if newprofile.startswith("calculate"): return path.join("../var/lib/layman/calculate/profiles", newprofile) else: return path.join("../usr/portage/profiles", newprofile) def checkVariables(self,printVars=None): """Check and fix variables values""" def printVarError(varname): self.printERROR(_("Wrong value in '%(var)s' variable: '%(val)s'")% {'var':varname, 'val':self.clVars.Get(varname)}) discardEmpty = lambda x : filter(lambda y:y,x) sync = self.clVars.Get('cl_assemble_sync') if sync and not self.setSyncMirror(sync) and not printVars: printVarError('cl_assemble_sync') return False profile = self.clVars.Get('os_assemble_system_profile') profilesFullname = map(self._shortToLongProfileName, self.clVars.Get('cl_assemble_profile')) profilesFullname += map(lambda x:x[2:],profilesFullname) if profile in profilesFullname: if profile[0] == '/': self.clVars.Set('os_assemble_system_profile',"..%s"%profile, True) elif not printVars and profile: printVarError('os_assemble_system_profile') return False availableDev = self.clVars.Get('cl_assemble_available_dev').split(',') availableDev = discardEmpty(availableDev) osDiskDev = self.clVars.Get('os_disk_dev') if availableDev: badDevs = filter(lambda x:not x in osDiskDev,availableDev) if badDevs: printVarError('cl_assemble_available_dev') self.printERROR(_("Device '%s' does not exist")%badDevs[0]) return False return True def tryUseAvailable(self): """Check free available device and set valut to os_assemble_root_dev""" distros = self.clVars.Get('cl_assemble_distro') assembleEnv = iniParser(self.assembleEnvFile) discardEmpty = lambda x : filter(lambda y:y,x) busyDevs = \ discardEmpty( map(lambda x:assembleEnv.getVar(x,'os_assemble_root_dev'), distros)) discardBusy = lambda x : filter(lambda y:not (x in busyDevs or isMount(y)),x) availableDev = self.clVars.Get('cl_assemble_available_dev').split(',') availableDev = discardEmpty(availableDev) freeDev = discardBusy(availableDev) if freeDev: rootDev = random.choice(freeDev) self.clVars.Set('os_assemble_root_dev',rootDev,True) return True return False def getCurrentNvidiaBinary(self): """Get versions already installed nvidia drivers""" packagePath = \ path.join(self.clVars.Get('cl_assemble_path'), 'usr/portage/packages') x11DriversPath = path.join(packagePath,'x11-drivers') if not path.exists(x11DriversPath): return [] return map(lambda x:x.groups()[1], filter(lambda x:x, map(self.reVerSplit.search, os.listdir(x11DriversPath)))) def fetchDrivers(self): """Fetch propreitary drivers""" if self.clVars.Get('cl_assemble_withvideo_set') == "on": drivers = [ ('nvidia-drivers', 'x11-drivers/nvidia-drivers'), ('nvidia-drivers', '\\= 0 pkgCategory = "x11-drivers" pkgName = "%s/nvidia-drivers"%pkgCategory chrootPath = self.clVars.Get('cl_assemble_path') varDbPath = path.join(chrootPath,'var/db/pkg') x11DriversPath = path.join(varDbPath,'x11-drivers') # if system has not nvidia-drivers then nvidia will not be updated if not path.exists(x11DriversPath) or \ not filter(lambda x:x.startswith('nvidia-drivers'), os.listdir(x11DriversPath)): self.printByResult(skip=True) return True pkgDir = '/usr/portage/packages' pathPackages = pathJoin(chrootPath,pkgDir,"Packages") if self.startMessage: self.startMessage = "" self.defaultPrint("\n") # get version list of installed binary nvidia-drivers allInstalled = self.getCurrentNvidiaBinary() if self.__isPackageBuilded(re.compile('sys-kernel/.*source.*')): removeNvidiaByVer(chrootPath,pkgDir,pkgName,allInstalled) allInstalled = [] drivers = (('96.XX.XX','97'), ('173.XX.XX','174')) needRegenPackages = False for verName,drvVer in drivers: self.printMessageForTest(" " + _("Assembling %s")%"nvidia-drivers-%s"%verName) # run verbose package emergin for get version checkprocess = self.runChroot( "emerge -vp \<%s-%s"% (pkgName,drvVer),raiseError=False,joinErr=True) rePackage = re.compile("^\[ebuild[^\]]+]\s+(\S+)") # get version from emerging nvidia-driver nvidiaVersions = \ map(lambda x:x.groups()[1], filter(lambda x:x, map(self.reVerSplit.search, map(lambda x:x.groups()[0], filter(lambda x:x, map(rePackage.search, checkprocess)))))) # nvidia-driver for this version absent if not nvidiaVersions: self.printByResult(False) continue nvidiaVersion = nvidiaVersions[0] # get version for this version range verInstall = filter(lambda x:verLt(x,drvVer), allInstalled) # discard this allInstalled = filter(lambda x:verGe(x,drvVer), allInstalled) # if package not newer if verInstall: if filter(lambda x:verGe(x,nvidiaVersion),verInstall): self.printByResult(skip=True) continue # remove old version else: removeNvidiaByVer(chrootPath,pkgDir,pkgName,verInstall) # remove package if it exists needRegenPackages = True # build binary process = self.runChroot("PKGDIR='%s' emerge -B \<%s-%s"% (pkgDir,pkgName,drvVer),raiseError=False) self.printByResult(process.success()) if needRegenPackages: self.regenPackages(chrootPath,pkgDir) return True def regenPackages(self,chrootPath,pkgDirPath): """Regenerate packages and clean SYNC param""" def fixKeywords(s): if s.startswith("KEYWORDS:"): return "KEYWORDS: amd64 x86\n" else: return s pathPackages = pathJoin(chrootPath,pkgDirPath,"Packages") # remove Packages if it recreated if path.exists(pathPackages): os.unlink(pathPackages) self.runChroot("PKGDIR='%s' emaint binhost"%pkgDirPath) if path.exists(pathPackages): # remove SYNC param filtredPackages = \ map(fixKeywords, filter(lambda x:not x.startswith("SYNC:"), open(pathPackages,'r'))) open(pathPackages,'w').writelines(filtredPackages) def binaryCleaning(self): """Clean binary repository""" chrootPath = self.clVars.Get('cl_assemble_path') pkgDir = pathJoin(chrootPath, self.clVars.Get('cl_assemble_pkgdir')) dbPkg = pathJoin(chrootPath, 'var/db/pkg') try: if not path.exists(dbPkg): os.makedirs(dbPkg) if not path.exists(pkgDir): os.makedirs(pkgDir) if path.exists(dbPkg) and path.exists(pkgDir): # get pkg list from distro pkgList = \ reduce(lambda x,y:x+y, map(lambda x:map(lambda z:path.join(x,"%s.tbz2"%z), os.listdir(path.join(dbPkg,x))), os.listdir(dbPkg)),[]) # get binary packages binList = \ reduce(lambda x,y:x+y, map(lambda x:map(lambda z:path.join(x,z)[len(pkgDir)+1:], os.listdir(path.join(x))), filter(lambda x:path.isdir(x), map(lambda x:path.join(pkgDir,x), os.listdir(pkgDir)))),[]) # remove files which in binary and not in db/pkg map(lambda x:os.unlink(x), map(lambda x:pathJoin(pkgDir,x), list(set(binList)-set(pkgList)))) # remove empty directories map(lambda x:os.rmdir(x), filter(lambda x:path.isdir(x) and not os.listdir(x), map(lambda x:path.join(pkgDir,x), os.listdir(pkgDir)))) #packagesDir = 'usr/portage/packages' #x11_drivers = 'x11-drivers' #nvidiaDir = pathJoin(chrootPath, packagesDir,x11_drivers) #pkgDirX11Drivers = pathJoin(pkgDir,'x11-drivers') #if not path.exists(pkgDirX11Drivers): # os.makedirs(pkgDirX11Drivers,mode=0755) #map(lambda x:copyfile(pathJoin(nvidiaDir,x), # pathJoin(pkgDirX11Drivers,x)), # listDirectory(nvidiaDir)) self.regenPackages(chrootPath,pkgDir[len(chrootPath):]) else: self.printByResult(skip=True) except OSError,e: raise AssembleError(str(e)) return True def createMaskList(self,chrootdir,filename): """Create package mask list by chrootdir""" pkgdir = path.join(chrootdir,'var/db/pkg') reVerSplit = re.compile(r"^(.*?)-(([^-]+?)(?:-(r\d+))?)$",re.S) if not path.exists(chrootdir): return False try: packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x), os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[])) open(filename,'w').writelines( map(lambda x:"%s\n"%x, map(lambda x:x.groups()[0], filter(lambda x:x, map(reVerSplit.search, packageList))))) except (IOError,OSError),e: return False return True def createUnmaskList(self,chrootdir,filename): """Create package unmask list by chrootdir""" pkgdir = path.join(chrootdir,'var/db/pkg') #x11_bindir = path.join(chrootdir,'usr/portage/packages/x11-drivers') if not path.exists(chrootdir): return False try: packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x), os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[])) #packageList = \ # sorted(packageList+ # map(lambda x:path.join('x11-drivers',x[:-5]), # filter(lambda x:x.endswith('.tbz2'), # listDirectory(x11_bindir)))) open(filename,'w').writelines(map(lambda x:"=%s\n"%x,packageList)) except (IOError,OSError),e: return False return True def createUseList(self,chrootdir,filename): """Create package uselist by chrootdir""" pkgdir = path.join(chrootdir,'var/db/pkg') def calcUseFlags(pkg): iusePath = path.join(pkgdir,pkg,"IUSE") usePath = path.join(pkgdir,pkg,"USE") if path.exists(iusePath): IUSE = set( map(lambda x: x[1:] if x and x[0] in ("-","+") else x, open(iusePath,"r").read().strip().split())) else: return "" if path.exists(usePath): USE = set(open(usePath,"r").read().strip().split()) else: USE = set([]) plus = " ".join(sorted(IUSE & USE)) minus = " ".join(sorted(map(lambda x:"-%s"%x, IUSE - USE))) if plus: plus = " %s"%plus if minus: minus = " %s"%minus return "=%s%s%s\n"%(pkg, plus, minus) if not path.exists(chrootdir): return False try: packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x), os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[])) open(filename,'w').writelines(map(calcUseFlags,packageList)) except (IOError,OSError),e: return False return True def createMaskUnmaskList(self): """Action create mask unmask list""" baseDir = self.clVars.Get('cl_assemble_pkgdir') name = "package" if not path.exists(baseDir): os.makedirs(baseDir,mode=0755) maskName = pathJoin(baseDir,"%s.mask"%name) unmaskName = pathJoin(baseDir,"%s.unmask"%name) useName = pathJoin(baseDir,"%s.use"%name) if self.createMaskList(self.clVars.Get('cl_assemble_path'), maskName) and \ self.createUnmaskList(self.clVars.Get('cl_assemble_path'), unmaskName) and \ self.createUseList(self.clVars.Get('cl_assemble_path'), useName): return True return False