# Make IUSE defaults backward compatible with all the old shell code.
iuse_temp=""
for x in ${IUSE} ; do
- if [[ ${x} == +* ]]; then
+ if [[ ${x} == +* ]] || [[ ${x} == -* ]] ; then
iuse_temp="${iuse_temp} ${x:1}"
else
iuse_temp="${iuse_temp} ${x}"
find "${dir}" -type f -name '*.ecompress.file' -print0 | ${XARGS} -0 rm -f
# not uncommon for packages to compress doc files themselves
- funk_up_dir "decompress" ".Z" "gunzip"
- funk_up_dir "decompress" ".gz" "gunzip"
- funk_up_dir "decompress" ".bz2" "bunzip2"
+ funk_up_dir "decompress" ".Z" "gunzip -f"
+ funk_up_dir "decompress" ".gz" "gunzip -f"
+ funk_up_dir "decompress" ".bz2" "bunzip2 -f"
# forcibly break all hard links as some compressors whine about it
find "${dir}" -type f -links +1 -exec env file="{}" sh -c \
self.not_installed = []
self.invalid_category = []
self.okay = []
- self.world_file = os.path.join("/", portage.const.WORLD_FILE)
- self.found = os.access(self.world_file, os.R_OK)
def _check_world(self, onProgress):
categories = set(portage.settings.categories)
myroot = portage.settings["ROOT"]
+ self.world_file = os.path.join(myroot, portage.const.WORLD_FILE)
+ self.found = os.access(self.world_file, os.R_OK)
vardb = portage.db[myroot]["vartree"].dbapi
world_atoms = open(self.world_file).read().split()
locks.unlockfile(pkgindex_lock)
return None
+class MoveHandler(object):
+
+ def __init__(self, tree):
+ self._tree = tree
+ self._portdir = tree.settings["PORTDIR"]
+ self._update_keys = ["DEPEND", "RDEPEND", "PDEPEND", "PROVIDE"]
+
+ def _grab_global_updates(self, portdir):
+ from portage.update import grab_updates, parse_updates
+ updpath = os.path.join(portdir, "profiles", "updates")
+ try:
+ rawupdates = grab_updates(updpath)
+ except portage.exception.DirectoryNotFound:
+ rawupdates = []
+ upd_commands = []
+ errors = []
+ for mykey, mystat, mycontent in rawupdates:
+ commands, errors = parse_updates(mycontent)
+ upd_commands.extend(commands)
+ errors.extend(errors)
+ return upd_commands, errors
+
+ def check(self, onProgress=None):
+ updates, errors = self._grab_global_updates(self._portdir)
+ # Matching packages and moving them is relatively fast, so the
+ # progress bar is updated in indeterminate mode.
+ match = self._tree.dbapi.match
+ aux_get = self._tree.dbapi.aux_get
+ if onProgress:
+ onProgress(0, 0)
+ for i, update_cmd in enumerate(updates):
+ if update_cmd[0] == "move":
+ origcp, newcp = update_cmd[1:]
+ for cpv in match(origcp):
+ errors.append("'%s' moved to '%s'" % (cpv, newcp))
+ elif update_cmd[0] == "slotmove":
+ pkg, origslot, newslot = update_cmd[1:]
+ for cpv in match(pkg):
+ slot = aux_get(cpv, ["SLOT"])[0]
+ if slot == origslot:
+ errors.append("'%s' slot moved from '%s' to '%s'" % \
+ (cpv, origslot, newslot))
+ if onProgress:
+ onProgress(0, 0)
+
+ # 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_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:
+ errors.append("'%s' has outdated metadata" % cpv)
+ if onProgress:
+ onProgress(maxval, i+1)
+ return errors
+
+ def fix(self, onProgress=None):
+ updates, errors = self._grab_global_updates(self._portdir)
+ # Matching packages and moving them is relatively fast, so the
+ # progress bar is updated in indeterminate mode.
+ move = self._tree.dbapi.move_ent
+ slotmove = self._tree.dbapi.move_slot_ent
+ if onProgress:
+ onProgress(0, 0)
+ for i, update_cmd in enumerate(updates):
+ if update_cmd[0] == "move":
+ move(update_cmd)
+ elif update_cmd[0] == "slotmove":
+ slotmove(update_cmd)
+ if onProgress:
+ onProgress(0, 0)
+
+ # 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)
+ return errors
+
+class MoveInstalled(MoveHandler):
+ def name():
+ return "moveinst"
+ name = staticmethod(name)
+ def __init__(self):
+ myroot = portage.settings["ROOT"]
+ MoveHandler.__init__(self, portage.db[myroot]["vartree"])
+
+class MoveBinary(MoveHandler):
+ def name():
+ return "movebin"
+ name = staticmethod(name)
+ def __init__(self):
+ myroot = portage.settings["ROOT"]
+ MoveHandler.__init__(self, portage.db[myroot]["bintree"])
+
class VdbKeyHandler(object):
def name():
return "vdbkeys"
# the need for hard coding.
modules = {
"world" : WorldHandler,
- "binhost":BinhostHandler
+ "binhost":BinhostHandler,
+ "moveinst":MoveInstalled,
+ "movebin":MoveBinary
}
module_names = modules.keys()
it will increment it. For more information about nice levels and what
are acceptable ranges, see \fBnice\fR(1).
.TP
+\fBPORTAGE_RSYNC_INITIAL_TIMEOUT\fR = \fIinteger\fR
+Used by \fBemerge \-\-sync\fR as a timeout for the initial connection to an
+rsync server.
+.br
+Defaults to 15 seconds.
+.TP
\fBPORTAGE_RSYNC_EXTRA_OPTS\fR = \fI[rsync options string]\fR
Additional rsync options to be used by \fBemerge \-\-sync\fR.
.br
print "Searching... ",
regexsearch = False
- if self.searchkey[0] == '%':
+ if self.searchkey.startswith('%'):
regexsearch = True
self.searchkey = self.searchkey[1:]
- if self.searchkey[0] == '@':
+ if self.searchkey.startswith('@'):
match_category = 1
self.searchkey = self.searchkey[1:]
if regexsearch:
def filter_iuse_defaults(iuse):
for flag in iuse:
- if flag.startswith("+"):
+ if flag.startswith("+") or flag.startswith("-"):
yield flag[1:]
else:
yield flag
pass
del content
+ try:
+ rsync_initial_timeout = \
+ int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
+ except ValueError:
+ rsync_initial_timeout = 15
+
try:
if settings.has_key("RSYNC_RETRIES"):
print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
# Timeout here in case the server is unresponsive. The
# --timeout rsync option doesn't apply to the initial
# connection attempt.
- signal.alarm(15)
+ if rsync_initial_timeout:
+ signal.alarm(rsync_initial_timeout)
try:
mypids.extend(portage.process.spawn(
mycommand, env=settings.environ(), returnpid=True))
exitcode = os.waitpid(mypids[0], 0)[1]
content = portage.grabfile(tmpservertimestampfile)
finally:
- signal.alarm(0)
+ if rsync_initial_timeout:
+ signal.alarm(0)
try:
os.unlink(tmpservertimestampfile)
except OSError:
has_changed = False
self.mycpv = mycpv
cp = dep_getkey(mycpv)
+ cpv_slot = self.mycpv
pkginternaluse = ""
if mydb:
- pkginternaluse = " ".join([x[1:] \
- for x in mydb.aux_get(mycpv, ["IUSE"])[0].split() \
- if x.startswith("+")])
+ slot, iuse = mydb.aux_get(self.mycpv, ["SLOT", "IUSE"])
+ cpv_slot = "%s:%s" % (self.mycpv, slot)
+ pkginternaluse = []
+ for x in iuse.split():
+ if x.startswith("+"):
+ pkginternaluse.append(x[1:])
+ elif x.startswith("-"):
+ pkginternaluse.append(x)
+ pkginternaluse = " ".join(pkginternaluse)
if pkginternaluse != self.configdict["pkginternal"].get("USE", ""):
self.configdict["pkginternal"]["USE"] = pkginternaluse
has_changed = True
defaults.append(self.make_defaults_use[i])
cpdict = self.pkgprofileuse[i].get(cp, None)
if cpdict:
- best_match = best_match_to_list(self.mycpv, cpdict.keys())
+ best_match = best_match_to_list(cpv_slot, cpdict.keys())
if best_match:
defaults.append(cpdict[best_match])
defaults = " ".join(defaults)
useforce.append(self.useforce_list[i])
cpdict = self.puseforce_list[i].get(cp, None)
if cpdict:
- best_match = best_match_to_list(self.mycpv, cpdict.keys())
+ best_match = best_match_to_list(cpv_slot, cpdict.keys())
if best_match:
useforce.append(cpdict[best_match])
useforce = set(stack_lists(useforce, incremental=True))
usemask.append(self.usemask_list[i])
cpdict = self.pusemask_list[i].get(cp, None)
if cpdict:
- best_match = best_match_to_list(self.mycpv, cpdict.keys())
+ best_match = best_match_to_list(cpv_slot, cpdict.keys())
if best_match:
usemask.append(cpdict[best_match])
usemask = set(stack_lists(usemask, incremental=True))
has_changed = True
oldpuse = self.puse
self.puse = ""
- if self.pusedict.has_key(cp):
- self.pusekey = best_match_to_list(self.mycpv, self.pusedict[cp].keys())
+ cpdict = self.pusedict.get(cp)
+ if cpdict:
+ self.pusekey = best_match_to_list(cpv_slot, cpdict.keys())
if self.pusekey:
- self.puse = " ".join(self.pusedict[cp][self.pusekey])
+ self.puse = " ".join(cpdict[self.pusekey])
if oldpuse != self.puse:
has_changed = True
self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
trees["/"]["bintree"] = binarytree("/", mysettings["PKGDIR"],
settings=mysettings)
+ vardb = trees["/"]["vartree"].dbapi
+ bindb = trees["/"]["bintree"].dbapi
for update_cmd in myupd:
if update_cmd[0] == "move":
- trees["/"]["vartree"].dbapi.move_ent(update_cmd)
- trees["/"]["bintree"].move_ent(update_cmd)
+ moves = vardb.move_ent(update_cmd)
+ if moves:
+ writemsg_stdout(moves * "@")
+ moves = bindb.move_ent(update_cmd)
+ if moves:
+ writemsg_stdout(moves * "%")
elif update_cmd[0] == "slotmove":
- trees["/"]["vartree"].dbapi.move_slot_ent(update_cmd)
- trees["/"]["bintree"].move_slot_ent(update_cmd)
+ 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")
# The above global updates proceed quickly, so they
# are considered a single mtimedb transaction.
class bindbapi(fakedbapi):
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:
origcat = origcp.split("/")[0]
mynewcat = newcp.split("/")[0]
origmatches=self.dbapi.cp_list(origcp)
+ moves = 0
if not origmatches:
- return
+ return moves
for mycpv in origmatches:
mycpsplit = catpkgsplit(mycpv)
noiselevel=-1)
continue
- #print ">>> Updating data in:",mycpv
- writemsg_stdout("%")
+ moves += 1
mytbz2 = portage.xpak.tbz2(tbz2path)
mydata = mytbz2.get_data()
updated_items = update_dbentries([mylist], mydata)
self._create_symlink(mynewcpv)
self.dbapi.cpv_inject(mynewcpv)
- return 1
+ return moves
def _remove_symlink(self, cpv):
"""Remove a ${PKGDIR}/${CATEGORY}/${PF}.tbz2 symlink and also remove
raise InvalidAtom(pkg)
origmatches = self.dbapi.match(pkg)
+ moves = 0
if not origmatches:
- return
+ return moves
for mycpv in origmatches:
mycpsplit = catpkgsplit(mycpv)
myoldpkg = mycpv.split("/")[1]
if (slot[0] != origslot):
continue
- writemsg_stdout("S")
+ moves += 1
mydata["SLOT"] = newslot+"\n"
mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata))
- return 1
+ return moves
def update_ents(self, update_iter):
if len(update_iter) == 0:
use = d["USE"].split()
iuse = set(d["IUSE"].split())
use = [f for f in use if f in iuse]
- del iuse, d["IUSE"]
+ if not iuse:
+ del d["IUSE"]
use.sort()
d["USE"] = " ".join(use)
d["DESC"] = d["DESCRIPTION"]
else:
writemsg("Resuming download of this tbz2, but it is possible that it is corrupt.\n",
noiselevel=-1)
- mydest = self.pkgdir + "/All/"
+ mydest = os.path.dirname(self.getname(pkgname))
try:
os.makedirs(mydest, 0775)
except (OSError, IOError):
pass
- return portage.getbinpkg.file_get(
+ success = portage.getbinpkg.file_get(
self.settings["PORTAGE_BINHOST"] + "/" + tbz2name,
mydest, fcmd=self.settings["RESUMECOMMAND"])
+ self.inject(pkgname)
+ return success
def getslot(self, mycatpkg):
"Get a slot for a catpkg; assume it exists."
if not (isvalidatom(cp) and isjustname(cp)):
raise InvalidPackageName(cp)
origmatches = self.match(origcp, use_cache=0)
+ moves = 0
if not origmatches:
- return
+ return moves
for mycpv in origmatches:
mycpsplit = catpkgsplit(mycpv)
mynewcpv = newcp + "-" + mycpsplit[2]
origpath = self.getpath(mycpv)
if not os.path.exists(origpath):
continue
- writemsg_stdout("@")
+ moves += 1
if not os.path.exists(self.getpath(mynewcat)):
#create the directory
os.makedirs(self.getpath(mynewcat))
write_atomic(os.path.join(newpath, "CATEGORY"), mynewcat+"\n")
fixdbentries([mylist], newpath)
+ return moves
def update_ents(self, update_iter):
"""Run fixdbentries on all installed packages (time consuming). Like
raise InvalidAtom(pkg)
origmatches = self.match(pkg, use_cache=0)
-
+ moves = 0
if not origmatches:
- return
+ return moves
for mycpv in origmatches:
origpath = self.getpath(mycpv)
if not os.path.exists(origpath):
if (slot[0] != origslot):
continue
- writemsg_stdout("s")
+ moves += 1
write_atomic(os.path.join(origpath, "SLOT"), newslot+"\n")
+ return moves
def cp_list(self, mycp, use_cache=1):
mysplit=catsplit(mycp)
@return: The operator. One of:
'~', '=', '>', '<', '=*', '>=', or '<='
"""
+ if mydep:
+ mydep = remove_slot(mydep)
if mydep[0] == "~":
operator = "~"
elif mydep[0] == "=":
if retval is not None:
return retval
mydep_orig = mydep
+ if mydep:
+ mydep = remove_slot(mydep)
if mydep and mydep[0] == "*":
mydep = mydep[1:]
if mydep and mydep[-1] == "*":
mydep = mydep[2:]
elif mydep[:1] in "=<>~":
mydep = mydep[1:]
- colon = mydep.rfind(":")
- if colon != -1:
- mydep = mydep[:colon]
_dep_getcpv_cache[mydep_orig] = mydep
return mydep
return mydep[colon+1:]
return None
+def remove_slot(mydep):
+ colon = mydep.rfind(":")
+ if colon != -1:
+ mydep = mydep[:colon]
+ return mydep
+
def dep_getusedeps( depend ):
"""
Pull a listing of USE Dependencies out of a dep atom.
if maxvalue < 3:
maxvalue = 3
bestm = x
- continue
op_val = operator_values[get_operator(x)]
if op_val > maxvalue:
maxvalue = op_val
mycpv = dep_getcpv(mydep)
mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
- slot = None
+ slot = dep_getslot(mydep)
if not mycpv_cps:
cat, pkg = catsplit(mycpv)
ver = None
rev = None
- slot = dep_getslot(mydep)
else:
cat, pkg, ver, rev = mycpv_cps
if mydep == mycpv:
if operator is None:
for x in candidate_list:
- xs = pkgsplit(x)
- if xs is None:
- xcpv = dep_getcpv(x)
- if slot is not None:
- xslot = dep_getslot(x)
- if xslot is not None and xslot != slot:
- """ This function isn't given enough information to
- reject atoms based on slot unless *both* compared atoms
- specify slots."""
- continue
- if xcpv != mycpv:
- continue
- elif xs[0] != mycpv:
+ if dep_getkey(x) != mycpv:
continue
mylist.append(x)
elif operator == "=": # Exact match
- mylist = [cpv for cpv in candidate_list if cpvequal(cpv, mycpv)]
+ mylist = [cpv for cpv in candidate_list if \
+ cpvequal(remove_slot(cpv), mycpv)]
elif operator == "=*": # glob match
# XXX: Nasty special casing for leading zeros
myver = "0"+myver
mycpv = mysplit[0]+"/"+mysplit[1]+"-"+myver
for x in candidate_list:
- xs = catpkgsplit(x)
+ xs = catpkgsplit(remove_slot(x))
myver = xs[2].lstrip("0")
if not myver or not myver[0].isdigit():
myver = "0"+myver
elif operator == "~": # version, any revision, match
for x in candidate_list:
- xs = catpkgsplit(x)
+ xs = catpkgsplit(remove_slot(x))
if xs is None:
raise InvalidData(x)
if not cpvequal(xs[0]+"/"+xs[1]+"-"+xs[2], mycpv_cps[0]+"/"+mycpv_cps[1]+"-"+mycpv_cps[2]):
mysplit = ["%s/%s" % (cat, pkg), ver, rev]
for x in candidate_list:
try:
- result = pkgcmp(pkgsplit(x), mysplit)
+ result = pkgcmp(pkgsplit(remove_slot(x)), mysplit)
except ValueError: # pkgcmp may return ValueError during int() conversion
writemsg("\nInvalid package name: %s\n" % x, noiselevel=-1)
raise
else:
raise KeyError("Unknown operator: %s" % mydep)
+ if slot is not None:
+ candidate_list = mylist
+ mylist = []
+ for x in candidate_list:
+ xslot = dep_getslot(x)
+ if xslot is not None and xslot != slot:
+ continue
+ mylist.append(x)
+
_match_from_list_cache[cache_key] = mylist
- return mylist
+ return mylist[:]
self._maxval = maxval
if value < 0:
value = 0
- elif value > maxval:
- value = maxval
+ elif value > self._maxval:
+ value = self._maxval
self._curval = value
def inc(self, n=1):
lines, self.term_columns = get_term_size()
self.file = sys.stdout
self._min_columns = 11
+ self._max_columns = 80
# for indeterminate mode, ranges from 0.0 to 1.0
self._position = 0.0
def _create_image(self):
cols = self.term_columns
+ if cols > self._max_columns:
+ cols = self._max_columns
min_columns = self._min_columns
curval = self._curval
maxval = self._maxval