desc_path = os.path.join(path, 'profiles', 'profiles.desc')
try:
- desc_file = codecs.open(desc_path, mode='r', errors='replace')
+ desc_file = codecs.open(desc_path, mode='r',
+ encoding='utf_8', errors='replace')
except EnvironmentError:
pass
else:
continue
try:
line = 1
- for l in codecs.open(checkdir+"/"+y, "r", "utf8"):
+ for l in codecs.open(os.path.join(checkdir, y), mode='r',
+ encoding='utf_8'):
line +=1
except UnicodeDecodeError, ue:
stats["file.UTF8"] += 1
# Default user options
FEATURES="assume-digests distlocks fixpackages parallel-fetch protect-owned
- sandbox sfperms strict unmerge-orphans userfetch"
+ sandbox sfperms strict unmerge-logs unmerge-orphans userfetch"
# Ignore file collisions in /lib/modules since files inside this directory
# are never unmerged, and therefore collisions must be ignored in order for
Note that the test phase for a specific package may be disabled by masking
the "test" \fBUSE\fR flag in \fBpackage.use.mask\fR (see \fBportage\fR(5)).
.TP
+.B unmerge\-logs
+Keep logs from successful unmerge phases. This is relevant only when
+\fBPORT_LOGDIR\fR is set.
+.TP
.B unmerge\-orphans
If a file is not claimed by another package in the same slot and it is not
protected by \fICONFIG_PROTECT\fR, unmerge it even if the modification time or
'newline' : 'nel',
}
- def __init__(self, out=sys.stdout, quiet=False, xterm_titles=True):
- object.__setattr__(self, "out", out)
+ def __init__(self, quiet=False, xterm_titles=True):
object.__setattr__(self, "quiet", quiet)
object.__setattr__(self, "xterm_titles", xterm_titles)
object.__setattr__(self, "maxval", 0)
object.__setattr__(self, "width", 80)
self.reset()
- isatty = hasattr(out, "isatty") and out.isatty()
+ isatty = hasattr(self.out, "isatty") and self.out.isatty()
object.__setattr__(self, "_isatty", isatty)
if not isatty or not self._init_term():
term_codes = {}
if not isinstance(v, basestring):
self._term_codes[k] = v.decode(encoding, 'replace')
+ @property
+ def out(self):
+ """Use a lazy reference to sys.stdout, in case the API consumer has
+ temporarily overridden stdout."""
+ return sys.stdout
+
def _init_term(self):
"""
Initialize term control codes.
# at the beginning, which annoy users, never
# spawn a prefetcher for the first package.
for pkg in self._mergelist[1:]:
- if pkg.operation == "uninstall":
+ # mergelist can contain solved Blocker instances
+ if not isinstance(pkg, Package) or pkg.operation == "uninstall":
continue
prefetcher = self._create_prefetcher(pkg)
if prefetcher is not None:
a non-essential package with a broken digest.
"""
mtimedb = self._mtimedb
+
+ mtimedb["resume"] = {}
+ # Stored as a dict starting with portage-2.1.6_rc1, and supported
+ # by >=portage-2.1.3_rc8. Versions <portage-2.1.3_rc8 only support
+ # a list type for options.
+ mtimedb["resume"]["myopts"] = self.myopts.copy()
+
+ # Convert Atom instances to plain str.
+ mtimedb["resume"]["favorites"] = [str(x) for x in self._favorites]
mtimedb["resume"]["mergelist"] = [list(x) \
for x in self._mergelist \
if isinstance(x, Package) and x.operation == "merge"]
mtimedb["resume_backup"] = mtimedb["resume"]
del mtimedb["resume"]
mtimedb.commit()
- mtimedb["resume"]={}
- # Stored as a dict starting with portage-2.1.6_rc1, and supported
- # by >=portage-2.1.3_rc8. Versions <portage-2.1.3_rc8 only support
- # a list type for options.
- mtimedb["resume"]["myopts"] = myopts.copy()
-
- # Convert Atom instances to plain str.
- mtimedb["resume"]["favorites"] = [str(x) for x in favorites]
pkglist = mydepgraph.altlist()
mydepgraph.saveNomergeFavorites()
cleanlist = [pkg.cpv for pkg in graph.order]
else:
# Order nodes from lowest to highest overall reference count for
- # optimal root node selection.
+ # optimal root node selection (this can help minimize issues
+ # with unaccounted implicit dependencies).
node_refcounts = {}
for node in graph.order:
node_refcounts[node] = len(graph.parent_nodes(node))
repo_conf_parser = SafeConfigParser()
try:
repo_conf_parser.readfp(
- codecs.open(self._local_repo_conf_path,
- mode='r', errors='replace'))
+ codecs.open(self._local_repo_conf_path, mode='r',
+ encoding='utf_8', errors='replace'))
except EnvironmentError, e:
if e.errno != errno.ENOENT:
raise
catdir_lock = None
scheduler = self._scheduler
retval = -1
+ failures = 0
try:
if myebuildpath:
catdir_lock = lockdir(catdir)
# XXX: Decide how to handle failures here.
if retval != os.EX_OK:
+ failures += 1
writemsg(_("!!! FAILED prerm: %s\n") % retval, noiselevel=-1)
self._unmerge_pkgfiles(pkgfiles, others_in_slot)
# XXX: Decide how to handle failures here.
if retval != os.EX_OK:
+ failures += 1
writemsg(_("!!! FAILED postrm: %s\n") % retval, noiselevel=-1)
# Skip this if another package in the same slot has just been
del e
unlockdir(catdir_lock)
+ if log_path is not None:
+
+ if not failures and 'unmerge-logs' not in self.settings.features:
+ try:
+ os.unlink(log_path)
+ except OSError:
+ pass
+
+ try:
+ st = os.stat(log_path)
+ except OSError:
+ pass
+ else:
+ if st.st_size == 0:
+ try:
+ os.unlink(log_path)
+ except OSError:
+ pass
+
if log_path is not None and os.path.exists(log_path):
# Restore this since it gets lost somewhere above and it
# needs to be set for _display_merge() to be able to log.
# once, which may be expensive due to digging in child classes.
func = self.lineParser
for fn in RecursiveFileLoader(self.fname):
- f = codecs.open(fn, mode='r', errors='replace')
+ f = codecs.open(fn, mode='r', encoding='utf_8', errors='replace')
for line_num, line in enumerate(f):
func(line, line_num, data, errors)
return (data, errors)
return token
try:
lineno=0
- for line in codecs.open( myfile, mode = 'r', errors = 'replace' ):
+ for line in codecs.open( myfile, mode='r',
+ encoding='utf_8', errors='replace' ):
lineno += 1
commenter_pos = line.find("#")
else:
try:
myfile = codecs.open(myfilename, mode='r',
- encoding=sys.getdefaultencoding(), errors='replace')
+ encoding='utf_8', errors='replace')
mylines = myfile.readlines()
myfile.close()
except IOError, e:
# Workaround for avoiding a silent error in shlex that
# is triggered by a source statement at the end of the file without a
# trailing newline after the source statement
- content = codecs.open(mycfg, mode='r', errors='replace').read()
- if content and content[-1] != u'\n':
- content += u'\n'
- f = StringIO(content)
+ # NOTE: shex doesn't seem to supported unicode objects
+ # (produces spurious \0 characters with python-2.6.2)
+ content = open(mycfg).read()
+ if content and content[-1] != '\n':
+ content += '\n'
except IOError, e:
if e.errno == PermissionDenied.errno:
raise PermissionDenied(mycfg)
# The default shlex.sourcehook() implementation
# only joins relative paths when the infile
# attribute is properly set.
- lex = shlex_class(f, infile=mycfg, posix=True)
+ lex = shlex_class(content, infile=mycfg, posix=True)
lex.wordchars = string.digits + string.ascii_letters + \
"~!@#$%*_\:;?,./-+{}"
lex.quotes="\"'"
open_func = open
else:
open_func = codecs.open
+ kargs.setdefault('encoding', 'utf_8')
kargs.setdefault('errors', 'replace')
if follow_links: