sys.exit(1)
-opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force'])
+try:
+ opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force'])
+except getopt.GetoptError, e:
+ print e
+ sys.exit(1)
debug = ("--debug",'') in opts
force = ("--force",'') in opts
# Searching for updates in all the metadata is relatively slow, so this
# is where the progress bar comes out of indeterminate mode.
- cpv_all = self._tree.dbapi.cpv_all()
- cpv_all.sort()
- maxval = len(cpv_all)
- aux_get = self._tree.dbapi.aux_get
- aux_update = self._tree.dbapi.aux_update
- update_keys = self._update_keys
- from itertools import izip
- from portage.update import update_dbentries
- if onProgress:
- onProgress(maxval, 0)
- for i, cpv in enumerate(cpv_all):
- metadata = dict(izip(update_keys, aux_get(cpv, update_keys)))
- metadata_updates = update_dbentries(updates, metadata)
- if metadata_updates:
- aux_update(cpv, metadata_updates)
- if onProgress:
- onProgress(maxval, i+1)
+ self._tree.dbapi.update_ents(updates, onProgress=onProgress)
return errors
class MoveInstalled(MoveHandler):
portage.writemsg("!!! %s\n" % str(e))
del e
-portage.global_updates(mysettings, mytrees, mtimedb["updates"])
+portage._global_updates(mytrees, mtimedb["updates"])
print
print "Done."
sys.stderr.write("".join(msg))
def calc_changelog(self,ebuildpath,current,next):
+ if ebuildpath == None or not os.path.exists(ebuildpath):
+ return []
current = '-'.join(portage.catpkgsplit(current)[1:])
- if current.endswith('-r0'): current = current[:-3]
+ if current.endswith('-r0'):
+ current = current[:-3]
next = '-'.join(portage.catpkgsplit(next)[1:])
- if next.endswith('-r0'): next = next[:-3]
+ if next.endswith('-r0'):
+ next = next[:-3]
changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
try:
changelog = open(changelogpath).read()
if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
action_metadata(settings, portdb, myopts)
- if portage.global_updates(settings, trees, mtimedb["updates"]):
+ if portage._global_updates(trees, mtimedb["updates"]):
mtimedb.commit()
# Reload the whole config from scratch.
settings, trees, mtimedb = load_emerge_config(trees=trees)
portage.writemsg("!!! %s\n" % str(e))
del e
- if portage.global_updates(settings, trees, mtimedb["updates"]):
+ if portage._global_updates(trees, mtimedb["updates"]):
mtimedb.commit()
# Reload the whole config from scratch.
settings, trees, mtimedb = load_emerge_config(trees=trees)
atexit_register(portageexit)
-def global_updates(mysettings, trees, prev_mtimes):
+def _global_updates(trees, prev_mtimes):
"""
Perform new global updates if they exist in $PORTDIR/profiles/updates/.
- @param mysettings: A config instance for ROOT="/".
- @type mysettings: config
@param trees: A dictionary containing portage trees.
@type trees: dict
@param prev_mtimes: A dictionary containing mtimes of files located in
global secpass
if secpass < 2 or "SANDBOX_ACTIVE" in os.environ:
return
+ mysettings = trees["/"]["vartree"].settings
updpath = os.path.join(mysettings["PORTDIR"], "profiles", "updates")
try:
settings=mysettings)
vardb = trees["/"]["vartree"].dbapi
bindb = trees["/"]["bintree"].dbapi
+ if not os.access(bindb.bintree.pkgdir, os.W_OK):
+ bindb = None
for update_cmd in myupd:
if update_cmd[0] == "move":
moves = vardb.move_ent(update_cmd)
if moves:
writemsg_stdout(moves * "@")
- moves = bindb.move_ent(update_cmd)
- if moves:
- writemsg_stdout(moves * "%")
+ if bindb:
+ moves = bindb.move_ent(update_cmd)
+ if moves:
+ writemsg_stdout(moves * "%")
elif update_cmd[0] == "slotmove":
moves = vardb.move_slot_ent(update_cmd)
if moves:
writemsg_stdout(moves * "s")
- moves = bindb.move_slot_ent(update_cmd)
- if moves:
- writemsg_stdout(moves * "S")
+ if bindb:
+ moves = bindb.move_slot_ent(update_cmd)
+ if moves:
+ writemsg_stdout(moves * "S")
# The above global updates proceed quickly, so they
# are considered a single mtimedb transaction.
# We gotta do the brute force updates for these now.
if mysettings["PORTAGE_CALLER"] == "fixpackages" or \
"fixpackages" in mysettings.features:
- trees["/"]["bintree"].update_ents(myupd)
+ def onProgress(maxval, curval):
+ writemsg_stdout("*")
+ vardb.update_ents(myupd, onProgress=onProgress)
+ if bindb:
+ bindb.update_ents(myupd, onProgress=onProgress)
else:
do_upgrade_packagesmessage = 1
print
print
- if do_upgrade_packagesmessage and \
- listdir(os.path.join(mysettings["PKGDIR"], "All"), EmptyOnError=1):
+ if do_upgrade_packagesmessage and bindb and \
+ bindb.cpv_all():
writemsg_stdout(" ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the")
writemsg_stdout("\n tbz2's in the packages directory. "+bold("Note: This can take a very long time."))
writemsg_stdout("\n")
else:
writemsg("!!! Invalid db entry: %s\n" % mypath, noiselevel=-1)
+ def update_ents(self, updates, onProgress=None):
+ """
+ Update metadata of all packages for packages moves.
+ @param updates: A list of move commands
+ @type updates: List
+ @param onProgress: A progress callback function
+ @type onProgress: a callable that takes 2 integer arguments: maxval and curval
+ """
+ cpv_all = self.cpv_all()
+ cpv_all.sort()
+ maxval = len(cpv_all)
+ aux_get = self.aux_get
+ aux_update = self.aux_update
+ update_keys = ["DEPEND", "RDEPEND", "PDEPEND", "PROVIDE"]
+ from itertools import izip
+ from portage.update import update_dbentries
+ if onProgress:
+ onProgress(maxval, 0)
+ for i, cpv in enumerate(cpv_all):
+ metadata = dict(izip(update_keys, aux_get(cpv, update_keys)))
+ metadata_updates = update_dbentries(updates, metadata)
+ if metadata_updates:
+ aux_update(cpv, metadata_updates)
+ if onProgress:
+ onProgress(maxval, i+1)
+
+ def move_slot_ent(self, mylist):
+ pkg = mylist[1]
+ origslot = mylist[2]
+ newslot = mylist[3]
+ origmatches = self.match(pkg)
+ moves = 0
+ if not origmatches:
+ return moves
+ from portage.versions import catsplit
+ for mycpv in origmatches:
+ slot = self.aux_get(mycpv, ["SLOT"])[0]
+ if slot != origslot:
+ continue
+ moves += 1
+ mydata = {"SLOT": newslot+"\n"}
+ self.aux_update(mycpv, mydata)
+ return moves
def __init__(self, mybintree=None, settings=None):
self.bintree = mybintree
self.move_ent = mybintree.move_ent
- self.move_slot_ent = mybintree.move_slot_ent
self.cpvdict={}
self.cpdict={}
if settings is None:
mytbz2 = portage.xpak.tbz2(tbz2path)
mydata = mytbz2.get_data()
mydata.update(values)
+ for k, v in mydata.items():
+ if not v:
+ del mydata[k]
mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata))
+ self.bintree.inject(cpv)
def cp_list(self, *pargs, **kwargs):
if not self.bintree.populated:
self.bintree.populate()
return fakedbapi.cp_list(self, *pargs, **kwargs)
+ def cp_all(self):
+ if not self.bintree.populated:
+ self.bintree.populate()
+ return fakedbapi.cp_all(self)
+
def cpv_all(self):
if not self.bintree.populated:
self.bintree.populate()
return fakedbapi.cpv_all(self)
-
class binarytree(object):
"this tree scans for a list of all packages available in PKGDIR"
def __init__(self, root, pkgdir, virtual=None, settings=None, clone=None):
if clone:
+ writemsg("binartree.__init__(): deprecated " + \
+ "use of clone parameter\n", noiselevel=-1)
# XXX This isn't cloning. It's an instance of the same thing.
self.root = clone.root
self.pkgdir = clone.pkgdir
#self.pkgdir=settings["PKGDIR"]
self.pkgdir = normalize_path(pkgdir)
self.dbapi = bindbapi(self, settings=settings)
+ self.update_ents = self.dbapi.update_ents
+ self.move_slot_ent = self.dbapi.move_slot_ent
self.populated = 0
self.tree = {}
- self.remotepkgs = {}
+ self._remote_has_index = False
+ self._remotepkgs = None # remote metadata indexed by cpv
+ self.remotepkgs = {} # indexed by tbz2 name (deprecated)
self.invalids = []
self.settings = settings
self._pkg_paths = {}
self._remove_symlink(mycpv)
if new_path.split(os.path.sep)[-2] == "All":
self._create_symlink(mynewcpv)
- self.dbapi.cpv_inject(mynewcpv)
+ self.inject(mynewcpv)
return moves
del e
os.symlink(os.path.join("..", "All", mypkg + ".tbz2"), full_path)
- def move_slot_ent(self, mylist):
- if not self.populated:
- self.populate()
- pkg = mylist[1]
- origslot = mylist[2]
- newslot = mylist[3]
-
- if not isvalidatom(pkg):
- raise InvalidAtom(pkg)
-
- origmatches = self.dbapi.match(pkg)
- moves = 0
- if not origmatches:
- return moves
- for mycpv in origmatches:
- mycpsplit = catpkgsplit(mycpv)
- myoldpkg = mycpv.split("/")[1]
- tbz2path = self.getname(mycpv)
- if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
- writemsg("!!! Cannot update readonly binary: "+mycpv+"\n",
- noiselevel=-1)
- continue
-
- #print ">>> Updating data in:",mycpv
- mytbz2 = portage.xpak.tbz2(tbz2path)
- mydata = mytbz2.get_data()
-
- slot = mydata["SLOT"]
- if (not slot):
- continue
-
- if (slot[0] != origslot):
- continue
-
- moves += 1
- mydata["SLOT"] = newslot+"\n"
- mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata))
- return moves
-
- def update_ents(self, update_iter):
- if len(update_iter) == 0:
- return
- if not self.populated:
- self.populate()
-
- for mycpv in self.dbapi.cp_all():
- tbz2path = self.getname(mycpv)
- if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
- writemsg("!!! Cannot update readonly binary: "+mycpv+"\n",
- noiselevel=-1)
- continue
- #print ">>> Updating binary data:",mycpv
- writemsg_stdout("*")
- mytbz2 = portage.xpak.tbz2(tbz2path)
- mydata = mytbz2.get_data()
- updated_items = update_dbentries(update_iter, mydata)
- if len(updated_items) > 0:
- mydata.update(updated_items)
- mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata))
- return 1
-
def prevent_collision(self, cpv):
"""Make sure that the file location ${PKGDIR}/All/${PF}.tbz2 is safe to
use for a given cpv. If a collision will occur with an existing
noiselevel=-1)
if getbinpkgs and \
- self.settings["PORTAGE_BINHOST"] and not self.remotepkgs:
+ "PORTAGE_BINHOST" in self.settings and \
+ not self._remotepkgs:
+
+ base_url = self.settings["PORTAGE_BINHOST"]
+ from portage.const import CACHE_PATH
+ from urlparse import urlparse
+ urldata = urlparse(base_url)
+ pkgindex_file = os.path.join(CACHE_PATH, "binhost",
+ urldata[1] + urldata[2], "Packages")
+ pkgindex = portage.getbinpkg.PackageIndex()
+ try:
+ f = open(pkgindex_file)
+ try:
+ pkgindex.read(f)
+ finally:
+ f.close()
+ except EnvironmentError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ local_timestamp = pkgindex.header.get("TIMESTAMP", None)
+ import urllib, urlparse
+ rmt_idx = portage.getbinpkg.PackageIndex()
+ try:
+ f = urllib.urlopen(urlparse.urljoin(base_url, "Packages"))
+ try:
+ rmt_idx.readHeader(f)
+ remote_timestamp = rmt_idx.header.get("TIMESTAMP", None)
+ if not remote_timestamp:
+ # no timestamp in the header, something's wrong
+ pkgindex = None
+ else:
+ if local_timestamp != remote_timestamp:
+ rmt_idx.readBody(f)
+ pkgindex = rmt_idx
+ finally:
+ f.close()
+ except EnvironmentError, e:
+ writemsg("\n\n!!! Error fetching binhost package" + \
+ " info from '%s'\n" % base_url)
+ writemsg("!!! %s\n\n" % str(e))
+ del e
+ pkgindex = None
+ if pkgindex is rmt_idx:
+ pkgindex.modified = False # don't update the header
+ from portage.util import atomic_ofstream, ensure_dirs
+ ensure_dirs(os.path.dirname(pkgindex_file))
+ f = atomic_ofstream(pkgindex_file)
+ try:
+ pkgindex.write(f)
+ finally:
+ f.close()
+ if pkgindex:
+ self._remotepkgs = pkgindex.packages
+ self._remote_has_index = True
+ self.remotepkgs = {}
+ for cpv, metadata in self._remotepkgs.iteritems():
+ self.dbapi.cpv_inject(cpv)
+ cat, pf = catsplit(cpv)
+ # backward compat
+ self.remotepkgs[pf+".tbz2"] = metadata
+ metadata["CATEGORY"] = cat
+ self.populated = 1
+ return
+ self._remotepkgs = {}
try:
chunk_size = long(self.settings["PORTAGE_BINHOST_CHUNKSIZE"])
if chunk_size < 8:
chunk_size = 8
except (ValueError, KeyError):
chunk_size = 3000
-
- writemsg(green("Fetching binary packages info...\n"))
+ writemsg_stdout(green("Fetching binary packages info...\n"))
self.remotepkgs = portage.getbinpkg.dir_get_metadata(
self.settings["PORTAGE_BINHOST"], chunk_size=chunk_size)
writemsg(green(" -- DONE!\n\n"))
# invalid tbz2's can hurt things.
#print "cpv_inject("+str(fullpkg)+")"
self.dbapi.cpv_inject(fullpkg)
+ metadata = self.remotepkgs[mypkg]
+ for k, v in metadata.items():
+ metadata[k] = v.strip()
+ self._remotepkgs[fullpkg] = metadata
#print " -- Injected"
except SystemExit, e:
raise
os.makedirs(mydest, 0775)
except (OSError, IOError):
pass
- success = portage.getbinpkg.file_get(
- self.settings["PORTAGE_BINHOST"] + "/" + tbz2name,
- mydest, fcmd=self.settings["RESUMECOMMAND"])
- self.inject(pkgname)
+ from urlparse import urljoin
+ base_url = self.settings["PORTAGE_BINHOST"]
+ fcmd = self.settings["RESUMECOMMAND"]
+ if self._remote_has_index:
+ url = urljoin(base_url, pkgname+".tbz2")
+ success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd)
+ if not success:
+ try:
+ os.unlink(self.getname(pkgname))
+ except OSError:
+ pass
+ # Fall back to the "All" directory
+ url = urljoin(base_url, "All/"+tbz2name)
+ success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd)
+ else:
+ url = urljoin(base_url, tbz2name)
+ success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd)
+ if success:
+ self.inject(pkgname)
return success
def getslot(self, mycatpkg):
"""
if clone:
+ writemsg("portagetree.__init__(): deprecated " + \
+ "use of clone parameter\n", noiselevel=-1)
self.root = clone.root
self.portroot = clone.portroot
self.pkglines = clone.pkglines
fixdbentries([mylist], newpath)
return moves
- def update_ents(self, update_iter):
- """Run fixdbentries on all installed packages (time consuming). Like
- fixpackages, this should be run from a helper script and display
- a progress indicator."""
- dbdir = os.path.join(self.root, VDB_PATH)
- for catdir in listdir(dbdir):
- catdir = dbdir+"/"+catdir
- if os.path.isdir(catdir):
- for pkgdir in listdir(catdir):
- pkgdir = catdir+"/"+pkgdir
- if os.path.isdir(pkgdir):
- fixdbentries(update_iter, pkgdir)
-
- def move_slot_ent(self, mylist):
- pkg = mylist[1]
- origslot = mylist[2]
- newslot = mylist[3]
-
- if not isvalidatom(pkg):
- raise InvalidAtom(pkg)
-
- origmatches = self.match(pkg, use_cache=0)
- moves = 0
- if not origmatches:
- return moves
- for mycpv in origmatches:
- origpath = self.getpath(mycpv)
- if not os.path.exists(origpath):
- continue
-
- slot = grabfile(os.path.join(origpath, "SLOT"));
- if (not slot):
- continue
-
- if (slot[0] != origslot):
- continue
-
- moves += 1
- write_atomic(os.path.join(origpath, "SLOT"), newslot+"\n")
- return moves
-
def cp_list(self, mycp, use_cache=1):
mysplit=catsplit(mycp)
if mysplit[0] == '*':
if not mylink.exists():
raise KeyError(cpv)
for k, v in values.iteritems():
- mylink.setfile(k, v)
+ if v:
+ mylink.setfile(k, v)
+ else:
+ try:
+ os.unlink(os.path.join(self.getpath(cpv), k))
+ except EnvironmentError:
+ pass
def counter_tick(self, myroot, mycpv=None):
return self.counter_tick_core(myroot, incrementing=1, mycpv=mycpv)
def __init__(self, root="/", virtual=None, clone=None, categories=None,
settings=None):
if clone:
+ writemsg("vartree.__init__(): deprecated " + \
+ "use of clone parameter\n", noiselevel=-1)
self.root = clone.root[:]
self.dbapi = copy.deepcopy(clone.dbapi)
self.populated = 1
# Check that each flag matches
ismatch = True
+ missing_flag = False
for head in newdeparray[:-1]:
head = head[:-1]
- if head[0] == "!":
+ if not head:
+ missing_flag = True
+ break
+ if head.startswith("!"):
head_key = head[1:]
+ if not head_key:
+ missing_flag = True
+ break
if not matchall and head_key in uselist or \
head_key in excludeall:
ismatch = False
break
else:
ismatch = False
+ if missing_flag:
+ raise portage_exception.InvalidDependString(
+ "Conditional without flag: \"" + \
+ paren_enclose([head+"?", newdeparray[-1]])+"\"")
# If they all match, process the target
if ismatch:
"""
if mydep:
mydep = remove_slot(mydep)
+ if not mydep:
+ return None
if mydep[0] == "~":
operator = "~"
elif mydep[0] == "=":
def __init__(self):
self.header = {}
self.packages = {}
+ self.modified = True
def read(self, pkgfile):
+ self.readHeader(pkgfile)
+ self.readBody(pkgfile)
+
+ def readHeader(self, pkgfile):
self.header.update(readpkgindex(pkgfile))
+
+ def readBody(self, pkgfile):
while True:
d = readpkgindex(pkgfile)
if not d:
def write(self, pkgfile):
cpv_all = self.packages.keys()
cpv_all.sort()
- import time
- self.header["TIMESTAMP"] = str(long(time.time()))
- self.header["PACKAGES"] = str(len(cpv_all))
+ if self.modified:
+ import time
+ self.header["TIMESTAMP"] = str(long(time.time()))
+ self.header["PACKAGES"] = str(len(cpv_all))
keys = self.header.keys()
keys.sort()
writepkgindex(pkgfile, [(k, self.header[k]) for k in keys])
timestamp = 0
path = os.path.join(self.portdb.getRepositoryPath(repoid), self.NEWS_PATH)
- newsdir_lock = None
- try:
- repo_path = self.portdb.getRepositoryPath(repoid)
- if os.access(os.path.dirname(repo_path), os.W_OK):
- # This lock file should really be mapped into /var somewhere
- # since the repo_path or it's parent directory may not even be
- # writable.
- newsdir_lock = lockdir(repo_path)
- # Skip reading news for repoid if the news dir does not exist. Requested by
- # NightMorph :)
- if not os.path.exists(path):
- return None
- news = os.listdir(path)
- updates = []
- for itemid in news:
- try:
- filename = os.path.join(path, itemid, itemid + "." + self.LANGUAGE_ID + ".txt")
- item = NewsItem(filename, itemid, timestamp)
- except (TypeError, ValueError), e:
- continue
- if item.isRelevant(profile=os.readlink(PROFILE_PATH), config=config, vardb=self.vdb):
- updates.append(item)
- finally:
- if newsdir_lock:
- unlockdir(newsdir_lock)
-
+
+ repo_path = self.portdb.getRepositoryPath(repoid)
+ # Skip reading news for repoid if the news dir does not exist. Requested by
+ # NightMorph :)
+ if not os.path.exists(path):
+ return None
+ news = os.listdir(path)
+ updates = []
+ for itemid in news:
+ try:
+ filename = os.path.join(path, itemid, itemid + "." + self.LANGUAGE_ID + ".txt")
+ item = NewsItem(filename, itemid, timestamp)
+ except (TypeError, ValueError), e:
+ continue
+ if item.isRelevant(profile=os.readlink(PROFILE_PATH), config=config, vardb=self.vdb):
+ updates.append(item)
del path
path = os.path.join(self.UNREAD_PATH, "news-"+repoid+".unread")