Create new directories:
ceph
config
config-files
filesystem
kernel
kernel/kernel-modules
ldap
logging
strorage-drivers
tools
utilities
virt
Retire directories:
connectivity
core
devtools
support
extended
Delete two packages:
tgt
irqbalance
Relocated packages:
base/
dhcp
initscripts
libevent
lighttpd
linuxptp
memcached
net-snmp
novnc
ntp
openssh
pam
procps
sanlock
shadow
sudo
systemd
util-linux
vim
watchdog
ceph/
python-cephclient
config/
facter
puppet-4.8.2
puppet-modules
filesystem/
e2fsprogs
nfs-utils
nfscheck
kernel/
kernel-std
kernel-rt
kernel/kernel-modules/
mlnx-ofa_kernel
ldap/
nss-pam-ldapd
openldap
logging/
syslog-ng
logrotate
networking/
lldpd
iproute
mellanox
python-ryu
mlx4-config
python/
python-2.7.5
python-django
python-gunicorn
python-setuptools
python-smartpm
python-voluptuous
security/
shim-signed
shim-unsigned
tboot
strorage-drivers/
python-3parclient
python-lefthandclient
virt/
cloud-init
libvirt
libvirt-python
qemu
tools/
storage-topology
vm-topology
utilities/
tis-extensions
namespace-utils
nova-utils
update-motd
Change-Id: I37ade764d873c701b35eac5881eb40412ba64a86
Story: 2002801
Task: 22687
Signed-off-by: Scott Little <scott.little@windriver.com>
197 lines
7.9 KiB
Diff
197 lines
7.9 KiB
Diff
Report a reason when a dependency could not be installed because it is locked
|
|
|
|
If a requirement of a package is conflicted, depending on how the
|
|
solution is reached, the transaction code may eliminate all providers
|
|
of the requirement and then error out because nothing provides them. To
|
|
work around this, store a reason in the locked dict and report that back
|
|
if we need to, so for example instead of:
|
|
|
|
error: Can't install packagegroup-core-ssh-dropbear-1.0-r1@all: no package provides dropbear
|
|
|
|
we now get:
|
|
|
|
error: Can't install packagegroup-core-ssh-dropbear-1.0-r1@all: unable to install provider for dropbear:
|
|
error: dropbear-2013.58-r1.0@armv5te is conflicted by openssh-sshd-6.2p2-r0@armv5te
|
|
|
|
Upstream-Status: Pending
|
|
|
|
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
|
|
---
|
|
smart/const.py | 7 +++++++
|
|
smart/transaction.py | 58 +++++++++++++++++++++++++++++++++++++++++-----------
|
|
2 files changed, 53 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/smart/const.py b/smart/const.py
|
|
index 4d8e5cb..67c1ac5 100644
|
|
--- a/smart/const.py
|
|
+++ b/smart/const.py
|
|
@@ -70,4 +70,11 @@ DATADIR = "/var/lib/smart/"
|
|
USERDATADIR = "~/.smart/"
|
|
CONFFILE = "config"
|
|
|
|
+LOCKED_INSTALL = Enum('LOCKED_INSTALL')
|
|
+LOCKED_REMOVE = Enum('LOCKED_REMOVE')
|
|
+LOCKED_CONFLICT = Enum('LOCKED_CONFLICT')
|
|
+LOCKED_CONFLICT_BY = Enum('LOCKED_CONFLICT_BY')
|
|
+LOCKED_NO_COEXIST = Enum('LOCKED_NO_COEXIST')
|
|
+LOCKED_SYSCONF = Enum('LOCKED_SYSCONF')
|
|
+
|
|
# vim:ts=4:sw=4:et
|
|
diff --git a/smart/transaction.py b/smart/transaction.py
|
|
index 300b9cc..dd9aa38 100644
|
|
--- a/smart/transaction.py
|
|
+++ b/smart/transaction.py
|
|
@@ -19,10 +19,31 @@
|
|
# along with Smart Package Manager; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
-from smart.const import INSTALL, REMOVE, UPGRADE, FIX, REINSTALL, KEEP
|
|
+from smart.const import INSTALL, REMOVE, UPGRADE, FIX, REINSTALL, KEEP, LOCKED_INSTALL, LOCKED_CONFLICT, LOCKED_CONFLICT_BY, LOCKED_NO_COEXIST, LOCKED_SYSCONF, LOCKED_REMOVE
|
|
from smart.cache import PreRequires, Package
|
|
from smart import *
|
|
|
|
+def lock_reason(pkg, lockvalue):
|
|
+ try:
|
|
+ (reason, otherpkg) = lockvalue
|
|
+ except TypeError:
|
|
+ reason = None
|
|
+ lockvalue = None
|
|
+ if reason == LOCKED_INSTALL:
|
|
+ return _("%s is to be installed") % pkg
|
|
+ elif reason == LOCKED_CONFLICT:
|
|
+ return _("%s conflicts with %s") % (pkg, otherpkg)
|
|
+ elif reason == LOCKED_CONFLICT_BY:
|
|
+ return _("%s is conflicted by %s") % (pkg, otherpkg)
|
|
+ elif reason == LOCKED_NO_COEXIST:
|
|
+ return _("%s cannot coexist with %s") % (pkg, otherpkg)
|
|
+ elif reason == LOCKED_SYSCONF:
|
|
+ return _("%s is locked in system configuration") % pkg
|
|
+ elif reason == LOCKED_REMOVE:
|
|
+ return _("%s is to be removed") % pkg
|
|
+ else:
|
|
+ return _("%s is locked (unknown reason)") % pkg
|
|
+
|
|
class ChangeSet(dict):
|
|
|
|
def __init__(self, cache, state=None, requested=None):
|
|
@@ -187,7 +208,7 @@ class Policy(object):
|
|
for pkg in pkgconf.filterByFlag("lock", cache.getPackages()):
|
|
if pkg not in self._locked:
|
|
self._sysconflocked.append(pkg)
|
|
- self._locked[pkg] = True
|
|
+ self._locked[pkg] = (LOCKED_SYSCONF, None)
|
|
|
|
def runFinished(self):
|
|
self._priorities.clear()
|
|
@@ -524,7 +545,7 @@ class Transaction(object):
|
|
if ownpending:
|
|
pending = []
|
|
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_INSTALL, None)
|
|
changeset.set(pkg, INSTALL)
|
|
isinst = changeset.installed
|
|
|
|
@@ -535,7 +556,7 @@ class Transaction(object):
|
|
if prvpkg is pkg:
|
|
continue
|
|
if not isinst(prvpkg):
|
|
- locked[prvpkg] = True
|
|
+ locked[prvpkg] = (LOCKED_CONFLICT_BY, pkg)
|
|
continue
|
|
if prvpkg in locked:
|
|
raise Failed, _("Can't install %s: conflicted package "
|
|
@@ -550,7 +571,7 @@ class Transaction(object):
|
|
if cnfpkg is pkg:
|
|
continue
|
|
if not isinst(cnfpkg):
|
|
- locked[cnfpkg] = True
|
|
+ locked[cnfpkg] = (LOCKED_CONFLICT, pkg)
|
|
continue
|
|
if cnfpkg in locked:
|
|
raise Failed, _("Can't install %s: it's conflicted by "
|
|
@@ -565,7 +586,7 @@ class Transaction(object):
|
|
for namepkg in namepkgs:
|
|
if namepkg is not pkg and not pkg.coexists(namepkg):
|
|
if not isinst(namepkg):
|
|
- locked[namepkg] = True
|
|
+ locked[namepkg] = (LOCKED_NO_COEXIST, pkg)
|
|
continue
|
|
if namepkg in locked:
|
|
raise Failed, _("Can't install %s: it can't coexist "
|
|
@@ -577,6 +598,7 @@ class Transaction(object):
|
|
|
|
# Check if someone is already providing it.
|
|
prvpkgs = {}
|
|
+ lockedpkgs = {}
|
|
found = False
|
|
for prv in req.providedby:
|
|
for prvpkg in prv.packages:
|
|
@@ -585,6 +607,8 @@ class Transaction(object):
|
|
break
|
|
if prvpkg not in locked:
|
|
prvpkgs[prvpkg] = True
|
|
+ else:
|
|
+ lockedpkgs[prvpkg] = locked[prvpkg]
|
|
else:
|
|
continue
|
|
break
|
|
@@ -597,7 +621,17 @@ class Transaction(object):
|
|
if not prvpkgs:
|
|
# No packages provide it at all. Give up.
|
|
if req in pkg.requires:
|
|
- raise Failed, _("Can't install %s: no package provides %s") % \
|
|
+ reasons = []
|
|
+ for prv in req.providedby:
|
|
+ for prvpkg in prv.packages:
|
|
+ lockedres = lockedpkgs.get(prvpkg, None)
|
|
+ if lockedres:
|
|
+ reasons.append(lock_reason(prvpkg, lockedres))
|
|
+ if reasons:
|
|
+ raise Failed, _("Can't install %s: unable to install provider for %s:\n %s") % \
|
|
+ (pkg, req, '\n '.join(reasons))
|
|
+ else:
|
|
+ raise Failed, _("Can't install %s: no package provides %s") % \
|
|
(pkg, req)
|
|
else:
|
|
# It's only a recommend, skip
|
|
@@ -627,7 +661,7 @@ class Transaction(object):
|
|
if ownpending:
|
|
pending = []
|
|
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_REMOVE, None)
|
|
changeset.set(pkg, REMOVE)
|
|
isinst = changeset.installed
|
|
|
|
@@ -1140,22 +1174,22 @@ class Transaction(object):
|
|
if op is KEEP:
|
|
if pkg in changeset:
|
|
del changeset[pkg]
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_KEEP, None)
|
|
elif op is INSTALL:
|
|
if not isinst(pkg) and pkg in locked:
|
|
raise Failed, _("Can't install %s: it's locked") % pkg
|
|
changeset.set(pkg, INSTALL)
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_INSTALL, None)
|
|
elif op is REMOVE:
|
|
if isinst(pkg) and pkg in locked:
|
|
raise Failed, _("Can't remove %s: it's locked") % pkg
|
|
changeset.set(pkg, REMOVE)
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_REMOVE, None)
|
|
elif op is REINSTALL:
|
|
if pkg in locked:
|
|
raise Failed, _("Can't reinstall %s: it's locked")%pkg
|
|
changeset.set(pkg, INSTALL, force=True)
|
|
- locked[pkg] = True
|
|
+ locked[pkg] = (LOCKED_INSTALL, None)
|
|
elif op is UPGRADE:
|
|
pass
|
|
|
|
--
|
|
1.8.1.2
|
|
|