blob: ec98e03c0a3c11e53df5be0bf7088884c3e97700 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001From b105e7fe812da3ccaf7155c0fe14c8728b0d39a5 Mon Sep 17 00:00:00 2001
2From: Mark Hatle <mark.hatle@windriver.com>
3Date: Mon, 20 Jan 2014 14:30:52 +0000
4Subject: [PATCH] Add mechanism to attempt install without failing
5
6In OpenEmbedded, for complementary and 'attemptonly' package processing,
7we need a way to instruct smart to try to install, but ignore any
8failures (usually conflicts).
9
10This option only works for the install operation.
11
12If a complementary install fails, an actual error occurred, one that
13we can't ignore without losing the entire attempted transaction. Keep
14this as an error so that we can catch these cases in the futre.
15
16Upstream-Status: Pending
17
18Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
19Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
20---
21 backends/rpm/pm.py | 35 ++++++++++++++++++++++++++++++++++-
22 transaction.py | 50 +++++++++++++++++++++++++++++++++++++-------------
23 2 files changed, 71 insertions(+), 14 deletions(-)
24
25diff --git a/smart/backends/rpm/pm.py b/smart/backends/rpm/pm.py
26index 9bbd952..ba6405a 100644
27--- a/smart/backends/rpm/pm.py
28+++ b/smart/backends/rpm/pm.py
29@@ -241,15 +241,48 @@ class RPMPackageManager(PackageManager):
30 cb = RPMCallback(prog, upgradednames)
31 cb.grabOutput(True)
32 probs = None
33+ retry = 0
34 try:
35 probs = ts.run(cb, None)
36 finally:
37 del getTS.ts
38 cb.grabOutput(False)
39+ if probs and sysconf.has("attempt-install", soft=True):
40+ def remove_conflict(pkgNEVR):
41+ for key in changeset.keys():
42+ if pkgNEVR == str(key):
43+ del changeset[key]
44+ del pkgpaths[key]
45+ iface.warning("Removing %s due to file %s conflicting with %s" % (pkgNEVR, fname, altNEVR))
46+ break
47+
48+ retry = 1
49+ for prob in probs:
50+ if prob[1][0] == rpm.RPMPROB_NEW_FILE_CONFLICT:
51+ msg = prob[0].split()
52+ fname = msg[1]
53+ pkgNEVR = msg[7]
54+ altNEVR = msg[9]
55+ pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
56+ altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
57+ remove_conflict(pkgNEVR)
58+ elif prob[1][0] == rpm.RPMPROB_FILE_CONFLICT:
59+ msg = prob[0].split()
60+ fname = msg[1]
61+ pkgNEVR = msg[5]
62+ altNEVR = msg[11]
63+ pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
64+ altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
65+ remove_conflict(pkgNEVR)
66+ else:
67+ retry = 0
68+
69 prog.setDone()
70- if probs:
71+ if probs and (not retry):
72 raise Error, "\n".join([x[0] for x in probs])
73 prog.stop()
74+ if retry and len(changeset):
75+ self.commit(changeset, pkgpaths)
76
77 class RPMCallback:
78 def __init__(self, prog, upgradednames):
79diff --git a/smart/transaction.py b/smart/transaction.py
80index 4b90cb7..3e043e9 100644
81--- a/smart/transaction.py
82+++ b/smart/transaction.py
83@@ -555,6 +555,8 @@ class Transaction(object):
84 changeset.set(pkg, INSTALL)
85 isinst = changeset.installed
86
87+ attempt = sysconf.has("attempt-install", soft=True)
88+
89 # Remove packages conflicted by this one.
90 for cnf in pkg.conflicts:
91 for prv in cnf.providedby:
92@@ -564,11 +566,16 @@ class Transaction(object):
93 if not isinst(prvpkg):
94 locked[prvpkg] = (LOCKED_CONFLICT_BY, pkg)
95 continue
96- if prvpkg in locked:
97- raise Failed, _("Can't install %s: conflicted package "
98- "%s is locked") % (pkg, prvpkg)
99- self._remove(prvpkg, changeset, locked, pending, depth)
100- pending.append((PENDING_UPDOWN, prvpkg))
101+ if attempt:
102+ del changeset[pkg]
103+ raise Failed, _("Can't install %s: it conflicts with package "
104+ "%s") % (pkg, prvpkg)
105+ else:
106+ if prvpkg in locked:
107+ raise Failed, _("Can't install %s: conflicted package "
108+ "%s is locked") % (pkg, prvpkg)
109+ self._remove(prvpkg, changeset, locked, pending, depth)
110+ pending.append((PENDING_UPDOWN, prvpkg))
111
112 # Remove packages conflicting with this one.
113 for prv in pkg.provides:
114@@ -579,12 +586,18 @@ class Transaction(object):
115 if not isinst(cnfpkg):
116 locked[cnfpkg] = (LOCKED_CONFLICT, pkg)
117 continue
118- if cnfpkg in locked:
119+ if attempt:
120+ del changeset[pkg]
121 raise Failed, _("Can't install %s: it's conflicted by "
122- "the locked package %s") \
123- % (pkg, cnfpkg)
124- self._remove(cnfpkg, changeset, locked, pending, depth)
125- pending.append((PENDING_UPDOWN, cnfpkg))
126+ "the package %s") \
127+ % (pkg, cnfpkg)
128+ else:
129+ if cnfpkg in locked:
130+ raise Failed, _("Can't install %s: it's conflicted by "
131+ "the locked package %s") \
132+ % (pkg, cnfpkg)
133+ self._remove(cnfpkg, changeset, locked, pending, depth)
134+ pending.append((PENDING_UPDOWN, cnfpkg))
135
136 # Remove packages with the same name that can't
137 # coexist with this one.
138@@ -594,10 +607,15 @@ class Transaction(object):
139 if not isinst(namepkg):
140 locked[namepkg] = (LOCKED_NO_COEXIST, pkg)
141 continue
142- if namepkg in locked:
143+ if attempt:
144+ del changeset[pkg]
145 raise Failed, _("Can't install %s: it can't coexist "
146 "with %s") % (pkg, namepkg)
147- self._remove(namepkg, changeset, locked, pending, depth)
148+ else:
149+ if namepkg in locked:
150+ raise Failed, _("Can't install %s: it can't coexist "
151+ "with %s") % (pkg, namepkg)
152+ self._remove(namepkg, changeset, locked, pending, depth)
153
154 # Install packages required by this one.
155 for req in pkg.requires + pkg.recommends:
156@@ -1176,6 +1194,8 @@ class Transaction(object):
157
158 self._policy.runStarting()
159
160+ attempt = sysconf.has("attempt-install", soft=True)
161+
162 try:
163 changeset = self._changeset.copy()
164 isinst = changeset.installed
165@@ -1190,7 +1210,11 @@ class Transaction(object):
166 locked[pkg] = (LOCKED_KEEP, None)
167 elif op is INSTALL:
168 if not isinst(pkg) and pkg in locked:
169- raise Failed, _("Can't install %s: it's locked") % pkg
170+ if attempt:
171+ iface.warning(_("Can't install %s: it's locked") % pkg)
172+ del changeset[pkg]
173+ else:
174+ raise Failed, _("Can't install %s: it's locked") % pkg
175 changeset.set(pkg, INSTALL)
176 locked[pkg] = (LOCKED_INSTALL, None)
177 elif op is REMOVE: