diff options
Diffstat (limited to 'meta/recipes-devtools/python/python-smartpm/smart-attempt.patch')
-rw-r--r-- | meta/recipes-devtools/python/python-smartpm/smart-attempt.patch | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch new file mode 100644 index 0000000000..82d2e6cf31 --- /dev/null +++ b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch | |||
@@ -0,0 +1,223 @@ | |||
1 | From b105e7fe812da3ccaf7155c0fe14c8728b0d39a5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mark Hatle <mark.hatle@windriver.com> | ||
3 | Date: Mon, 20 Jan 2014 14:30:52 +0000 | ||
4 | Subject: [PATCH] Add mechanism to attempt install without failing | ||
5 | |||
6 | In OpenEmbedded, for complementary and 'attemptonly' package processing, | ||
7 | we need a way to instruct smart to try to install, but ignore any | ||
8 | failures (usually conflicts). | ||
9 | |||
10 | This option only works for the install operation. | ||
11 | |||
12 | If a complementary install fails, an actual error occurred, one that | ||
13 | we can't ignore without losing the entire attempted transaction. Keep | ||
14 | this as an error so that we can catch these cases in the futre. | ||
15 | |||
16 | Upstream-Status: Pending | ||
17 | |||
18 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> | ||
19 | Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> | ||
20 | --- | ||
21 | smart.py | 5 +++- | ||
22 | smart/commands/install.py | 5 ++++ | ||
23 | smart/transaction.py | 65 +++++++++++++++++++++++++++++++++++------------ | ||
24 | 3 files changed, 58 insertions(+), 17 deletions(-) | ||
25 | |||
26 | Index: smart-1.4.1/smart/commands/install.py | ||
27 | =================================================================== | ||
28 | --- smart-1.4.1.orig/smart/commands/install.py | ||
29 | +++ smart-1.4.1/smart/commands/install.py | ||
30 | @@ -50,6 +50,8 @@ def option_parser(): | ||
31 | parser = OptionParser(usage=USAGE, | ||
32 | description=DESCRIPTION, | ||
33 | examples=EXAMPLES) | ||
34 | + parser.add_option("--attempt", action="store_true", | ||
35 | + help=_("attempt to install packages, ignore failures")) | ||
36 | parser.add_option("--stepped", action="store_true", | ||
37 | help=_("split operation in steps")) | ||
38 | parser.add_option("--urls", action="store_true", | ||
39 | @@ -80,6 +82,9 @@ def main(ctrl, opts): | ||
40 | if not opts.args: | ||
41 | raise Error, _("no package(s) given") | ||
42 | |||
43 | + if opts.attempt: | ||
44 | + sysconf.set("attempt-install", True, soft=True) | ||
45 | + | ||
46 | if opts.explain: | ||
47 | sysconf.set("explain-changesets", True, soft=True) | ||
48 | |||
49 | Index: smart-1.4.1/smart/transaction.py | ||
50 | =================================================================== | ||
51 | --- smart-1.4.1.orig/smart/transaction.py | ||
52 | +++ smart-1.4.1/smart/transaction.py | ||
53 | @@ -555,6 +555,8 @@ class Transaction(object): | ||
54 | changeset.set(pkg, INSTALL) | ||
55 | isinst = changeset.installed | ||
56 | |||
57 | + attempt = sysconf.has("attempt-install", soft=True) | ||
58 | + | ||
59 | # Remove packages conflicted by this one. | ||
60 | for cnf in pkg.conflicts: | ||
61 | for prv in cnf.providedby: | ||
62 | @@ -564,11 +566,16 @@ class Transaction(object): | ||
63 | if not isinst(prvpkg): | ||
64 | locked[prvpkg] = (LOCKED_CONFLICT_BY, pkg) | ||
65 | continue | ||
66 | - if prvpkg in locked: | ||
67 | - raise Failed, _("Can't install %s: conflicted package " | ||
68 | - "%s is locked") % (pkg, prvpkg) | ||
69 | - self._remove(prvpkg, changeset, locked, pending, depth) | ||
70 | - pending.append((PENDING_UPDOWN, prvpkg)) | ||
71 | + if attempt: | ||
72 | + del changeset[pkg] | ||
73 | + raise Failed, _("Can't install %s: it conflicts with package " | ||
74 | + "%s") % (pkg, prvpkg) | ||
75 | + else: | ||
76 | + if prvpkg in locked: | ||
77 | + raise Failed, _("Can't install %s: conflicted package " | ||
78 | + "%s is locked") % (pkg, prvpkg) | ||
79 | + self._remove(prvpkg, changeset, locked, pending, depth) | ||
80 | + pending.append((PENDING_UPDOWN, prvpkg)) | ||
81 | |||
82 | # Remove packages conflicting with this one. | ||
83 | for prv in pkg.provides: | ||
84 | @@ -579,12 +586,18 @@ class Transaction(object): | ||
85 | if not isinst(cnfpkg): | ||
86 | locked[cnfpkg] = (LOCKED_CONFLICT, pkg) | ||
87 | continue | ||
88 | - if cnfpkg in locked: | ||
89 | + if attempt: | ||
90 | + del changeset[pkg] | ||
91 | raise Failed, _("Can't install %s: it's conflicted by " | ||
92 | - "the locked package %s") \ | ||
93 | - % (pkg, cnfpkg) | ||
94 | - self._remove(cnfpkg, changeset, locked, pending, depth) | ||
95 | - pending.append((PENDING_UPDOWN, cnfpkg)) | ||
96 | + "the package %s") \ | ||
97 | + % (pkg, cnfpkg) | ||
98 | + else: | ||
99 | + if cnfpkg in locked: | ||
100 | + raise Failed, _("Can't install %s: it's conflicted by " | ||
101 | + "the locked package %s") \ | ||
102 | + % (pkg, cnfpkg) | ||
103 | + self._remove(cnfpkg, changeset, locked, pending, depth) | ||
104 | + pending.append((PENDING_UPDOWN, cnfpkg)) | ||
105 | |||
106 | # Remove packages with the same name that can't | ||
107 | # coexist with this one. | ||
108 | @@ -594,10 +607,15 @@ class Transaction(object): | ||
109 | if not isinst(namepkg): | ||
110 | locked[namepkg] = (LOCKED_NO_COEXIST, pkg) | ||
111 | continue | ||
112 | - if namepkg in locked: | ||
113 | + if attempt: | ||
114 | + del changeset[pkg] | ||
115 | raise Failed, _("Can't install %s: it can't coexist " | ||
116 | "with %s") % (pkg, namepkg) | ||
117 | - self._remove(namepkg, changeset, locked, pending, depth) | ||
118 | + else: | ||
119 | + if namepkg in locked: | ||
120 | + raise Failed, _("Can't install %s: it can't coexist " | ||
121 | + "with %s") % (pkg, namepkg) | ||
122 | + self._remove(namepkg, changeset, locked, pending, depth) | ||
123 | |||
124 | # Install packages required by this one. | ||
125 | for req in pkg.requires + pkg.recommends: | ||
126 | @@ -1176,6 +1194,8 @@ class Transaction(object): | ||
127 | |||
128 | self._policy.runStarting() | ||
129 | |||
130 | + attempt = sysconf.has("attempt-install", soft=True) | ||
131 | + | ||
132 | try: | ||
133 | changeset = self._changeset.copy() | ||
134 | isinst = changeset.installed | ||
135 | @@ -1190,7 +1210,11 @@ class Transaction(object): | ||
136 | locked[pkg] = (LOCKED_KEEP, None) | ||
137 | elif op is INSTALL: | ||
138 | if not isinst(pkg) and pkg in locked: | ||
139 | - raise Failed, _("Can't install %s: it's locked") % pkg | ||
140 | + if attempt: | ||
141 | + iface.warning(_("Can't install %s: it's locked") % pkg) | ||
142 | + del changeset[pkg] | ||
143 | + else: | ||
144 | + raise Failed, _("Can't install %s: it's locked") % pkg | ||
145 | changeset.set(pkg, INSTALL) | ||
146 | locked[pkg] = (LOCKED_INSTALL, None) | ||
147 | elif op is REMOVE: | ||
148 | @@ -1216,9 +1240,18 @@ class Transaction(object): | ||
149 | else: | ||
150 | op = REMOVE | ||
151 | if op is INSTALL or op is REINSTALL: | ||
152 | - self._install(pkg, changeset, locked, pending) | ||
153 | - if pkg in changeset: | ||
154 | - changeset.setRequested(pkg, True) | ||
155 | + try: | ||
156 | + self._install(pkg, changeset, locked, pending) | ||
157 | + if pkg in changeset: | ||
158 | + changeset.setRequested(pkg, True) | ||
159 | + except Failed, e: | ||
160 | + if attempt: | ||
161 | + iface.warning(_("Can't install %s: %s") % (pkg, e)) | ||
162 | + if pkg in changeset: | ||
163 | + del changeset[pkg] | ||
164 | + continue | ||
165 | + else: | ||
166 | + raise Failed, e | ||
167 | elif op is REMOVE: | ||
168 | self._remove(pkg, changeset, locked, pending) | ||
169 | elif op is UPGRADE: | ||
170 | Index: smart-1.4.1/smart/backends/rpm/pm.py | ||
171 | =================================================================== | ||
172 | --- smart-1.4.1.orig/smart/backends/rpm/pm.py | ||
173 | +++ smart-1.4.1/smart/backends/rpm/pm.py | ||
174 | @@ -243,15 +253,48 @@ class RPMPackageManager(PackageManager): | ||
175 | cb = RPMCallback(prog, upgradednames) | ||
176 | cb.grabOutput(True) | ||
177 | probs = None | ||
178 | + retry = 0 | ||
179 | try: | ||
180 | probs = ts.run(cb, None) | ||
181 | finally: | ||
182 | del getTS.ts | ||
183 | cb.grabOutput(False) | ||
184 | + if probs and sysconf.has("attempt-install", soft=True): | ||
185 | + def remove_conflict(pkgNEVR): | ||
186 | + for key in changeset.keys(): | ||
187 | + if pkgNEVR == str(key): | ||
188 | + del changeset[key] | ||
189 | + del pkgpaths[key] | ||
190 | + iface.warning("Removing %s due to file %s conflicting with %s" % (pkgNEVR, fname, altNEVR)) | ||
191 | + break | ||
192 | + | ||
193 | + retry = 1 | ||
194 | + for prob in probs: | ||
195 | + if prob[1][0] == rpm.RPMPROB_NEW_FILE_CONFLICT: | ||
196 | + msg = prob[0].split() | ||
197 | + fname = msg[1] | ||
198 | + pkgNEVR = msg[7] | ||
199 | + altNEVR = msg[9] | ||
200 | + pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1] | ||
201 | + altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1] | ||
202 | + remove_conflict(pkgNEVR) | ||
203 | + elif prob[1][0] == rpm.RPMPROB_FILE_CONFLICT: | ||
204 | + msg = prob[0].split() | ||
205 | + fname = msg[1] | ||
206 | + pkgNEVR = msg[5] | ||
207 | + altNEVR = msg[11] | ||
208 | + pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1] | ||
209 | + altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1] | ||
210 | + remove_conflict(pkgNEVR) | ||
211 | + else: | ||
212 | + retry = 0 | ||
213 | + | ||
214 | prog.setDone() | ||
215 | - if probs: | ||
216 | + if probs and (not retry): | ||
217 | raise Error, "\n".join([x[0] for x in probs]) | ||
218 | prog.stop() | ||
219 | + if retry and len(changeset): | ||
220 | + self.commit(changeset, pkgpaths) | ||
221 | |||
222 | class RPMCallback: | ||
223 | def __init__(self, prog, upgradednames): | ||