diff options
author | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:24:26 +0100 |
---|---|---|
committer | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:24:26 +0100 |
commit | 3a63f58d0993f66975cd324eb85f4a2340d4f7c3 (patch) | |
tree | bb48a71faf4016196f9f8bc42ba2173bccf57e9f | |
parent | Convert forced flags from new multilib eclass to the matching ones from multi... (diff) | |
parent | Updates for a release (diff) | |
download | portage-3a63f58d.tar.gz portage-3a63f58d.tar.bz2 portage-3a63f58d.zip |
Merge tag 'v2.2.23' into multilib
New release
52 files changed, 310 insertions, 125 deletions
diff --git a/.travis.yml b/.travis.yml index 8a86aa69f..237963f14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ python: - 2.7 - 3.3 - 3.4 + - 3.5 - pypy script: - ./setup.py test @@ -2,8 +2,8 @@ About Portage ============= Portage is a package management system based on ports collections. The -Package Manager Specification Project (PMS) standardises and documents -the behaviour of Portage so that the Portage tree can be used by other +Package Manager Specification Project (PMS) standardises and documents +the behaviour of Portage so that the Portage tree can be used by other package managers. @@ -28,7 +28,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Portage; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -44,6 +44,6 @@ More information Links ===== -Gentoo project page: <http://www.gentoo.org/proj/en/portage/> +Gentoo project page: <https://wiki.gentoo.org/wiki/Project:Portage> PMS: <https://dev.gentoo.org/~ulm/pms/head/pms.html> -PMS git repo: <http://git.overlays.gentoo.org/gitweb/?p=proj/pms.git> +PMS git repo: <https://gitweb.gentoo.org/proj/pms.git/> diff --git a/RELEASE-NOTES b/RELEASE-NOTES index b26ba208e..11b18a9c2 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -1,6 +1,20 @@ Release Notes; upgrade information mainly. Features/major bugfixes are listed in NEWS +portage-2.2.23 +================================== +* Bug Fixes: + - Bug 561474 Add check that we need commit signing + - Bug 561596 Fix typo in function call + - Bug 561264 AbstractEbuildProcess: remove cgroup with release_agent + SyncRepos.async: group sync and callback as composite task + - Bug 554084 unpack: use chmod-lite helper + - Bug 562108 repoman/argparser.py: _unicode_decode the commitmsg + - Bug 561846 dohtml: handle unicode + - Bug 534022 scanner.py: Fix options.output_style for column output +* Add icecream feature support + + portage-2.2.22 ================================== * Bug Fixes: diff --git a/bin/cgroup-release-agent b/bin/cgroup-release-agent new file mode 100755 index 000000000..7aa6d56b4 --- /dev/null +++ b/bin/cgroup-release-agent @@ -0,0 +1,2 @@ +#!/bin/bash +exec rmdir "/sys/fs/cgroup/portage/${1}" diff --git a/bin/chmod-lite b/bin/chmod-lite new file mode 100755 index 000000000..ffa8d4d23 --- /dev/null +++ b/bin/chmod-lite @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright 2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +export __PORTAGE_HELPER_CWD=${PWD} + +# Use safe cwd, avoiding unsafe import for bug #469338. +cd "${PORTAGE_PYM_PATH}" || exit 1 +PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \ + exec "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH/chmod-lite.py" "$@" diff --git a/bin/chmod-lite.py b/bin/chmod-lite.py new file mode 100755 index 000000000..177be7eab --- /dev/null +++ b/bin/chmod-lite.py @@ -0,0 +1,30 @@ +#!/usr/bin/python -b +# Copyright 2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import os +import sys + +from portage.util import apply_recursive_permissions + +# Change back to original cwd _after_ all imports (bug #469338). +os.chdir(os.environ["__PORTAGE_HELPER_CWD"]) + +def main(files): + + if sys.hexversion >= 0x3000000: + # We can't trust that the filesystem encoding (locale dependent) + # correctly matches the arguments, so use surrogateescape to + # pass through the original argv bytes for Python 3. + fs_encoding = sys.getfilesystemencoding() + files = [x.encode(fs_encoding, 'surrogateescape') for x in files] + + for filename in files: + # Emulate 'chmod -fR a+rX,u+w,g-w,o-w' with minimal chmod calls. + apply_recursive_permissions(filename, filemode=0o644, + filemask=0o022, dirmode=0o755, dirmask=0o022) + + return os.EX_OK + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/bin/dohtml.py b/bin/dohtml.py index 5359f5e89..dfcaa6026 100755 --- a/bin/dohtml.py +++ b/bin/dohtml.py @@ -28,13 +28,13 @@ # - will do as 'dohtml -r', but ignore directories named CVS, SCCS, RCS # -from __future__ import print_function +from __future__ import print_function, unicode_literals -import os -import shutil +import os as _os import sys -from portage.util import normalize_path +from portage import _unicode_encode, _unicode_decode, os, shutil +from portage.util import normalize_path, writemsg # Change back to original cwd _after_ all imports (bug #469338). os.chdir(os.environ["__PORTAGE_HELPER_CWD"]) @@ -92,7 +92,13 @@ def install(basename, dirname, options, prefix=""): skipped_files.append(fullpath) elif options.recurse and os.path.isdir(fullpath) and \ basename not in options.disallowed_dirs: - for i in os.listdir(fullpath): + for i in _os.listdir(_unicode_encode(fullpath)): + try: + i = _unicode_decode(i, errors='strict') + except UnicodeDecodeError: + writemsg('dohtml: argument is not encoded as UTF-8: %s\n' % + _unicode_decode(i), noiselevel=-1) + sys.exit(1) pfx = basename if prefix: pfx = os.path.join(prefix, pfx) @@ -155,12 +161,29 @@ def print_help(): print() def parse_args(): + argv = sys.argv[:] + + if sys.hexversion >= 0x3000000: + # We can't trust that the filesystem encoding (locale dependent) + # correctly matches the arguments, so use surrogateescape to + # pass through the original argv bytes for Python 3. + fs_encoding = sys.getfilesystemencoding() + argv = [x.encode(fs_encoding, 'surrogateescape') for x in argv] + + for x, arg in enumerate(argv): + try: + argv[x] = _unicode_decode(arg, errors='strict') + except UnicodeDecodeError: + writemsg('dohtml: argument is not encoded as UTF-8: %s\n' % + _unicode_decode(arg), noiselevel=-1) + sys.exit(1) + options = OptionsClass() args = [] x = 1 - while x < len(sys.argv): - arg = sys.argv[x] + while x < len(argv): + arg = argv[x] if arg in ["-h","-r","-V"]: if arg == "-h": print_help() @@ -169,17 +192,17 @@ def parse_args(): options.recurse = True elif arg == "-V": options.verbose = True - elif sys.argv[x] in ["-A","-a","-f","-x","-p"]: + elif argv[x] in ["-A","-a","-f","-x","-p"]: x += 1 - if x == len(sys.argv): + if x == len(argv): print_help() sys.exit(0) elif arg == "-p": - options.doc_prefix = sys.argv[x] + options.doc_prefix = argv[x] if options.doc_prefix: options.doc_prefix = normalize_path(options.doc_prefix) else: - values = sys.argv[x].split(",") + values = argv[x].split(",") if arg == "-A": options.allowed_exts.extend(values) elif arg == "-a": @@ -189,7 +212,7 @@ def parse_args(): elif arg == "-x": options.disallowed_dirs = values else: - args.append(sys.argv[x]) + args.append(argv[x]) x += 1 return (options, args) diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh index 28aa0ecea..4245ec382 100644 --- a/bin/phase-helpers.sh +++ b/bin/phase-helpers.sh @@ -532,8 +532,8 @@ unpack() { done # Do not chmod '.' since it's probably ${WORKDIR} and PORTAGE_WORKDIR_MODE # should be preserved. - find . -mindepth 1 '!' -type l '!' -perm /a+rX,u+w,g-w,o-w \ - -exec chmod -f a+rX,u+w,g-w,o-w '{}' + + find . -mindepth 1 -maxdepth 1 ! -type l -print0 | \ + ${XARGS} -0 "${PORTAGE_BIN_PATH}/chmod-lite" } econf() { diff --git a/man/make.conf.5 b/man/make.conf.5 index 13b80428d..1d1cfebd4 100644 --- a/man/make.conf.5 +++ b/man/make.conf.5 @@ -411,6 +411,9 @@ for all EAPIs (for obvious reasons). Force emerges to always try to fetch files from the \fIPORTAGE_BINHOST\fR. See \fBmake.conf\fR(5) for more information. .TP +.B icecream +Enable portage support for the icecream package. +.TP .B installsources Install source code into /usr/src/debug/${CATEGORY}/${PF} (also see \fBsplitdebug\fR). This feature works only if debugedit is installed and CFLAGS diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py index 68d96e406..2b5d9c78d 100644 --- a/pym/_emerge/AbstractEbuildProcess.py +++ b/pym/_emerge/AbstractEbuildProcess.py @@ -89,6 +89,13 @@ class AbstractEbuildProcess(SpawnProcess): subprocess.check_call(['mount', '-t', 'cgroup', '-o', 'rw,nosuid,nodev,noexec,none,name=portage', 'tmpfs', cgroup_portage]) + with open(os.path.join( + cgroup_portage, 'release_agent'), 'w') as f: + f.write(os.path.join(self.settings['PORTAGE_BIN_PATH'], + 'cgroup-release-agent')) + with open(os.path.join( + cgroup_portage, 'notify_on_release'), 'w') as f: + f.write('1') cgroup_path = tempfile.mkdtemp(dir=cgroup_portage, prefix='%s:%s.' % (self.settings["CATEGORY"], @@ -313,13 +320,6 @@ class AbstractEbuildProcess(SpawnProcess): def _set_returncode(self, wait_retval): SpawnProcess._set_returncode(self, wait_retval) - if self.cgroup is not None: - try: - shutil.rmtree(self.cgroup) - except EnvironmentError as e: - if e.errno != errno.ENOENT: - raise - if self._exit_timeout_id is not None: self.scheduler.source_remove(self._exit_timeout_id) self._exit_timeout_id = None diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index 8eeef06fe..20a4e854d 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -65,6 +65,10 @@ from _emerge.SequentialTaskQueue import SequentialTaskQueue if sys.hexversion >= 0x3000000: basestring = str +# enums +FAILURE = 1 + + class Scheduler(PollScheduler): # max time between loadavg checks (milliseconds) @@ -284,11 +288,11 @@ class Scheduler(PollScheduler): self._parallel_fetch = True if self._parallel_fetch: - # clear out existing fetch log if it exists - try: - open(self._fetch_log, 'w').close() - except EnvironmentError: - pass + # clear out existing fetch log if it exists + try: + open(self._fetch_log, 'w').close() + except EnvironmentError: + pass self._running_portage = None portage_match = self._running_root.trees["vartree"].dbapi.match( @@ -353,7 +357,7 @@ class Scheduler(PollScheduler): Use this to free memory at the beginning of _calc_resume_list(). After _calc_resume_list(), the _init_graph() method must to be called in order to re-generate the structures that - this method destroys. + this method destroys. """ self._blocker_db = None self._set_graph_config(None) @@ -641,7 +645,7 @@ class Scheduler(PollScheduler): writemsg_level( "!!! Unable to generate manifest for '%s'.\n" \ % x.cpv, level=logging.ERROR, noiselevel=-1) - return 1 + return FAILURE return os.EX_OK @@ -673,7 +677,7 @@ class Scheduler(PollScheduler): out = portage.output.EOutput() for line in textwrap.wrap(msg, 70): out.eerror(line) - return 1 + return FAILURE return os.EX_OK @@ -719,7 +723,7 @@ class Scheduler(PollScheduler): failures |= 1 if failures: - return 1 + return FAILURE return os.EX_OK def _add_prefetchers(self): @@ -934,7 +938,7 @@ class Scheduler(PollScheduler): build_dir.unlock() if failures: - return 1 + return FAILURE return os.EX_OK def merge(self): @@ -949,7 +953,7 @@ class Scheduler(PollScheduler): try: self._background = self._background_mode() except self._unknown_internal_error: - return 1 + return FAILURE rval = self._handle_self_update() if rval != os.EX_OK: @@ -971,7 +975,7 @@ class Scheduler(PollScheduler): out = portage.output.EOutput() for l in msg: out.eerror(l) - return 1 + return FAILURE if self._background: root_config.settings.unlock() @@ -1180,7 +1184,7 @@ class Scheduler(PollScheduler): printer.eerror("") if self._failed_pkgs_all: - return 1 + return FAILURE return os.EX_OK def _elog_listener(self, mysettings, key, logentries, fulltext): diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py index 642602ea1..cdf467003 100644 --- a/pym/portage/checksum.py +++ b/pym/portage/checksum.py @@ -7,7 +7,7 @@ from portage.const import PRELINK_BINARY, HASHING_BLOCKSIZE from portage.localization import _ from portage import os from portage import _encodings -from portage import _unicode_encode +from portage import _unicode_decode, _unicode_encode import errno import stat import subprocess @@ -22,7 +22,7 @@ def _open_file(filename): return open(_unicode_encode(filename, encoding=_encodings['fs'], errors='strict'), 'rb') except IOError as e: - func_call = "open('%s')" % filename + func_call = "open('%s')" % _unicode_decode(filename) if e.errno == errno.EPERM: raise portage.exception.OperationNotPermitted(func_call) elif e.errno == errno.EACCES: diff --git a/pym/portage/const.py b/pym/portage/const.py index 6b03017cb..20cf40e16 100644 --- a/pym/portage/const.py +++ b/pym/portage/const.py @@ -150,6 +150,7 @@ SUPPORTED_FEATURES = frozenset([ "force-multilib", "force-prefix", "getbinpkg", + "icecream", "installsources", "ipc-sandbox", "keeptemp", diff --git a/pym/portage/data.py b/pym/portage/data.py index 2fd287ddb..2c99548cb 100644 --- a/pym/portage/data.py +++ b/pym/portage/data.py @@ -139,7 +139,7 @@ def _get_global(k): v = 2 elif unprivileged: v = 2 - elif portage_gid in os.getgroups(): + elif _get_global('portage_gid') in os.getgroups(): v = 1 elif k in ('portage_gid', 'portage_uid'): diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py index b6745fa15..95053840d 100644 --- a/pym/portage/dbapi/__init__.py +++ b/pym/portage/dbapi/__init__.py @@ -215,7 +215,7 @@ class dbapi(object): yield cpv - def _match_use(self, atom, pkg, metadata): + def _match_use(self, atom, pkg, metadata, ignore_profile=False): eapi_attrs = _get_eapi_attrs(metadata["EAPI"]) if eapi_attrs.iuse_effective: iuse_implicit_match = self.settings._iuse_effective_match @@ -261,17 +261,18 @@ class dbapi(object): return False elif not self.settings.local_config: - # Check masked and forced flags for repoman. - usemask = self.settings._getUseMask(pkg, - stable=self.settings._parent_stable) - if any(x in usemask for x in atom.use.enabled): - return False + if not ignore_profile: + # Check masked and forced flags for repoman. + usemask = self.settings._getUseMask(pkg, + stable=self.settings._parent_stable) + if any(x in usemask for x in atom.use.enabled): + return False - useforce = self.settings._getUseForce(pkg, - stable=self.settings._parent_stable) - if any(x in useforce and x not in usemask - for x in atom.use.disabled): - return False + useforce = self.settings._getUseForce(pkg, + stable=self.settings._parent_stable) + if any(x in useforce and x not in usemask + for x in atom.use.disabled): + return False # Check unsatisfied use-default deps if atom.use.enabled: diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index d13fdee6d..a954de53b 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -809,9 +809,9 @@ class portdbapi(dbapi): return mylist def freeze(self): - for x in "bestmatch-visible", "cp-list", "match-all", \ - "match-all-cpv-only", "match-visible", "minimum-all", \ - "minimum-visible": + for x in ("bestmatch-visible", "cp-list", "match-all", + "match-all-cpv-only", "match-visible", "minimum-all", + "minimum-all-ignore-profile", "minimum-visible"): self.xcache[x]={} self.frozen=1 @@ -870,8 +870,9 @@ class portdbapi(dbapi): myval = match_from_list(mydep, self.cp_list(mykey, mytree=mytree)) - elif level in ("bestmatch-visible", "match-all", "match-visible", - "minimum-all", "minimum-visible"): + elif level in ("bestmatch-visible", "match-all", + "match-visible", "minimum-all", "minimum-all-ignore-profile", + "minimum-visible"): # Find the minimum matching visible version. This is optimized to # minimize the number of metadata accesses (improves performance # especially in cases where metadata needs to be generated). @@ -881,7 +882,9 @@ class portdbapi(dbapi): mylist = match_from_list(mydep, self.cp_list(mykey, mytree=mytree)) - visibility_filter = level not in ("match-all", "minimum-all") + ignore_profile = level in ("minimum-all-ignore-profile",) + visibility_filter = level not in ("match-all", + "minimum-all", "minimum-all-ignore-profile") single_match = level not in ("match-all", "match-visible") myval = [] aux_keys = list(self._aux_cache_keys) @@ -922,7 +925,8 @@ class portdbapi(dbapi): continue if mydep.unevaluated_atom.use is not None and \ - not self._match_use(mydep, pkg_str, metadata): + not self._match_use(mydep, pkg_str, metadata, + ignore_profile=ignore_profile): continue myval.append(pkg_str) diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py index 3594ff06f..e581724d9 100644 --- a/pym/portage/package/ebuild/doebuild.py +++ b/pym/portage/package/ebuild/doebuild.py @@ -45,7 +45,7 @@ portage.proxy.lazyimport.lazyimport(globals(), 'portage.util.ExtractKernelVersion:ExtractKernelVersion' ) -from portage import auxdbkeys, bsd_chflags, \ +from portage import bsd_chflags, \ eapi_is_supported, merge, os, selinux, shutil, \ unmerge, _encodings, _os_merge, \ _shell_quote, _unicode_decode, _unicode_encode @@ -69,7 +69,7 @@ from portage.localization import _ from portage.output import colormap from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs from portage.util import apply_recursive_permissions, \ - apply_secpass_permissions, noiselimit, normalize_path, \ + apply_secpass_permissions, noiselimit, \ writemsg, writemsg_stdout, write_atomic from portage.util.cpuinfo import get_cpu_count from portage.util.lafilefixer import rewrite_lafile @@ -251,8 +251,6 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, EAPI metadata. The myroot and use_cache parameters are unused. """ - myroot = None - use_cache = None if settings is None: raise TypeError("settings argument is required") @@ -465,7 +463,9 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, ccache = "ccache" in mysettings.features distcc = "distcc" in mysettings.features - if ccache or distcc: + icecream = "icecream" in mysettings.features + + if ccache or distcc or icecream: # Use default ABI libdir in accordance with bug #355283. libdir = None default_abi = mysettings.get("DEFAULT_ABI") @@ -478,6 +478,10 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, mysettings["PATH"] = os.path.join(os.sep, eprefix_lstrip, "usr", libdir, "distcc", "bin") + ":" + mysettings["PATH"] + if icecream: + mysettings["PATH"] = os.path.join(os.sep, eprefix_lstrip, + "usr", 'libexec', "icecc", "bin") + ":" + mysettings["PATH"] + if ccache: mysettings["PATH"] = os.path.join(os.sep, eprefix_lstrip, "usr", libdir, "ccache", "bin") + ":" + mysettings["PATH"] diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py index 28dbc575a..159b9c094 100644 --- a/pym/portage/sync/controller.py +++ b/pym/portage/sync/controller.py @@ -25,6 +25,7 @@ from portage.util._async.AsyncFunction import AsyncFunction from portage import OrderedDict from portage import _unicode_decode from portage import util +from _emerge.CompositeTask import CompositeTask class TaskHandler(object): @@ -119,10 +120,9 @@ class SyncManager(object): self.settings, self.trees, self.mtimedb = emerge_config self.xterm_titles = "notitles" not in self.settings.features self.portdb = self.trees[self.settings['EROOT']]['porttree'].dbapi - proc = AsyncFunction(target=self.sync, - kwargs=dict(emerge_config=emerge_config, repo=repo)) - proc.addExitListener(self._sync_callback) - return proc + return SyncRepo(sync_task=AsyncFunction(target=self.sync, + kwargs=dict(emerge_config=emerge_config, repo=repo)), + sync_callback=self._sync_callback) def sync(self, emerge_config=None, repo=None): self.callback = None @@ -343,3 +343,34 @@ class SyncManager(object): action_metadata(self.settings, self.portdb, self.emerge_config.opts, porttrees=[repo.location]) + +class SyncRepo(CompositeTask): + """ + Encapsulates a sync operation and the callback which executes afterwards, + so both can be considered as a single composite task. This is useful + since we don't want to consider a particular repo's sync operation as + complete until after the callback has executed (bug 562264). + + The kwargs and result properties expose attributes that are accessed + by SyncScheduler. + """ + + __slots__ = ('sync_task', 'sync_callback') + + @property + def kwargs(self): + return self.sync_task.kwargs + + @property + def result(self): + return self.sync_task.result + + def _start(self): + self._start_task(self.sync_task, self._sync_task_exit) + + def _sync_task_exit(self, sync_task): + self._current_task = None + self.returncode = sync_task.returncode + self.sync_callback(self.sync_task) + self._async_wait() + diff --git a/pym/portage/util/__init__.py b/pym/portage/util/__init__.py index c0b509ba6..b739257e8 100644 --- a/pym/portage/util/__init__.py +++ b/pym/portage/util/__init__.py @@ -17,9 +17,9 @@ from copy import deepcopy import errno import io try: - from itertools import filterfalse + from itertools import chain, filterfalse except ImportError: - from itertools import ifilterfalse as filterfalse + from itertools import chain, ifilterfalse as filterfalse import logging import re import shlex @@ -1041,6 +1041,23 @@ def unique_everseen(iterable, key=None): seen_add(k) yield element +def _do_stat(filename, follow_links=True): + try: + if follow_links: + return os.stat(filename) + else: + return os.lstat(filename) + except OSError as oe: + func_call = "stat('%s')" % filename + if oe.errno == errno.EPERM: + raise OperationNotPermitted(func_call) + elif oe.errno == errno.EACCES: + raise PermissionDenied(func_call) + elif oe.errno == errno.ENOENT: + raise FileNotFound(filename) + else: + raise + def apply_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1, stat_cached=None, follow_links=True): """Apply user, group, and mode bits to a file if the existing bits do not @@ -1058,21 +1075,7 @@ def apply_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1, gid = int(gid) if stat_cached is None: - try: - if follow_links: - stat_cached = os.stat(filename) - else: - stat_cached = os.lstat(filename) - except OSError as oe: - func_call = "stat('%s')" % filename - if oe.errno == errno.EPERM: - raise OperationNotPermitted(func_call) - elif oe.errno == errno.EACCES: - raise PermissionDenied(func_call) - elif oe.errno == errno.ENOENT: - raise FileNotFound(filename) - else: - raise + stat_cached = _do_stat(filename, follow_links=follow_links) if (uid != -1 and uid != stat_cached.st_uid) or \ (gid != -1 and gid != stat_cached.st_gid): @@ -1177,22 +1180,40 @@ def apply_recursive_permissions(top, uid=-1, gid=-1, else: raise + # For bug 554084, always apply permissions to a directory before + # that directory is traversed. all_applied = True - for dirpath, dirnames, filenames in os.walk(top): - try: - applied = apply_secpass_permissions(dirpath, - uid=uid, gid=gid, mode=dirmode, mask=dirmask, - follow_links=follow_links) - if not applied: - all_applied = False - except PortageException as e: + + try: + stat_cached = _do_stat(top, follow_links=follow_links) + except FileNotFound: + # backward compatibility + return True + + if stat.S_ISDIR(stat_cached.st_mode): + mode = dirmode + mask = dirmask + else: + mode = filemode + mask = filemask + + try: + applied = apply_secpass_permissions(top, + uid=uid, gid=gid, mode=mode, mask=mask, + stat_cached=stat_cached, follow_links=follow_links) + if not applied: all_applied = False - onerror(e) + except PortageException as e: + all_applied = False + onerror(e) - for name in filenames: + for dirpath, dirnames, filenames in os.walk(top): + for name, mode, mask in chain( + ((x, filemode, filemask) for x in filenames), + ((x, dirmode, dirmask) for x in dirnames)): try: applied = apply_secpass_permissions(os.path.join(dirpath, name), - uid=uid, gid=gid, mode=filemode, mask=filemask, + uid=uid, gid=gid, mode=mode, mask=mask, follow_links=follow_links) if not applied: all_applied = False @@ -1216,25 +1237,13 @@ def apply_secpass_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1, unapplied.""" if stat_cached is None: - try: - if follow_links: - stat_cached = os.stat(filename) - else: - stat_cached = os.lstat(filename) - except OSError as oe: - func_call = "stat('%s')" % filename - if oe.errno == errno.EPERM: - raise OperationNotPermitted(func_call) - elif oe.errno == errno.EACCES: - raise PermissionDenied(func_call) - elif oe.errno == errno.ENOENT: - raise FileNotFound(filename) - else: - raise + stat_cached = _do_stat(filename, follow_links=follow_links) all_applied = True - if portage.data.secpass < 2: + # Avoid accessing portage.data.secpass when possible, since + # it triggers config loading (undesirable for chmod-lite). + if (uid != -1 or gid != -1) and portage.data.secpass < 2: if uid != -1 and \ uid != stat_cached.st_uid: diff --git a/pym/repoman/_subprocess.py b/pym/repoman/_subprocess.py index 5449e64ff..dcdc985fe 100644 --- a/pym/repoman/_subprocess.py +++ b/pym/repoman/_subprocess.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import codecs diff --git a/pym/repoman/_xml.py b/pym/repoman/_xml.py index 7bf6698c6..0acda28e6 100644 --- a/pym/repoman/_xml.py +++ b/pym/repoman/_xml.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import sys import xml diff --git a/pym/repoman/actions.py b/pym/repoman/actions.py index 54622487a..f4617036e 100644 --- a/pym/repoman/actions.py +++ b/pym/repoman/actions.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals @@ -172,7 +173,7 @@ class Actions(object): digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb) if self.repo_settings.sign_manifests: - self.sign_manifests(myupdates, myremoved, mymanifests) + self.sign_manifest(myupdates, myremoved, mymanifests) if self.vcs_settings.vcs == 'git': # It's not safe to use the git commit -a option since there might diff --git a/pym/repoman/argparser.py b/pym/repoman/argparser.py index 1c9bd4582..0f34ed01c 100644 --- a/pym/repoman/argparser.py +++ b/pym/repoman/argparser.py @@ -10,6 +10,7 @@ import sys # import our initialized portage instance from repoman._portage import portage +from portage import _unicode_decode from portage import util from portage.util._argparse import ArgumentParser @@ -210,6 +211,9 @@ def parse_args(argv, qahelp, repoman_default_opts): logger = logging.getLogger() logger.setLevel(logger.getEffectiveLevel() + 10) + if opts.mode == 'commit' and opts.commitmsg: + opts.commitmsg = _unicode_decode(opts.commitmsg) + if opts.mode == 'commit' and not (opts.force or opts.pretend): if opts.ignore_masked: opts.ignore_masked = False diff --git a/pym/repoman/check_missingslot.py b/pym/repoman/check_missingslot.py index 3f79435b6..4a3c57b2c 100644 --- a/pym/repoman/check_missingslot.py +++ b/pym/repoman/check_missingslot.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # repoman: missing slot check # Copyright 2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 diff --git a/pym/repoman/checks/directories/files.py b/pym/repoman/checks/directories/files.py index b1d77df49..9bb560c78 100644 --- a/pym/repoman/checks/directories/files.py +++ b/pym/repoman/checks/directories/files.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''repoman/checks/diretories/files.py diff --git a/pym/repoman/checks/ebuilds/checks.py b/pym/repoman/checks/ebuilds/checks.py index 5ebc6c1aa..245ab2b01 100644 --- a/pym/repoman/checks/ebuilds/checks.py +++ b/pym/repoman/checks/ebuilds/checks.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # repoman: Checks # Copyright 2007-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 diff --git a/pym/repoman/checks/ebuilds/errors.py b/pym/repoman/checks/ebuilds/errors.py index d5c8d2e97..3090de0d1 100644 --- a/pym/repoman/checks/ebuilds/errors.py +++ b/pym/repoman/checks/ebuilds/errors.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # repoman: Error Messages # Copyright 2007-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 diff --git a/pym/repoman/checks/ebuilds/fetches.py b/pym/repoman/checks/ebuilds/fetches.py index 077340dd8..32da21ac2 100644 --- a/pym/repoman/checks/ebuilds/fetches.py +++ b/pym/repoman/checks/ebuilds/fetches.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''fetches.py Performs the src_uri fetchlist and files checks diff --git a/pym/repoman/checks/ebuilds/isebuild.py b/pym/repoman/checks/ebuilds/isebuild.py index f0c9a48cc..3992c9c10 100644 --- a/pym/repoman/checks/ebuilds/isebuild.py +++ b/pym/repoman/checks/ebuilds/isebuild.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import stat diff --git a/pym/repoman/checks/ebuilds/keywords.py b/pym/repoman/checks/ebuilds/keywords.py index 235c75154..9d2585e46 100644 --- a/pym/repoman/checks/ebuilds/keywords.py +++ b/pym/repoman/checks/ebuilds/keywords.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''keywords.py Perform KEYWORDS related checks diff --git a/pym/repoman/checks/ebuilds/manifests.py b/pym/repoman/checks/ebuilds/manifests.py index 3b8dec5ac..1ca4f94fd 100644 --- a/pym/repoman/checks/ebuilds/manifests.py +++ b/pym/repoman/checks/ebuilds/manifests.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import logging import sys diff --git a/pym/repoman/checks/ebuilds/misc.py b/pym/repoman/checks/ebuilds/misc.py index d73554272..e2bef34de 100644 --- a/pym/repoman/checks/ebuilds/misc.py +++ b/pym/repoman/checks/ebuilds/misc.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''repoman/checks/ebuilds/misc.py Miscelaneous ebuild check functions''' diff --git a/pym/repoman/checks/ebuilds/pkgmetadata.py b/pym/repoman/checks/ebuilds/pkgmetadata.py index 8dc3f60d8..f22ef1958 100644 --- a/pym/repoman/checks/ebuilds/pkgmetadata.py +++ b/pym/repoman/checks/ebuilds/pkgmetadata.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''Package Metadata Checks operations''' diff --git a/pym/repoman/checks/ebuilds/thirdpartymirrors.py b/pym/repoman/checks/ebuilds/thirdpartymirrors.py index 061e71f5d..848dfb9f0 100644 --- a/pym/repoman/checks/ebuilds/thirdpartymirrors.py +++ b/pym/repoman/checks/ebuilds/thirdpartymirrors.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # import our initialized portage instance from repoman._portage import portage diff --git a/pym/repoman/checks/ebuilds/use_flags.py b/pym/repoman/checks/ebuilds/use_flags.py index 73680d078..ac21b47b6 100644 --- a/pym/repoman/checks/ebuilds/use_flags.py +++ b/pym/repoman/checks/ebuilds/use_flags.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- '''use_flags.py Performs USE flag related checks diff --git a/pym/repoman/checks/herds/metadata.py b/pym/repoman/checks/herds/metadata.py index 3c67fcf36..b4a433ed7 100644 --- a/pym/repoman/checks/herds/metadata.py +++ b/pym/repoman/checks/herds/metadata.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- class UnknownHerdsError(ValueError): diff --git a/pym/repoman/copyrights.py b/pym/repoman/copyrights.py index 056cfda09..761309af6 100644 --- a/pym/repoman/copyrights.py +++ b/pym/repoman/copyrights.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import difflib diff --git a/pym/repoman/ebuild.py b/pym/repoman/ebuild.py index 1dddfb940..fdfb08383 100644 --- a/pym/repoman/ebuild.py +++ b/pym/repoman/ebuild.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from portage import os diff --git a/pym/repoman/errors.py b/pym/repoman/errors.py index 305eecef1..2ea46803b 100644 --- a/pym/repoman/errors.py +++ b/pym/repoman/errors.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import sys diff --git a/pym/repoman/gpg.py b/pym/repoman/gpg.py index 90fe74904..26e243201 100644 --- a/pym/repoman/gpg.py +++ b/pym/repoman/gpg.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals diff --git a/pym/repoman/main.py b/pym/repoman/main.py index e2325584e..00d48e70d 100755 --- a/pym/repoman/main.py +++ b/pym/repoman/main.py @@ -1,4 +1,5 @@ #!/usr/bin/python -bO +# -*- coding:utf-8 -*- # Copyright 1999-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 diff --git a/pym/repoman/metadata.py b/pym/repoman/metadata.py index f2b63a77c..70c07a874 100644 --- a/pym/repoman/metadata.py +++ b/pym/repoman/metadata.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import errno import logging diff --git a/pym/repoman/modules/commit/repochecks.py b/pym/repoman/modules/commit/repochecks.py index 8019e283d..163466d4a 100644 --- a/pym/repoman/modules/commit/repochecks.py +++ b/pym/repoman/modules/commit/repochecks.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals diff --git a/pym/repoman/profile.py b/pym/repoman/profile.py index 3634fb936..50da91728 100644 --- a/pym/repoman/profile.py +++ b/pym/repoman/profile.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals diff --git a/pym/repoman/qa_data.py b/pym/repoman/qa_data.py index b26559c24..dddfb98ba 100644 --- a/pym/repoman/qa_data.py +++ b/pym/repoman/qa_data.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import logging diff --git a/pym/repoman/repos.py b/pym/repoman/repos.py index f16bf7a37..9a62e0519 100644 --- a/pym/repoman/repos.py +++ b/pym/repoman/repos.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import io @@ -60,7 +61,7 @@ class RepoSettings(object): if self.repo_config.allow_provide_virtual: qawarnings.add("virtual.oldstyle") - if self.repo_config.sign_commit: + if self.repo_config.sign_commit and options.mode in ("commit", "fix", "manifest"): if vcs_settings.vcs: func = getattr(self, '_vcs_gpg_%s' % vcs_settings.vcs) func() diff --git a/pym/repoman/scan.py b/pym/repoman/scan.py index fef6d8295..0b74efd82 100644 --- a/pym/repoman/scan.py +++ b/pym/repoman/scan.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- import logging import os @@ -167,4 +168,5 @@ class Changes(object): with repoman_popen("hg status --no-status --removed .") as f: removed = f.readlines() self.removed = ["./" + elem.rstrip() for elem in removed] - del changed, new, removed + del removed + del changed, new diff --git a/pym/repoman/scanner.py b/pym/repoman/scanner.py index 1e1a38e39..df46144e2 100644 --- a/pym/repoman/scanner.py +++ b/pym/repoman/scanner.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals @@ -632,7 +633,7 @@ class Scanner(object): continue # we are testing deps for a masked package; give it some lee-way suffix = "masked" - matchmode = "minimum-all" + matchmode = "minimum-all-ignore-profile" else: suffix = "" matchmode = "minimum-visible" @@ -688,15 +689,27 @@ class Scanner(object): # if we emptied out our list, continue: if not atoms: continue + if self.options.output_style in ['column']: + self.qatracker.add_error(mykey, + "%s: %s: %s(%s) %s" + % (ebuild.relative_path, mytype, keyword, + prof, repr(atoms))) + else: + self.qatracker.add_error(mykey, + "%s: %s: %s(%s)\n%s" + % (ebuild.relative_path, mytype, keyword, + prof, pformat(atoms, indent=6))) + else: + if self.options.output_style in ['column']: + self.qatracker.add_error(mykey, + "%s: %s: %s(%s) %s" + % (ebuild.relative_path, mytype, keyword, + prof, repr(atoms))) + else: self.qatracker.add_error(mykey, "%s: %s: %s(%s)\n%s" - % (ebuild.relative_path, mytype, keyword, prof, - pformat(atoms, indent=6))) - else: - self.qatracker.add_error(mykey, - "%s: %s: %s(%s)\n%s" - % (ebuild.relative_path, mytype, keyword, prof, - pformat(atoms, indent=6))) + % (ebuild.relative_path, mytype, keyword, + prof, pformat(atoms, indent=6))) if not baddepsyntax and unknown_pkgs: type_map = {} diff --git a/pym/repoman/utilities.py b/pym/repoman/utilities.py index 2a1f4d909..47b5aabcb 100644 --- a/pym/repoman/utilities.py +++ b/pym/repoman/utilities.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # repoman: Utilities # Copyright 2007-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 diff --git a/pym/repoman/vcs/vcs.py b/pym/repoman/vcs/vcs.py index 9b77e8eb5..49d305891 100644 --- a/pym/repoman/vcs/vcs.py +++ b/pym/repoman/vcs/vcs.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- from __future__ import print_function, unicode_literals diff --git a/pym/repoman/vcs/vcsstatus.py b/pym/repoman/vcs/vcsstatus.py index 30e00ad53..4dc633eb5 100644 --- a/pym/repoman/vcs/vcsstatus.py +++ b/pym/repoman/vcs/vcsstatus.py @@ -1,3 +1,4 @@ +# -*- coding:utf-8 -*- # import our initialized portage instance @@ -612,7 +612,7 @@ def get_manpages(): setup( name = 'portage', - version = '2.2.22', + version = '2.2.23', url = 'https://wiki.gentoo.org/wiki/Project:Portage', author = 'Gentoo Portage Development Team', author_email = 'dev-portage@gentoo.org', |