summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2013-07-24 11:15:57 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-07-29 13:09:14 +0100
commite8dfbb092c1bbf9bb2d8cec2d2d77eb89b3e887a (patch)
treec755d3349daa7cd29a7e5a1587ca5cabcd2e9158 /meta
parent1cbabdbd06fd6c9328c94776df372d26396cf9f9 (diff)
downloadpoky-e8dfbb092c1bbf9bb2d8cec2d2d77eb89b3e887a.tar.gz
python-smartpm: fix sometimes reporting no provider instead of conflict
If a requirement of a package is conflicted, depending on how the solution is reached, Smart's transaction code may eliminate all providers of the requirement and then error out because nothing provides them without saying why. To work around this, store a reason 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 will 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 Fixes [YOCTO #4305]. (From OE-Core rev: 1ed09b87fc8780d4a99f6516493fae2e0c92862c) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Saul Wold <sgw@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-devtools/python/python-smartpm/smart-conflict-provider.patch196
-rw-r--r--meta/recipes-devtools/python/python-smartpm_1.4.1.bb1
2 files changed, 197 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python-smartpm/smart-conflict-provider.patch b/meta/recipes-devtools/python/python-smartpm/smart-conflict-provider.patch
new file mode 100644
index 0000000000..10a7447cb4
--- /dev/null
+++ b/meta/recipes-devtools/python/python-smartpm/smart-conflict-provider.patch
@@ -0,0 +1,196 @@
1Report a reason when a dependency could not be installed because it is locked
2
3If a requirement of a package is conflicted, depending on how the
4solution is reached, the transaction code may eliminate all providers
5of the requirement and then error out because nothing provides them. To
6work around this, store a reason in the locked dict and report that back
7if we need to, so for example instead of:
8
9 error: Can't install packagegroup-core-ssh-dropbear-1.0-r1@all: no package provides dropbear
10
11we now get:
12
13 error: Can't install packagegroup-core-ssh-dropbear-1.0-r1@all: unable to install provider for dropbear:
14 error: dropbear-2013.58-r1.0@armv5te is conflicted by openssh-sshd-6.2p2-r0@armv5te
15
16Upstream-Status: Pending
17
18Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
19---
20 smart/const.py | 7 +++++++
21 smart/transaction.py | 58 +++++++++++++++++++++++++++++++++++++++++-----------
22 2 files changed, 53 insertions(+), 12 deletions(-)
23
24diff --git a/smart/const.py b/smart/const.py
25index 4d8e5cb..67c1ac5 100644
26--- a/smart/const.py
27+++ b/smart/const.py
28@@ -70,4 +70,11 @@ DATADIR = "/var/lib/smart/"
29 USERDATADIR = "~/.smart/"
30 CONFFILE = "config"
31
32+LOCKED_INSTALL = Enum('LOCKED_INSTALL')
33+LOCKED_REMOVE = Enum('LOCKED_REMOVE')
34+LOCKED_CONFLICT = Enum('LOCKED_CONFLICT')
35+LOCKED_CONFLICT_BY = Enum('LOCKED_CONFLICT_BY')
36+LOCKED_NO_COEXIST = Enum('LOCKED_NO_COEXIST')
37+LOCKED_SYSCONF = Enum('LOCKED_SYSCONF')
38+
39 # vim:ts=4:sw=4:et
40diff --git a/smart/transaction.py b/smart/transaction.py
41index 300b9cc..dd9aa38 100644
42--- a/smart/transaction.py
43+++ b/smart/transaction.py
44@@ -19,10 +19,31 @@
45 # along with Smart Package Manager; if not, write to the Free Software
46 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 #
48-from smart.const import INSTALL, REMOVE, UPGRADE, FIX, REINSTALL, KEEP
49+from smart.const import INSTALL, REMOVE, UPGRADE, FIX, REINSTALL, KEEP, LOCKED_INSTALL, LOCKED_CONFLICT, LOCKED_CONFLICT_BY, LOCKED_NO_COEXIST, LOCKED_SYSCONF, LOCKED_REMOVE
50 from smart.cache import PreRequires, Package
51 from smart import *
52
53+def lock_reason(pkg, lockvalue):
54+ try:
55+ (reason, otherpkg) = lockvalue
56+ except TypeError:
57+ reason = None
58+ lockvalue = None
59+ if reason == LOCKED_INSTALL:
60+ return _("%s is to be installed") % pkg
61+ elif reason == LOCKED_CONFLICT:
62+ return _("%s conflicts with %s") % (pkg, otherpkg)
63+ elif reason == LOCKED_CONFLICT_BY:
64+ return _("%s is conflicted by %s") % (pkg, otherpkg)
65+ elif reason == LOCKED_NO_COEXIST:
66+ return _("%s cannot coexist with %s") % (pkg, otherpkg)
67+ elif reason == LOCKED_SYSCONF:
68+ return _("%s is locked in system configuration") % pkg
69+ elif reason == LOCKED_REMOVE:
70+ return _("%s is to be removed") % pkg
71+ else:
72+ return _("%s is locked (unknown reason)") % pkg
73+
74 class ChangeSet(dict):
75
76 def __init__(self, cache, state=None, requested=None):
77@@ -187,7 +208,7 @@ class Policy(object):
78 for pkg in pkgconf.filterByFlag("lock", cache.getPackages()):
79 if pkg not in self._locked:
80 self._sysconflocked.append(pkg)
81- self._locked[pkg] = True
82+ self._locked[pkg] = (LOCKED_SYSCONF, None)
83
84 def runFinished(self):
85 self._priorities.clear()
86@@ -524,7 +545,7 @@ class Transaction(object):
87 if ownpending:
88 pending = []
89
90- locked[pkg] = True
91+ locked[pkg] = (LOCKED_INSTALL, None)
92 changeset.set(pkg, INSTALL)
93 isinst = changeset.installed
94
95@@ -535,7 +556,7 @@ class Transaction(object):
96 if prvpkg is pkg:
97 continue
98 if not isinst(prvpkg):
99- locked[prvpkg] = True
100+ locked[prvpkg] = (LOCKED_CONFLICT_BY, pkg)
101 continue
102 if prvpkg in locked:
103 raise Failed, _("Can't install %s: conflicted package "
104@@ -550,7 +571,7 @@ class Transaction(object):
105 if cnfpkg is pkg:
106 continue
107 if not isinst(cnfpkg):
108- locked[cnfpkg] = True
109+ locked[cnfpkg] = (LOCKED_CONFLICT, pkg)
110 continue
111 if cnfpkg in locked:
112 raise Failed, _("Can't install %s: it's conflicted by "
113@@ -565,7 +586,7 @@ class Transaction(object):
114 for namepkg in namepkgs:
115 if namepkg is not pkg and not pkg.coexists(namepkg):
116 if not isinst(namepkg):
117- locked[namepkg] = True
118+ locked[namepkg] = (LOCKED_NO_COEXIST, pkg)
119 continue
120 if namepkg in locked:
121 raise Failed, _("Can't install %s: it can't coexist "
122@@ -577,6 +598,7 @@ class Transaction(object):
123
124 # Check if someone is already providing it.
125 prvpkgs = {}
126+ lockedpkgs = {}
127 found = False
128 for prv in req.providedby:
129 for prvpkg in prv.packages:
130@@ -585,6 +607,8 @@ class Transaction(object):
131 break
132 if prvpkg not in locked:
133 prvpkgs[prvpkg] = True
134+ else:
135+ lockedpkgs[prvpkg] = locked[prvpkg]
136 else:
137 continue
138 break
139@@ -597,7 +621,17 @@ class Transaction(object):
140 if not prvpkgs:
141 # No packages provide it at all. Give up.
142 if req in pkg.requires:
143- raise Failed, _("Can't install %s: no package provides %s") % \
144+ reasons = []
145+ for prv in req.providedby:
146+ for prvpkg in prv.packages:
147+ lockedres = lockedpkgs.get(prvpkg, None)
148+ if lockedres:
149+ reasons.append(lock_reason(prvpkg, lockedres))
150+ if reasons:
151+ raise Failed, _("Can't install %s: unable to install provider for %s:\n %s") % \
152+ (pkg, req, '\n '.join(reasons))
153+ else:
154+ raise Failed, _("Can't install %s: no package provides %s") % \
155 (pkg, req)
156 else:
157 # It's only a recommend, skip
158@@ -627,7 +661,7 @@ class Transaction(object):
159 if ownpending:
160 pending = []
161
162- locked[pkg] = True
163+ locked[pkg] = (LOCKED_REMOVE, None)
164 changeset.set(pkg, REMOVE)
165 isinst = changeset.installed
166
167@@ -1140,22 +1174,22 @@ class Transaction(object):
168 if op is KEEP:
169 if pkg in changeset:
170 del changeset[pkg]
171- locked[pkg] = True
172+ locked[pkg] = (LOCKED_KEEP, None)
173 elif op is INSTALL:
174 if not isinst(pkg) and pkg in locked:
175 raise Failed, _("Can't install %s: it's locked") % pkg
176 changeset.set(pkg, INSTALL)
177- locked[pkg] = True
178+ locked[pkg] = (LOCKED_INSTALL, None)
179 elif op is REMOVE:
180 if isinst(pkg) and pkg in locked:
181 raise Failed, _("Can't remove %s: it's locked") % pkg
182 changeset.set(pkg, REMOVE)
183- locked[pkg] = True
184+ locked[pkg] = (LOCKED_REMOVE, None)
185 elif op is REINSTALL:
186 if pkg in locked:
187 raise Failed, _("Can't reinstall %s: it's locked")%pkg
188 changeset.set(pkg, INSTALL, force=True)
189- locked[pkg] = True
190+ locked[pkg] = (LOCKED_INSTALL, None)
191 elif op is UPGRADE:
192 pass
193
194--
1951.8.1.2
196
diff --git a/meta/recipes-devtools/python/python-smartpm_1.4.1.bb b/meta/recipes-devtools/python/python-smartpm_1.4.1.bb
index 0cf3847c77..3e392311f3 100644
--- a/meta/recipes-devtools/python/python-smartpm_1.4.1.bb
+++ b/meta/recipes-devtools/python/python-smartpm_1.4.1.bb
@@ -26,6 +26,7 @@ SRC_URI = "\
26 file://smart-multilib-fixes.patch \ 26 file://smart-multilib-fixes.patch \
27 file://smart-yaml-error.patch \ 27 file://smart-yaml-error.patch \
28 file://smart-channelsdir.patch \ 28 file://smart-channelsdir.patch \
29 file://smart-conflict-provider.patch \
29 " 30 "
30 31
31SRC_URI[md5sum] = "573ef32ba177a6b3c4bf7ef04873fcb6" 32SRC_URI[md5sum] = "573ef32ba177a6b3c4bf7ef04873fcb6"