#!/usr/bin/python ''' # DESCRIPTION: # Variables container 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 random import gc import sys import os import stat import maskingparser import exceptionTools # Specifications of the content of etpData ''' etpData = { 'name': u"", # the Package Name 'version': u"", # the Package version 'description': u"", # the Package description 'category': u"", # the gentoo category 'chost': u"", # the CHOST used to compile it 'cflags': u"", # CFLAGS used 'cxxflags': u"", # CXXFLAGS used 'homepage': u"", # home page of the package 'useflags': u"", # USE flags used 'license': u"", # License adpoted 'keywords': u"", # supported ARCHs (by the SRC) 'branch': u"", # package branch location 'download': u"", # link to download the binary package 'digest': u"", # md5 hash of the .tbz2 package 'sources': u"", # link to the sources 'slot': u"", # this is filled if the package is slotted 'content': u"", # content of the package (files) 'mirrorlinks': u"", # =mirror://openoffice|link1|link2|link3 'dependencies': u"", # dependencies 'conflicts': u"", # blockers 'etpapi': u"", # Entropy API revision 'datecreation': u"", # mtime of the .tbz2 file 'size': u"", # the package size 'versiontag': u"", # particular version tag 'provide': u"", # like, cups provides dep virtual/lpr 'systempackage': u"", # if this is a system package, this will be != "" 'config_protect': u"", # list of directories that contain files that should not be overwritten 'config_protect_mask': u"", # list of directories that contain files that should be overwritten 'disksize': u"", # size on the hard disk in bytes (integer) 'counter': u"", # aka. COUNTER file 'messages': u"", # elog content from portage 'eclasses': u"", # eclasses used by the ebuild 'needed': u"", # runtime libraries needed by the package 'trigger': u"", # this will become a bool, containing info about external trigger presence 'injected': bool, # if the package has been injected manually, this will be true } ''' # Entropy database SQL initialization Schema and data structure etpSQLInitDestroyAll = """ DROP TABLE IF EXISTS baseinfo; DROP TABLE IF EXISTS extrainfo; DROP TABLE IF EXISTS content; DROP TABLE IF EXISTS contentreference; DROP TABLE IF EXISTS contenttypes; DROP TABLE IF EXISTS dependencies; DROP TABLE IF EXISTS rundependencies; DROP TABLE IF EXISTS rundependenciesxt; DROP TABLE IF EXISTS dependenciesreference; DROP TABLE IF EXISTS provide; DROP TABLE IF EXISTS conflicts; DROP TABLE IF EXISTS neededlibs; DROP TABLE IF EXISTS libraries; DROP TABLE IF EXISTS mirrorlinks; DROP TABLE IF EXISTS sources; DROP TABLE IF EXISTS sourcesreference; DROP TABLE IF EXISTS useflags; DROP TABLE IF EXISTS useflagsreference; DROP TABLE IF EXISTS keywords; DROP TABLE IF EXISTS binkeywords; DROP TABLE IF EXISTS keywordsreference; DROP TABLE IF EXISTS categories; DROP TABLE IF EXISTS licenses; DROP TABLE IF EXISTS flags; DROP TABLE IF EXISTS systempackages; DROP TABLE IF EXISTS configprotect; DROP TABLE IF EXISTS configprotectmask; DROP TABLE IF EXISTS configprotectreference; DROP TABLE IF EXISTS installedtable; DROP TABLE IF EXISTS dependstable; DROP TABLE IF EXISTS sizes; DROP TABLE IF EXISTS messages; DROP TABLE IF EXISTS counters; DROP TABLE IF EXISTS eclasses; DROP TABLE IF EXISTS eclassesreference; DROP TABLE IF EXISTS needed; DROP TABLE IF EXISTS neededreference; DROP TABLE IF EXISTS triggers; DROP TABLE IF EXISTS countersdata; DROP TABLE IF EXISTS injected; DROP TABLE IF EXISTS treeupdates; DROP TABLE IF EXISTS treeupdatesactions; """ etpSQLInit = """ CREATE TABLE baseinfo ( idpackage INTEGER PRIMARY KEY, atom VARCHAR, idcategory INTEGER, name VARCHAR, version VARCHAR, versiontag VARCHAR, revision INTEGER, branch VARCHAR, slot VARCHAR, idlicense INTEGER, etpapi INTEGER, trigger INTEGER ); CREATE TABLE extrainfo ( idpackage INTEGER PRIMARY KEY, description VARCHAR, homepage VARCHAR, download VARCHAR, size VARCHAR, idflags INTEGER, digest VARCHAR, datecreation VARCHAR ); CREATE TABLE content ( idpackage INTEGER, file VARCHAR, type VARCHAR ); CREATE TABLE provide ( idpackage INTEGER, atom VARCHAR ); CREATE TABLE dependencies ( idpackage INTEGER, iddependency INTEGER ); CREATE TABLE dependenciesreference ( iddependency INTEGER PRIMARY KEY, dependency VARCHAR ); CREATE TABLE conflicts ( idpackage INTEGER, conflict VARCHAR ); CREATE TABLE mirrorlinks ( mirrorname VARCHAR, mirrorlink VARCHAR ); CREATE TABLE sources ( idpackage INTEGER, idsource INTEGER ); CREATE TABLE sourcesreference ( idsource INTEGER PRIMARY KEY, source VARCHAR ); CREATE TABLE useflags ( idpackage INTEGER, idflag INTEGER ); CREATE TABLE useflagsreference ( idflag INTEGER PRIMARY KEY, flagname VARCHAR ); CREATE TABLE keywords ( idpackage INTEGER, idkeyword INTEGER ); CREATE TABLE keywordsreference ( idkeyword INTEGER PRIMARY KEY, keywordname VARCHAR ); CREATE TABLE categories ( idcategory INTEGER PRIMARY KEY, category VARCHAR ); CREATE TABLE licenses ( idlicense INTEGER PRIMARY KEY, license VARCHAR ); CREATE TABLE flags ( idflags INTEGER PRIMARY KEY, chost VARCHAR, cflags VARCHAR, cxxflags VARCHAR ); CREATE TABLE configprotect ( idpackage INTEGER PRIMARY KEY, idprotect INTEGER ); CREATE TABLE configprotectmask ( idpackage INTEGER PRIMARY KEY, idprotect INTEGER ); CREATE TABLE configprotectreference ( idprotect INTEGER PRIMARY KEY, protect VARCHAR ); CREATE TABLE systempackages ( idpackage INTEGER PRIMARY KEY ); CREATE TABLE injected ( idpackage INTEGER PRIMARY KEY ); CREATE TABLE installedtable ( idpackage INTEGER PRIMARY KEY, repositoryname VARCHAR ); CREATE TABLE sizes ( idpackage INTEGER PRIMARY KEY, size INTEGER ); CREATE TABLE messages ( idpackage INTEGER, message VARCHAR ); CREATE TABLE counters ( counter INTEGER PRIMARY KEY, idpackage INTEGER ); CREATE TABLE eclasses ( idpackage INTEGER, idclass INTEGER ); CREATE TABLE eclassesreference ( idclass INTEGER PRIMARY KEY, classname VARCHAR ); CREATE TABLE needed ( idpackage INTEGER, idneeded INTEGER ); CREATE TABLE neededreference ( idneeded INTEGER PRIMARY KEY, library VARCHAR ); CREATE TABLE treeupdates ( repository VARCHAR PRIMARY KEY, digest VARCHAR ); CREATE TABLE treeupdatesactions ( idupdate INTEGER PRIMARY KEY, repository VARCHAR, command VARCHAR ); CREATE TABLE binkeywords ( idpackage INTEGER, idkeyword INTEGER ); """ # ETP_ARCH_CONST setup if os.uname()[4] == "x86_64": ETP_ARCH_CONST = "amd64" else: ETP_ARCH_CONST = "x86" etpSys = { 'archs': ["x86", "amd64"], 'api': '1', 'arch': ETP_ARCH_CONST, 'rootdir': "", 'maxthreads': 5, 'threads': 0, 'dirstoclean': set(), } etpUi = { 'quiet': False, 'verbose': False, 'ask': False, 'pretend': False, 'mute': False, 'nolog': False, 'postinstall_triggers_disable': set(), 'postremove_triggers_disable': set(), 'preinstall_triggers_disable': set(), 'preremove_triggers_disable': set() } # static logging stuff ETP_LOGLEVEL_NORMAL = 1 ETP_LOGLEVEL_VERBOSE = 2 ETP_LOGPRI_INFO = "[ INFO ]" ETP_LOGPRI_WARNING = "[ WARNING ]" ETP_LOGPRI_ERROR = "[ ERROR ]" # disk caching dictionary etpCache = { 'configfiles': 'scanfs', # used to store information about files that should be merged using "equo conf merge" 'dbMatch': 'cache_', # used by the database controller as prefix to the cache files belonging to etpDatabase class (dep solving) 'dbSearch': 'search_', # used by the database controller as prefix to the cache files belonging to etpDatabase class (searches) 'dbInfo': 'info_', # used by the database controller as prefix to the cache files belonging to etpDatabase class (info retrival) 'atomMatch': 'atomMatchCache', # used to store info about repository dependencies solving 'generateDependsTree': 'generateDependsTreeCache', # used to store info about removal dependencies 'install': 'resume_install', # resume cache (install) 'remove': 'resume_remove', # resume cache (remove) 'world': 'resume_world', # resume cache (world) 'world_update': 'world_cache', 'world_available': 'available_cache', 'check_package_update': 'package_update' } # byte sizes of disk caches etpCacheSizes = { 'dbMatch': 3000000, # bytes 'dbInfo': 6000000, # bytes 'dbSearch': 2000000, # bytes 'atomMatch': 3000000, # bytes 'generateDependsTree': 3000000, # bytes } # ahahaha etpExitMessages = { 0: "You should run equo --help", 1: "You didn't run equo --help, did you?", 2: "Did you even read equo --help??", 3: "I give up. Run that equo --help !!!!!!!", 4: "OH MY GOD. RUN equo --heeeeeeeeeeeeeelp", 5: "Illiteracy is a huge problem in this world", 6: "Ok i give up, you are hopeless", 7: "Go to hell." } # information about what has been done on the database, # those dicts will be dumped to a file and used by activator to update and updload .rss etpRSSMessages = { 'added': {}, # packages that has been added 'removed': {}, # packages that has been removed 'commitmessage': "" # commit message from the guy who is going to submit a repository update } # Handlers used by entropy to run and retrieve data remotely, using php helpers etpHandlers = {} # CACHING dictionaries dbCacheStore = {} atomMatchCache = {} atomClientMatchCache = {} generateDependsTreeCache = {} idpackageValidatorCache = {} filterSatisfiedDependenciesCache = {} filterSatisfiedDependenciesCmpResults = {} generateDependencyTreeCache = {} check_package_update_cache = {} ververifyCache = {} isjustnameCache = {} catpkgsplitCache = {} dep_striptagCache = {} dep_getkeyCache = {} dep_getcpvCache = {} dep_getslotCache = {} dep_gettagCache = {} removePackageOperatorsCache = {} compareVersionsCache = {} getNewerVersionCache = {} # generateDependencyTree match filter matchFilter = set() linkerPaths = set() # repository atoms updates digest cache repositoryUpdatesDigestCache_db = {} repositoryUpdatesDigestCache_disk = {} fetch_repository_if_not_available_cache = {} repo_error_messages_cache = set() ### Application disk cache def const_resetCache(): for item in dbCacheStore: dbCacheStore[item].clear() atomMatchCache.clear() atomClientMatchCache.clear() generateDependsTreeCache.clear() idpackageValidatorCache.clear() filterSatisfiedDependenciesCache.clear() filterSatisfiedDependenciesCmpResults.clear() generateDependencyTreeCache.clear() ververifyCache.clear() isjustnameCache.clear() catpkgsplitCache.clear() dep_striptagCache.clear() dep_getkeyCache.clear() dep_getcpvCache.clear() dep_getslotCache.clear() dep_gettagCache.clear() removePackageOperatorsCache.clear() compareVersionsCache.clear() getNewerVersionCache.clear() matchFilter.clear() linkerPaths.clear() repositoryUpdatesDigestCache_db.clear() repositoryUpdatesDigestCache_disk.clear() check_package_update_cache.clear() fetch_repository_if_not_available_cache.clear() repo_error_messages_cache.clear() # Inside it you'll find instantiated vartree classes portageRoots = {} # portage fakedbapi cache portageFakeDbApi = {} # Client packages/database repositories etpRepositories = {} etpRepositoriesExcluded = {} etpRepositoriesOrder = [] # remote section etpRemoteSupport = {} etpRemoteFailures = {} # dict of excluded mirrors due to failures, # it contains mirror name and failure count | > 5 == ignore mirror # your bible etpConst = {} # database status dict etpDbStatus = {} # Portage /var/db///* # you never know if gentoo devs change these things dbDESCRIPTION = "DESCRIPTION" dbHOMEPAGE = "HOMEPAGE" dbCHOST = "CHOST" dbCATEGORY = "CATEGORY" dbCFLAGS = "CFLAGS" dbCXXFLAGS = "CXXFLAGS" dbLICENSE = "LICENSE" dbSRC_URI = "SRC_URI" dbUSE = "USE" dbIUSE = "IUSE" dbSLOT = "SLOT" dbPROVIDE = "PROVIDE" dbDEPEND = "DEPEND" dbRDEPEND = "RDEPEND" dbPDEPEND = "PDEPEND" dbNEEDED = "NEEDED" dbINHERITED = "INHERITED" dbOR = "|or|" dbKEYWORDS = "KEYWORDS" dbCONTENTS = "CONTENTS" dbCOUNTER = "COUNTER" # =============================================================================================== # BEGINNING OF DYNAMIC SECTION # =============================================================================================== def initConfig_entropyConstants(rootdir): if rootdir and not os.path.isdir(rootdir): import exceptionTools raise exceptionTools.FileNotFound("FileNotFound: not a valid chroot.") ETP_DIR = rootdir+"/var/lib/entropy" ETP_TMPDIR = "/tmp" ETP_RANDOM = str(random.random())[2:7] ETP_TMPFILE = "/.random-"+ETP_RANDOM+".tmp" ETP_REPODIR = "/packages/"+ETP_ARCH_CONST ETP_PORTDIR = rootdir+"/usr/portage" ETP_DISTFILESDIR = "/distfiles" ETP_DBDIR = "/database/"+ETP_ARCH_CONST ETP_DBFILE = "packages.db" ETP_DBCLIENTFILE = "equo.db" ETP_CLIENT_REPO_DIR = "/client" ETP_UPLOADDIR = "/upload/"+ETP_ARCH_CONST ETP_STOREDIR = "/store/"+ETP_ARCH_CONST ETP_TRIGGERSDIR = "/triggers/"+ETP_ARCH_CONST ETP_SMARTAPPSDIR = "/smartapps/"+ETP_ARCH_CONST ETP_SMARTPACKAGESDIR = "/smartpackages/"+ETP_ARCH_CONST ETP_CACHESDIR = "/caches/" ETP_LOG_DIR = ETP_DIR+"/"+"logs" ETP_CONF_DIR = rootdir+"/etc/entropy" ETP_SYSLOG_DIR = rootdir+"/var/log/entropy/" ETP_VAR_DIR = rootdir+"/var/tmp/entropy" edbCOUNTER = rootdir+"/var/cache/edb/counter" const_resetCache() etpConst.clear() myConst = { 'packagestmpdir': ETP_DIR+ETP_TMPDIR, # etpConst['packagestmpdir'] --> temp directory 'packagestmpfile': ETP_DIR+ETP_TMPDIR+ETP_TMPFILE, # etpConst['packagestmpfile'] --> general purpose tmp file 'packagesbindir': ETP_DIR+ETP_REPODIR, # etpConst['packagesbindir'] --> repository where the packages will be stored # by the clients: to query if a package has been already downloaded # by the servers or rsync mirrors: to store already uploaded packages to the main rsync server 'smartappsdir': ETP_DIR+ETP_SMARTAPPSDIR, # etpConst['smartappsdir'] location where smart apps files are places 'smartpackagesdir': ETP_DIR+ETP_SMARTPACKAGESDIR, # etpConst['smartpackagesdir'] location where smart packages files are places 'triggersdir': ETP_DIR+ETP_TRIGGERSDIR, # etpConst['triggersdir'] location where external triggers are placed 'packagesstoredir': ETP_DIR+ETP_STOREDIR, # etpConst['packagesstoredir'] --> directory where .tbz2 files are stored waiting for being processed by reagent 'packagessuploaddir': ETP_DIR+ETP_UPLOADDIR, # etpConst['packagessuploaddir'] --> directory where .tbz2 files are stored waiting for being uploaded to our main mirror 'portagetreedir': ETP_PORTDIR, # directory where is stored our local portage tree 'distfilesdir': ETP_PORTDIR+ETP_DISTFILESDIR, # directory where our sources are downloaded 'confdir': ETP_CONF_DIR, # directory where entropy stores its configuration 'entropyconf': ETP_CONF_DIR+"/entropy.conf", # entropy.conf file 'repositoriesconf': ETP_CONF_DIR+"/repositories.conf", # repositories.conf file 'activatorconf': ETP_CONF_DIR+"/activator.conf", # activator.conf file 'serverconf': ETP_CONF_DIR+"/server.conf", # server.conf file (generic server side settings) 'reagentconf': ETP_CONF_DIR+"/reagent.conf", # reagent.conf file 'remoteconf': ETP_CONF_DIR+"/remote.conf", # remote.conf file 'equoconf': ETP_CONF_DIR+"/equo.conf", # equo.conf file 'activatoruploaduris': [], # list of URIs that activator can use to upload files (parsed from activator.conf) 'activatordownloaduris': [], # list of URIs that activator can use to fetch data 'binaryurirelativepath': "packages/"+ETP_ARCH_CONST+"/", # Relative remote path for the binary repository. 'etpurirelativepath': "database/"+ETP_ARCH_CONST+"/", # database relative path 'entropyworkdir': ETP_DIR, # Entropy workdir 'entropyunpackdir': ETP_VAR_DIR, # Entropy unpack directory 'entropyimagerelativepath': "image", # Entropy packages image directory 'entropyxpakrelativepath': "xpak", # Gentoo xpak temp directory path 'entropyxpakdatarelativepath': "data", # Gentoo xpak metadata directory path 'entropyxpakfilename': "metadata.xpak", # Gentoo xpak metadata file name 'etpdatabaserevisionfile': ETP_DBFILE+".revision", # the local/remote database revision file 'etpdatabasehashfile': ETP_DBFILE+".md5", # its checksum 'etpdatabaselockfile': ETP_DBFILE+".lock", # the remote database lock file 'etpdatabasedownloadlockfile': ETP_DBFILE+".download.lock", # the remote database download lock file 'etpdatabasetaintfile': ETP_DBFILE+".tainted", # when this file exists, the database is not synced anymore with the online one 'etpdatabasefile': ETP_DBFILE, # Entropy sqlite database file ETP_DIR+ETP_DBDIR+"/packages.db" 'etpdatabasefilegzip': ETP_DBFILE+".gz", # Entropy sqlite database file (gzipped) 'etpdatabasefilebzip2': ETP_DBFILE+".bz2", # Entropy sqlite database file (bzipped2) 'etpdatabasefileformat': "bz2", # Entropy default compressed database format 'etpdatabasesupportedcformats': ["bz2","gz"], # Entropy compressed databases format support 'etpdatabasecompressclasses': { "bz2": ("bz2.BZ2File","unpackBzip2","etpdatabasefilebzip2",), "gz": ("gzip.GzipFile","unpackGzip","etpdatabasefilegzip",) }, 'rss-feed': True, # enable/disable packages RSS feed feature 'rss-name': "packages.rss", # default name of the RSS feed 'rss-base-url': "http://packages.sabayonlinux.org/", # default URL to the entropy web interface (overridden in reagent.conf) 'rss-website-url': "http://www.sabayonlinux.org/", # default URL to the Operating System website (overridden in reagent.conf) 'rss-dump-name': "rss_database_actions", # xml file where will be dumped etpRSSMessages dictionary 'rss-max-entries': 10000, # maximum rss entries 'rss-managing-editor': "lxnay@sabayonlinux.org", # updates submitter 'packageshashfileext': ".md5", # Extension of the file that contains the checksum of its releated package file 'packagesexpirationfileext': ".expired", # Extension of the file that "contains" expiration mtime 'packagesexpirationdays': 15, # number of days after a package will be removed from mirrors 'triggername': "trigger", # name of the trigger file that would be executed by equo inside triggerTools 'proxy': {}, # proxy configuration information, used system wide 'reagentloglevel': 1 , # Reagent log level (default: 1 - see reagent.conf for more info) 'activatorloglevel': 1, # # Activator log level (default: 1 - see activator.conf for more info) 'entropyloglevel': 1, # # Entropy log level (default: 1 - see entropy.conf for more info) 'equologlevel': 1, # # Equo log level (default: 1 - see equo.conf for more info) 'logdir': ETP_LOG_DIR , # Log dir where ebuilds store their stuff 'syslogdir': ETP_SYSLOG_DIR, # Entropy system tools log directory 'reagentlogfile': ETP_SYSLOG_DIR+"reagent.log", # Reagent operations log file 'activatorlogfile': ETP_SYSLOG_DIR+"activator.log", # Activator operations log file 'entropylogfile': ETP_SYSLOG_DIR+"entropy.log", # Activator operations log file 'equologfile': ETP_SYSLOG_DIR+"equo.log", # Activator operations log file 'distccconf': "/etc/distcc/hosts", # distcc hosts configuration file FIXME: remove this? 'etpdatabasedir': ETP_DIR+ETP_DBDIR, 'etpdatabasefilepath': ETP_DIR+ETP_DBDIR+"/"+ETP_DBFILE, 'etpdatabaseclientdir': ETP_DIR+ETP_CLIENT_REPO_DIR+ETP_DBDIR, 'etpdatabaseclientfilepath': ETP_DIR+ETP_CLIENT_REPO_DIR+ETP_DBDIR+"/"+ETP_DBCLIENTFILE, # path to equo.db - client side database file 'dbnamerepoprefix': "repo_", # prefix of the name of self.dbname in etpDatabase class for the repositories 'etpapi': etpSys['api'], # Entropy database API revision 'currentarch': etpSys['arch'], # contains the current running architecture 'supportedarchs': etpSys['archs'], # Entropy supported Archs 'branches': [], # available branches, this only exists for the server part, these settings will be overridden by server.conf ones 'branch': "3.5", # default choosen branch (overridden by setting in repositories.conf) 'keywords': set([etpSys['arch'],"~"+etpSys['arch']]), # default allowed package keywords 'gentoo-compat': False, # Gentoo compatibility (/var/db/pkg + Portage availability) 'edbcounter': edbCOUNTER, 'filesystemdirs': ['/bin','/boot','/emul','/etc','/lib','/lib32','/lib64','/opt','/sbin','/usr','/var'], # directory of the filesystem 'filesystemdirsmask': [ '/var/cache','/var/db','/var/empty','/var/lib/portage','/var/lib/entropy','/var/log','/var/mail','/var/tmp','/var/www', '/usr/portage', '/var/lib/scrollkeeper', '/usr/src', '/etc/skel', '/etc/ssh', '/etc/ssl', '/var/run', '/var/spool/cron', '/var/lib/init.d', '/lib/modules', '/etc/env.d', '/etc/gconf', '/etc/runlevels', '/lib/splash/cache', '/usr/share/mime', '/etc/portage' ], 'officialrepositoryid': "sabayonlinux.org", # our official repository name 'conntestlink': "http://www.google.com", 'databasestarttag': "|ENTROPY:PROJECT:DB:MAGIC:START|", # tag to append to .tbz2 file before entropy database (must be 32bytes) 'pidfile': "/var/run/equo.pid", 'applicationlock': False, 'filesbackup': True, # option to keep a backup of config files after being overwritten by equo conf update 'collisionprotect': 1, # collision protection option, read equo.conf for more info 'configprotect': [], # list of user specified CONFIG_PROTECT directories (see Gentoo manual to understand the meaining of this parameter) 'configprotectmask': [], # list of user specified CONFIG_PROTECT_MASK directories 'configprotectskip': [], # list of user specified configuration files that should be ignored and kept as they are 'dbconfigprotect': [], # installed database CONFIG_PROTECT directories 'dbconfigprotectmask': [], # installed database CONFIG_PROTECT_MASK directories 'configprotectcounter': 0, # this will be used to show the number of updated files at the end of the processes 'entropyversion': "1.0", # default Entropy release version 'systemname': "Sabayon Linux", # default system name (overidden by entropy.conf settings) 'product': "standard", # Product identificator (standard, professional...) 'errorstatus': ETP_CONF_DIR+"/code", 'systemroot': rootdir, # default system root 'uid': os.getuid(), # current running UID 'treeupdatescalled': False, # to avoid running tree updates functions multiple times 'dumpstoragedir': ETP_DIR+ETP_CACHESDIR, # data storage directory, useful to speed up equo across multiple issued commands # packages keywords/mask/unmask settings 'packagemasking': {}, # package masking information dictionary filled by maskingparser.py } etpConst.update(myConst) del myConst # load server database status myDatabase = { etpConst['etpdatabasefilepath']: { 'bumped': False, 'tainted': False } } if os.path.isfile(etpConst['etpdatabasedir']+"/"+etpConst['etpdatabasetaintfile']): myDatabase[etpConst['etpdatabasefilepath']]['tainted'] = True myDatabase[etpConst['etpdatabasefilepath']]['bumped'] = True etpDbStatus.update(myDatabase) del myDatabase # handle Entropy Version ETP_REVISION_FILE = "../libraries/revision" if os.path.isfile(ETP_REVISION_FILE): f = open(ETP_REVISION_FILE,"r") myrev = f.readline().strip() etpConst['entropyversion'] = myrev # handle pid file piddir = os.path.dirname(etpConst['pidfile']) if not os.path.exists(piddir): if etpConst['uid'] == 0: os.makedirs(piddir) else: import exceptionTools raise exceptionTools.DirectoryNotFound("DirectoryNotFound: please run this as root at least once or create: "+piddir) # PID creation pid = os.getpid() if os.path.exists(etpConst['pidfile']): f = open(etpConst['pidfile'],"r") foundPid = f.readline().strip() f.close() if foundPid != str(pid): # is foundPid still running ? import commands pids = commands.getoutput("pidof python").split("\n")[0].split() try: pids.index(foundPid) etpConst['applicationlock'] = True except: # if root, write new pid if etpConst['uid'] == 0: try: f = open(etpConst['pidfile'],"w") f.write(str(pid)) f.flush() f.close() except IOError, (errno,strerror): if errno == 30: # readonly filesystem pass else: raise else: if etpConst['uid'] == 0: f = open(etpConst['pidfile'],"w") f.write(str(pid)) f.flush() f.close() else: import exceptionTools raise exceptionTools.FileNotFound("FileNotFound: pid not found. please run this application as root at least once.") # Create paths if not os.path.isdir(etpConst['entropyworkdir']): if etpConst['uid'] == 0: for x in etpConst: if (type(etpConst[x]) is str): if (not etpConst[x]) or (etpConst[x].endswith(".conf")) or (not etpConst[x].startswith("/")) or (etpConst[x].endswith(".cfg")) or (etpConst[x].endswith(".tmp")) or (etpConst[x].find(".db") != -1) or (etpConst[x].find(".log") != -1): continue try: os.makedirs(etpConst[x],0755) os.chown(etpConst[x],0,0) except OSError: pass else: import exceptionTools raise exceptionTools.DirectoryNotFound("DirectoryNotFound: pid not found. please run this application as root at least once or create: "+etpConst['entropyworkdir']) # entropy section if os.path.isfile(etpConst['entropyconf']): f = open(etpConst['entropyconf'],"r") entropyconf = f.readlines() f.close() for line in entropyconf: if line.startswith("loglevel|") and (len(line.split("loglevel|")) == 2): loglevel = line.split("loglevel|")[1] try: loglevel = int(loglevel) except: print "ERROR: invalid loglevel in: "+etpConst['entropyconf'] if (loglevel > -1) and (loglevel < 3): etpConst['entropyloglevel'] = loglevel else: print "WARNING: invalid loglevel in: "+etpConst['entropyconf'] elif line.startswith("ftp-proxy|") and (len(line.split("|")) == 2): ftpproxy = line.split("|")[1].strip() for x in ftpproxy.split(): etpConst['proxy']['ftp'] = ftpproxy elif line.startswith("http-proxy|") and (len(line.split("|")) == 2): httpproxy = line.split("|")[1].strip() for x in httpproxy.split(): etpConst['proxy']['http'] = httpproxy elif line.startswith("system-name|") and (len(line.split("|")) == 2): etpConst['systemname'] = line.split("|")[1].strip() etpHandlers.clear() etpHandlers['md5sum'] = "md5sum.php?arch="+etpConst['currentarch']+"&package=" # md5sum handler etpHandlers['errorsend'] = "http://svn.sabayonlinux.org/entropy/%s/handlers/http_error_report.php" % (etpConst['product'],) etpRepositories.clear() del etpRepositoriesOrder[:] if os.path.isfile(etpConst['repositoriesconf']): f = open(etpConst['repositoriesconf'],"r") repositoriesconf = f.readlines() f.close() # setup product first for line in repositoriesconf: if (line.strip().find("product|") != -1) and (not line.strip().startswith("#")) and (len(line.strip().split("|")) == 2): etpConst['product'] = line.strip().split("|")[1] for line in repositoriesconf: line = line.strip() # populate etpRepositories if (line.find("repository|") != -1) and (len(line.split("|")) == 5): excluded = False myRepodata = etpRepositories if line.startswith("##"): continue elif line.startswith("#"): excluded = True myRepodata = etpRepositoriesExcluded line = line[1:] reponame = line.split("|")[1] repodesc = line.split("|")[2] repopackages = line.split("|")[3] repodatabase = line.split("|")[4] dbformat = etpConst['etpdatabasefileformat'] dbformatcolon = repodatabase.rfind("#") if dbformatcolon != -1: if dbformat in etpConst['etpdatabasesupportedcformats']: try: dbformat = repodatabase[dbformatcolon+1:] except: pass repodatabase = repodatabase[:dbformatcolon] if ((repopackages.startswith("http://") or repopackages.startswith("ftp://")) and \ (repodatabase.startswith("http://") or repodatabase.startswith("ftp://"))) or \ ((not repodatabase) and (myRepodata.has_key(reponame))): if not myRepodata.has_key(reponame): myRepodata[reponame] = {} myRepodata[reponame]['description'] = repodesc myRepodata[reponame]['packages'] = [] myRepodata[reponame]['dbpath'] = etpConst['etpdatabaseclientdir']+"/"+reponame+"/"+etpConst['product']+"/"+etpConst['currentarch'] myRepodata[reponame]['dbcformat'] = dbformat myRepodata[reponame]['database'] = repodatabase+"/"+etpConst['product']+"/database/"+etpConst['currentarch'] myRepodata[reponame]['dbrevision'] = "0" dbrevision_file = os.path.join(myRepodata[reponame]['dbpath'],etpConst['etpdatabaserevisionfile']) if os.path.isfile(dbrevision_file): rev_file = open(dbrevision_file,"r") myRepodata[reponame]['dbrevision'] = rev_file.readline().strip() rev_file.close() del rev_file # initialize CONFIG_PROTECT - will be filled the first time the db will be opened myRepodata[reponame]['configprotect'] = None myRepodata[reponame]['configprotectmask'] = None if not excluded: etpRepositoriesOrder.append(reponame) for x in repopackages.split(): myRepodata[reponame]['packages'].append(x+"/"+etpConst['product']) elif (line.find("branch|") != -1) and (not line.startswith("#")) and (len(line.split("|")) == 2): branch = line.split("|")[1] etpConst['branch'] = branch if not os.path.isdir(etpConst['packagesbindir']+"/"+branch): if etpConst['uid'] == 0: # check if we have a broken symlink os.makedirs(etpConst['packagesbindir']+"/"+branch) else: import exceptionTools raise exceptionTools.DirectoryNotFound("DirectoryNotFound: please run this as root at least once or create: "+etpConst['packagesbindir']+"/"+branch) elif (line.find("officialrepositoryid|") != -1) and (not line.startswith("#")) and (len(line.split("|")) == 2): officialreponame = line.split("|")[1] etpConst['officialrepositoryid'] = officialreponame elif (line.find("conntestlink|") != -1) and (not line.startswith("#")) and (len(line.split("|")) == 2): conntestlink = line.split("|")[1] etpConst['conntestlink'] = conntestlink # align etpConst['binaryurirelativepath'] and etpConst['etpurirelativepath'] with etpConst['product'] etpConst['binaryurirelativepath'] = etpConst['product']+"/"+etpConst['binaryurirelativepath'] etpConst['etpurirelativepath'] = etpConst['product']+"/"+etpConst['etpurirelativepath'] # check for packages and upload directories if etpConst['uid'] == 0: for x in etpConst['branches']: if not os.path.isdir(etpConst['packagesbindir']+"/"+x): os.makedirs(etpConst['packagesbindir']+"/"+x) if not os.path.isdir(etpConst['packagessuploaddir']+"/"+x): os.makedirs(etpConst['packagessuploaddir']+"/"+x) etpRemoteSupport.clear() etpRemoteFailures.clear() if (os.path.isfile(etpConst['remoteconf'])): f = open(etpConst['remoteconf'],"r") remoteconf = f.readlines() f.close() for line in remoteconf: if line.startswith("handler|") and (len(line.split("|")) > 2): servername = line.split("|")[1].strip() url = line.split("|")[2].strip() if not url.endswith("/"): url = url+"/" 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() def initConfig_clientConstants(): # equo section if (os.path.isfile(etpConst['equoconf'])): f = open(etpConst['equoconf'],"r") equoconf = f.readlines() f.close() for line in equoconf: if line.startswith("loglevel|") and (len(line.split("loglevel|")) == 2): loglevel = line.split("loglevel|")[1] try: loglevel = int(loglevel) except: pass if (loglevel > -1) and (loglevel < 3): etpConst['equologlevel'] = loglevel if line.startswith("gentoo-compat|") and (len(line.split("|")) == 2): compatopt = line.split("|")[1].strip() if compatopt == "disable": etpConst['gentoo-compat'] = False else: etpConst['gentoo-compat'] = True if line.startswith("filesbackup|") and (len(line.split("|")) == 2): compatopt = line.split("|")[1].strip() if compatopt == "disable": etpConst['filesbackup'] = False if line.startswith("collisionprotect|") and (len(line.split("|")) == 2): collopt = line.split("|")[1].strip() if collopt == "0" or collopt == "1" or collopt == "2": etpConst['collisionprotect'] = int(collopt) if line.startswith("configprotect|") and (len(line.split("|")) == 2): configprotect = line.split("|")[1].strip() for x in configprotect.split(): etpConst['configprotect'].append(x) if line.startswith("configprotectmask|") and (len(line.split("|")) == 2): configprotect = line.split("|")[1].strip() for x in configprotect.split(): etpConst['configprotectmask'].append(x) if line.startswith("configprotectskip|") and (len(line.split("|")) == 2): configprotect = line.split("|")[1].strip() for x in configprotect.split(): etpConst['configprotectskip'].append(etpConst['systemroot']+x) # load config initConfig_entropyConstants(etpSys['rootdir'])