From fdceddfc0835ff3510d528052df4348d7c9affab Mon Sep 17 00:00:00 2001 From: lxnay Date: Sat, 24 Mar 2007 08:53:21 +0000 Subject: [PATCH] some fixes, beautified --nodeps, added --skipfirst for world, added libraries breakage control, added activator data (there is nothning to see atm) git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@185 cd1c1023-2f26-0410-ae45-c471fc1f0318 --- TODO | 16 ++++- handlers/activator | 132 ++++++++++++++++++++++++++++++++++++ handlers/enzyme | 5 +- libraries/activatorTools.py | 31 +++++++++ libraries/entropyTools.py | 23 ++++++- libraries/enzymeTools.py | 94 +++++++++++++++++++++---- 6 files changed, 282 insertions(+), 19 deletions(-) create mode 100644 handlers/activator create mode 100644 libraries/activatorTools.py diff --git a/TODO b/TODO index 99ec25c80..b33eb4b1c 100644 --- a/TODO +++ b/TODO @@ -3,8 +3,8 @@ TODO list (for developers only): - activator should care about the removal of the old packages - build() on enzyme, when calculating runtime dependencies, please check if there's a broken link too and report as warning - build() on enzyme, also trap einfo and ewarn ? -- build() on enzyme, also integrate a sort of revdep-rebuild ? -- build() and world(), on enzyme, add the support for a blacklist +- build() and world(), on enzyme, add the support for whitelist+cron +- build(), on enzyme, beautify sanity check when all the packages are not found - Sabayon Linux USE flags: remove all server related use flags Project Status: @@ -17,4 +17,14 @@ Project Status: Features plan: -- distcc support to enzyme \ No newline at end of file +- distcc support to enzyme + + +>> * These are the actions that will be taken, in order: +>> * [BUILD] [D] sys-apps/dbus-0.62-r2 +>> * Building packages... +>> * Compiling: sys-apps/dbus-0.62-r2 ... +['libdbus-1.so.3.2.0'] +>> * redirecting output to: /var/lib/entropy/tmp/.emerge-dbus-0.62-r2-36787 +['libdbus-1.so.2.0.0', 'dbus_bindings.so', 'dbus_glib_bindings.so', 'libdbus-glib-1.so.2.0.0', 'libdbus-qt-1.so.1.0.0'] +>> * Compiled successfully diff --git a/handlers/activator b/handlers/activator new file mode 100644 index 000000000..02270ad07 --- /dev/null +++ b/handlers/activator @@ -0,0 +1,132 @@ +#!/usr/bin/python +''' + # DESCRIPTION: + # Entropy mirrors syncing manager + + Copyright (C) 2007 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 +''' + +# Never do "import portage" here, please use entropyTools binding + +import os +import sys +import string + +sys.path.append('../libraries') +import entropyTools +import activatorTools +from entropyConstants import * + +# CONSTANTS +APPNAME = "activator" +APPVERSION = "1.0" +def print_help(): + entropyTools.print_info("Sabayon Linux "+APPNAME+" (C - 2007)") + entropyTools.print_info("Usage: "+APPNAME+" ") + entropyTools.print_info("General Options:") + entropyTools.print_info(" --help\t\tthis output") + entropyTools.print_info(" --version\t\tprint version") + entropyTools.print_info(" --verbose\t\tprint debugging info") + entropyTools.print_info(" --nocolor\t\tdisable colorized output") + entropyTools.print_info(entropyTools.blue("Tools available: ")) + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("world"))+entropyTools.yellow("\t\t to build all the possible new packages")) + entropyTools.print_info(" \t\t"+entropyTools.red("--empty-tree")+"\t\t rebuild all, including updates") + entropyTools.print_info(" \t\t"+entropyTools.red("--deep")+"\t\t\t analyzes world dependencies deeply") + entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t\t just show what should be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--ask")+"\t\t\t just ask before doing what should be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--repackage-installed")+"\t creates binaries of all the installed packages") + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("build"))+entropyTools.yellow("\t\t to build all the packages specified in ")) + entropyTools.print_info(" \t\t"+entropyTools.red("--force-rebuild")+"\t\t force the building of the package, nevertheless") + entropyTools.print_info(" \t\t"+entropyTools.red("--force-repackage")+"\t force the repackaging of all the possible package") + entropyTools.print_info(" \t\t"+entropyTools.red("--deep")+"\t\t\t analyze the dependencies deeply") + entropyTools.print_info(" \t\t"+entropyTools.red("--nodeps")+"\t\t\t do not include dependencies and force compilation") + entropyTools.print_info(" \t\t"+entropyTools.red("--use")+"\t\t\t show packages USE flags") + entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t just show what should be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--ask")+"\t\t\t just ask before doing what should be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--ignore-conflicts")+"\t ignore conflicts between packages") + entropyTools.print_info(" \t\t"+entropyTools.red("--no-interaction")+"\t disable user interaction, automatic driving") + entropyTools.print_info(" \t\t"+entropyTools.red("--simulate-building")+"\t compilations are simulated only") + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("uninstall"))+entropyTools.yellow("\t to uninstall one or a list of packages")) + entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t just show what would be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--just-prune")+"\t\t with slotted packages, keep only the latest, remove the rest") + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("overlay"))+entropyTools.yellow("\t\t to manage overlays")) + entropyTools.print_info(" \t\t "+entropyTools.red("add")+"\t\t\t to add overlays") + entropyTools.print_info(" \t\t "+entropyTools.red("remove")+"\t\t\t to remove overlays") + entropyTools.print_info(" \t\t "+entropyTools.red("sync")+"\t\t\t to sync overlays (after this you can specify which overlay)") + entropyTools.print_info(" \t\t "+entropyTools.red("list")+"\t\t\t to list overlays") + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("sync"))+entropyTools.yellow("\t\t to just sync portage tree")) + entropyTools.print_info(" \t\t "+entropyTools.red("--sync-back")+"\t\t sync between Entropy Portage Tree and the official one") + entropyTools.print_info(" \t\t "+entropyTools.red("--only-sync-back")+"\t only sync between Entropy Portage Tree and the official one") + entropyTools.print_info(" \t\t "+entropyTools.red("--no-overlay-sync")+"\t disable automatic overlays sync") + entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("cleanup"))+entropyTools.yellow("\t\t to clean temporary files")) + +options = sys.argv[1:] + +# no color parsing +_options = [] +for opt in options: + if (opt == "--nocolor"): + entropyTools.nocolor() + else: + _options.append(opt) +options = _options + +# print version +if (string.join(options).find("--version") != -1) or (string.join(options).find(" -V") != -1): + entropyTools.print_generic(APPNAME+": "+APPVERSION) + sys.exit(0) + +# print help +if len(options) < 1 or string.join(options).find("--help") != -1 or string.join(options).find(" -h") != -1: + print_help() + if len(options) < 1: + entropyTools.print_error("not enough parameters") + sys.exit(1) + +if (not entropyTools.isRoot()): + entropyTools.print_error("you must be root in order to run "+APPNAME) + sys.exit(2) + +# world tool +if (options[0] == "world"): + enzymeTools.world(options) + sys.exit(0) +# sync tool +if (options[0] == "sync"): + enzymeTools.sync(options) + sys.exit(0) +# overlay tool +if (options[0] == "overlay"): + rc = enzymeTools.overlay(options) + if (rc): + sys.exit(0) + else: + # an error occoured + print_help() + sys.exit(3) +# build tool +if (options[0] == "build"): + enzymeTools.build(options[1:]) + sys.exit(0) +# uninstall tool +if (options[0] == "uninstall"): + enzymeTools.uninstall(options[1:]) + sys.exit(0) +# cleanup tool +if (options[0] == "cleanup"): + entropyTools.cleanup(options[1:]) + sys.exit(0) \ No newline at end of file diff --git a/handlers/enzyme b/handlers/enzyme index cc6f394f6..b11879e22 100644 --- a/handlers/enzyme +++ b/handlers/enzyme @@ -46,14 +46,15 @@ def print_help(): entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("world"))+entropyTools.yellow("\t\t to build all the possible new packages")) entropyTools.print_info(" \t\t"+entropyTools.red("--empty-tree")+"\t\t rebuild all, including updates") entropyTools.print_info(" \t\t"+entropyTools.red("--deep")+"\t\t\t analyzes world dependencies deeply") - entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t\t just show what should be done") + entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t just show what should be done") entropyTools.print_info(" \t\t"+entropyTools.red("--ask")+"\t\t\t just ask before doing what should be done") entropyTools.print_info(" \t\t"+entropyTools.red("--repackage-installed")+"\t creates binaries of all the installed packages") + entropyTools.print_info(" \t\t"+entropyTools.red("--skipfirst")+"\t\t skip the first package in the packages list") entropyTools.print_info(" \t"+entropyTools.green(entropyTools.bold("build"))+entropyTools.yellow("\t\t to build all the packages specified in ")) entropyTools.print_info(" \t\t"+entropyTools.red("--force-rebuild")+"\t\t force the building of the package, nevertheless") entropyTools.print_info(" \t\t"+entropyTools.red("--force-repackage")+"\t force the repackaging of all the possible package") entropyTools.print_info(" \t\t"+entropyTools.red("--deep")+"\t\t\t analyze the dependencies deeply") - entropyTools.print_info(" \t\t"+entropyTools.red("--nodeps")+"\t\t\t do not include dependencies and force compilation") + entropyTools.print_info(" \t\t"+entropyTools.red("--nodeps")+"\t\t do not include dependencies and force compilation") entropyTools.print_info(" \t\t"+entropyTools.red("--use")+"\t\t\t show packages USE flags") entropyTools.print_info(" \t\t"+entropyTools.red("--pretend")+"\t\t just show what should be done") entropyTools.print_info(" \t\t"+entropyTools.red("--ask")+"\t\t\t just ask before doing what should be done") diff --git a/libraries/activatorTools.py b/libraries/activatorTools.py new file mode 100644 index 000000000..719e7398c --- /dev/null +++ b/libraries/activatorTools.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +''' + # DESCRIPTION: + # generic tools for enzyme application + + Copyright (C) 2007 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 +''' + +# Never do "import portage" here, please use entropyTools binding + +from entropyConstants import * +from entropyTools import * + +import sys +import os +import commands +import string \ No newline at end of file diff --git a/libraries/entropyTools.py b/libraries/entropyTools.py index 44ebba2c8..0f8c4e442 100644 --- a/libraries/entropyTools.py +++ b/libraries/entropyTools.py @@ -210,6 +210,7 @@ def translateArch(string,chost): else: return string +# please always force =pkgcat/pkgname-ver if possible def getInstalledAtom(atom): rc = portage.db['/']['vartree'].dep_match(str(atom)) if (rc != []): @@ -229,7 +230,27 @@ def getPackageSlot(atom): else: return None -# INFO: there is get_slot too :) +# you must provide a complete atom +def collectBinaryFilesForInstalledPackage(atom): + if atom.startswith("="): + atom = atom[1:] + pkgcat = atom.split("/")[0] + pkgnamever = atom.split("/")[1] + dbentrypath = "/var/db/pkg/"+pkgcat+"/"+pkgnamever+"/CONTENTS" + binarylibs = [] + if os.path.isfile(dbentrypath): + f = open(dbentrypath,"r") + contents = f.readlines() + f.close() + for i in contents: + file = i.split()[1] + if i.startswith("obj") and (file.find("lib") != -1) and (file.find(".so") != -1) and (not file.endswith(".la")): + # FIXME: rough way + binarylibs.append(i.split()[1].split("/")[len(i.split()[1].split("/"))-1]) + return binarylibs + else: + return binarylibs + def getEbuildDbPath(atom): return portage.db['/']['vartree'].getebuildpath(atom) diff --git a/libraries/enzymeTools.py b/libraries/enzymeTools.py index aed7b03ee..53cfe980b 100644 --- a/libraries/enzymeTools.py +++ b/libraries/enzymeTools.py @@ -208,7 +208,7 @@ def build(atoms): PackagesConflicting = [] PackagesQuickpkg = [] - if (not enzymeRequestNodeps): + if (not enzymeRequestNodeps) and (not enzymeRequestIgnoreConflicts): # Check if a .tbz2 has already been done # control if --force-rebuild or --force-repackage has been provided # and filter the packages list accordingly to line 1 @@ -237,7 +237,7 @@ def build(atoms): if len(toBeBuilt) > 1: cleanatomlist = [] for atom in toBeBuilt: - if (not atom.startswith(">")) and (not atom.startswith("<")) and (not atoms.startswith("=")) and (not isjustname(atom)): + if (not atom.startswith(">")) and (not atom.startswith("<")) and (not atom.startswith("=")) and (not isjustname(atom)): cleanatomlist.append("="+atom) else: cleanatomlist.append(atom) @@ -271,7 +271,11 @@ def build(atoms): print_info(" Analyzing package "+bold(atom)+" ...",back = True) if (not enzymeRequestNodeps): atomdeps, atomconflicts = calculateFullAtomsDependencies("="+atom,enzymeRequestDeep) if(enzymeRequestVerbose): print_info(" Analyzing package: "+bold(atom)) - if(enzymeRequestVerbose): print_info(" Current installed release: "+bold(str(getInstalledAtom("="+atom)))) + if(enzymeRequestVerbose): + if (getPackageSlot("="+atom) is None): + print_info(" Current installed release: "+bold(str(getInstalledAtom(dep_getkey(atom))))) + else: + print_info(" Current installed release: "+bold(str(getInstalledAtom("="+atom)))) if(enzymeRequestVerbose): print_info("\tfiltering "+atom+" related packages...") if (not enzymeRequestNodeps): @@ -281,7 +285,10 @@ def build(atoms): if(enzymeRequestVerbose): print_info("\tchecking for: "+red(dep[1:])) wantedAtom = getBestAtom(dep) if(enzymeRequestVerbose): print_info("\t\tI want: "+yellow(wantedAtom)) - installedAtom = getInstalledAtom(dep) + if (getPackageSlot(dep) is None): + installedAtom = getInstalledAtom(dep_getkey(dep)) + else: + installedAtom = getInstalledAtom(dep) if(enzymeRequestVerbose): print_info("\t\tIs installed: "+green(str(installedAtom))) if ( installedAtom is None ) or (enzymeRequestForceRebuild): # then append - because it's not installed ! @@ -319,13 +326,17 @@ def build(atoms): useflags = "" if enzymeRequestUse: useflags = bold(" [")+yellow("USE: ")+calculateAtomUSEFlags("="+i)+bold("]") pkgstatus = "[?]" - if (getInstalledAtom(dep_getkey(i)) == None): + if (getPackageSlot("="+i) is None): + pkg = dep_getkey(i) + else: + pkg = "="+i + if (getInstalledAtom(pkg) == None): pkgstatus = green("[N]") - elif (compareAtoms(i,getInstalledAtom("="+i)) == 0): + elif (compareAtoms(i,getInstalledAtom(pkg)) == 0): pkgstatus = yellow("[R]") - elif (compareAtoms(i,getInstalledAtom("="+i)) > 0): + elif (compareAtoms(i,getInstalledAtom(pkg)) > 0): pkgstatus = blue("[U]") - elif (compareAtoms(i,getInstalledAtom("="+i)) < 0): + elif (compareAtoms(i,getInstalledAtom(pkg)) < 0): pkgstatus = darkblue("[D]") print_info(red(" *")+bold(" [")+red("BUILD")+bold("] ")+pkgstatus+" "+i+useflags) @@ -365,10 +376,66 @@ def build(atoms): print_info(green(" *")+" Compiling: "+red(dep)+" ... ") mountProc() if (not enzymeRequestVerbose): + + pkgBinaryFiles = [] # collect libraries info for the current installed package, if any + if (getPackageSlot("="+atom) is None): + pkgquestion = dep_getkey(atom) + else: + pkgquestion = "="+atom + if (getInstalledAtom(pkgquestion) is not None): + # collect them! + pkgBinaryFiles = collectBinaryFilesForInstalledPackage(getInstalledAtom(pkgquestion)) print_info(yellow(" *")+" redirecting output to: "+green(outfile)) rc, outfile = emerge("="+dep, odbNodeps, outfile, "&>", enzymeRequestSimulation) + + # after install, check for changes + newPkgBinaryFiles = [] + # collect libraries info for the current installed package, if any + if (getPackageSlot("="+atom) is None): + pkgquestion = dep_getkey(atom) + else: + pkgquestion = "="+atom + if (getInstalledAtom(pkgquestion) is not None): + # collect them! + newPkgBinaryFiles = collectBinaryFilesForInstalledPackage(getInstalledAtom(pkgquestion)) + + brokenBinariesList = [] + # check if there has been a API breakage + if pkgBinaryFiles != newPkgBinaryFiles: + _pkgBinaryFiles = [] + _newPkgBinaryFiles = [] + # extract only similar packages + for pkg in pkgBinaryFiles: + _pkg = pkg.split(".so")[0] + for newpkg in newPkgBinaryFiles: + _newpkg = newpkg.split(".so")[0] + if (_newpkg == _pkg): + _pkgBinaryFiles.append(pkg) + _newPkgBinaryFiles.append(newpkg) + pkgBinaryFiles = _pkgBinaryFiles + newPkgBinaryFiles = _newPkgBinaryFiles + + # check for version bumps + for pkg in pkgBinaryFiles: + _pkgver = pkg.split(".so")[len(pkg.split(".so"))-1] + _pkg = pkg.split(".so")[0] + for newpkg in newPkgBinaryFiles: + _newpkgver = newpkg.split(".so")[len(newpkg.split(".so"))-1] + _newpkg = newpkg.split(".so")[0] + if (_newpkg == _pkg): + # check version + if (_pkgver != _newpkgver): + brokenBinariesList.append([ pkg, newpkg ]) + + if brokenBinariesList != []: + # FIXME: make this warning fatal? + print_warning(yellow(" * ")+red("ATTENTION: Package ")+bold(dep)+red(" caused an API breakage:")) + for i in brokenBinariesList: + print_warning(yellow(" * ")+green("Previous library: ")+yellow(i[0])+bold(" -- became --> ")+red(i[1])+" (now installed)") + import time + time.sleep(30) else: rc, outfile = emerge("="+dep,odbNodeps,None,None, enzymeRequestSimulation) #umountProc() @@ -487,6 +554,7 @@ def world(options): enzymeRequestAsk = False enzymeRequestPretend = False enzymeRequestJustRepackageWorld = False + enzymeRequestSkipfirst = False for i in myopts: if ( i == "--verbose" ) or ( i == "-v" ): enzymeRequestVerbose = True @@ -496,6 +564,8 @@ def world(options): enzymeRequestAsk = True elif ( i == "--pretend" ): enzymeRequestPretend = True + elif ( i == "--skipfirst" ): + enzymeRequestSkipfirst = True elif ( i == "--repackage-installed" ): enzymeRequestJustRepackageWorld = True elif ( i == "--deep" ): @@ -537,20 +607,18 @@ def world(options): # classical world, trapping --deep if necessary else: emergeopts = " -u " - #print "DEBUG: running world()" - #if (enzymeRequestDeep): print "DEBUG: world(): --deep on" - #if (enzymeRequestRebuild): print "DEBUG: world(): --empty-tree on" if (enzymeRequestDeep): emergeopts += " -D" if (enzymeRequestRebuild) and (not enzymeRequestDeep): emergeopts += " -e" - #print emergeopts print_info(green(" * ")+red("Scanning tree for ")+bold("updates")+red("...")) deplist, blocklist = calculateFullAtomsDependencies("world",False,emergeopts) - #print "-----asdasd-----" if blocklist != []: print blocklist print "error there is something that is blocking all this shit" sys.exit(303) + if (enzymeRequestSkipfirst): + deplist = deplist[1:] + # composing the request atoms = [] for atom in deplist: