With the following config and build image: ... IMAGE_INSTALL_append = "shadow man-pages" EXTRA_IMAGE_FEATURES += "doc-pkgs" ... There is an error during install with --attempt, and it breaks the build. ... |error: file /usr/share/man/man5/passwd.5 from install of shadow-doc-4.2.1-r0.i586 conflicts with file from package man-pages-3.71-r0.i586 ... For complementary and 'attemptonly' package processing, we should make sure the warn rather than error messages reported. [YOCTO #6769] (From OE-Core rev: beb2e989e24e671fecd37805876dfb2375ee0df6) Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
189 lines
8.1 KiB
Diff
189 lines
8.1 KiB
Diff
From b105e7fe812da3ccaf7155c0fe14c8728b0d39a5 Mon Sep 17 00:00:00 2001
|
|
From: Mark Hatle <mark.hatle@windriver.com>
|
|
Date: Mon, 20 Jan 2014 14:30:52 +0000
|
|
Subject: [PATCH] Add mechanism to attempt install without failing
|
|
|
|
In OpenEmbedded, for complementary and 'attemptonly' package processing,
|
|
we need a way to instruct smart to try to install, but ignore any
|
|
failures (usually conflicts).
|
|
|
|
This option only works for the install operation.
|
|
|
|
Upstream-Status: Pending
|
|
|
|
Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
|
|
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
|
|
|
|
For complementary and 'attemptonly' package processing, we should
|
|
make sure the warn rather than error reported.
|
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
|
---
|
|
smart.py | 5 +++-
|
|
smart/commands/install.py | 5 ++++
|
|
smart/transaction.py | 65 +++++++++++++++++++++++++++++++++++------------
|
|
3 files changed, 58 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/smart.py b/smart.py
|
|
index c5c7a02..7e7fd34 100755
|
|
--- a/smart.py
|
|
+++ b/smart.py
|
|
@@ -179,7 +179,10 @@ def main(argv):
|
|
if opts and opts.log_level == "debug":
|
|
import traceback
|
|
traceback.print_exc()
|
|
- if iface.object:
|
|
+ if iface.object and sysconf.has("attempt-install", soft=True):
|
|
+ iface.warning(unicode(e))
|
|
+ exitcode = 0
|
|
+ elif iface.object:
|
|
iface.error(unicode(e))
|
|
else:
|
|
sys.stderr.write(_("error: %s\n") % e)
|
|
diff --git a/smart/commands/install.py b/smart/commands/install.py
|
|
index 590222c..6ef9682 100644
|
|
--- a/smart/commands/install.py
|
|
+++ b/smart/commands/install.py
|
|
@@ -50,6 +50,8 @@ def option_parser():
|
|
parser = OptionParser(usage=USAGE,
|
|
description=DESCRIPTION,
|
|
examples=EXAMPLES)
|
|
+ parser.add_option("--attempt", action="store_true",
|
|
+ help=_("attempt to install packages, ignore failures"))
|
|
parser.add_option("--stepped", action="store_true",
|
|
help=_("split operation in steps"))
|
|
parser.add_option("--urls", action="store_true",
|
|
@@ -80,6 +82,9 @@ def main(ctrl, opts):
|
|
if not opts.args:
|
|
raise Error, _("no package(s) given")
|
|
|
|
+ if opts.attempt:
|
|
+ sysconf.set("attempt-install", True, soft=True)
|
|
+
|
|
if opts.explain:
|
|
sysconf.set("explain-changesets", True, soft=True)
|
|
|
|
diff --git a/smart/transaction.py b/smart/transaction.py
|
|
index 5730a42..e3e61c6 100644
|
|
--- a/smart/transaction.py
|
|
+++ b/smart/transaction.py
|
|
@@ -555,6 +555,8 @@ class Transaction(object):
|
|
changeset.set(pkg, INSTALL)
|
|
isinst = changeset.installed
|
|
|
|
+ attempt = sysconf.has("attempt-install", soft=True)
|
|
+
|
|
# Remove packages conflicted by this one.
|
|
for cnf in pkg.conflicts:
|
|
for prv in cnf.providedby:
|
|
@@ -564,11 +566,16 @@ class Transaction(object):
|
|
if not isinst(prvpkg):
|
|
locked[prvpkg] = (LOCKED_CONFLICT_BY, pkg)
|
|
continue
|
|
- if prvpkg in locked:
|
|
- raise Failed, _("Can't install %s: conflicted package "
|
|
- "%s is locked") % (pkg, prvpkg)
|
|
- self._remove(prvpkg, changeset, locked, pending, depth)
|
|
- pending.append((PENDING_UPDOWN, prvpkg))
|
|
+ if attempt:
|
|
+ del changeset[pkg]
|
|
+ raise Failed, _("Can't install %s: it conflicts with package "
|
|
+ "%s") % (pkg, prvpkg)
|
|
+ else:
|
|
+ if prvpkg in locked:
|
|
+ raise Failed, _("Can't install %s: conflicted package "
|
|
+ "%s is locked") % (pkg, prvpkg)
|
|
+ self._remove(prvpkg, changeset, locked, pending, depth)
|
|
+ pending.append((PENDING_UPDOWN, prvpkg))
|
|
|
|
# Remove packages conflicting with this one.
|
|
for prv in pkg.provides:
|
|
@@ -579,12 +586,18 @@ class Transaction(object):
|
|
if not isinst(cnfpkg):
|
|
locked[cnfpkg] = (LOCKED_CONFLICT, pkg)
|
|
continue
|
|
- if cnfpkg in locked:
|
|
+ if attempt:
|
|
+ del changeset[pkg]
|
|
raise Failed, _("Can't install %s: it's conflicted by "
|
|
- "the locked package %s") \
|
|
- % (pkg, cnfpkg)
|
|
- self._remove(cnfpkg, changeset, locked, pending, depth)
|
|
- pending.append((PENDING_UPDOWN, cnfpkg))
|
|
+ "the package %s") \
|
|
+ % (pkg, cnfpkg)
|
|
+ else:
|
|
+ if cnfpkg in locked:
|
|
+ raise Failed, _("Can't install %s: it's conflicted by "
|
|
+ "the locked package %s") \
|
|
+ % (pkg, cnfpkg)
|
|
+ self._remove(cnfpkg, changeset, locked, pending, depth)
|
|
+ pending.append((PENDING_UPDOWN, cnfpkg))
|
|
|
|
# Remove packages with the same name that can't
|
|
# coexist with this one.
|
|
@@ -594,10 +607,15 @@ class Transaction(object):
|
|
if not isinst(namepkg):
|
|
locked[namepkg] = (LOCKED_NO_COEXIST, pkg)
|
|
continue
|
|
- if namepkg in locked:
|
|
+ if attempt:
|
|
+ del changeset[pkg]
|
|
raise Failed, _("Can't install %s: it can't coexist "
|
|
"with %s") % (pkg, namepkg)
|
|
- self._remove(namepkg, changeset, locked, pending, depth)
|
|
+ else:
|
|
+ if namepkg in locked:
|
|
+ raise Failed, _("Can't install %s: it can't coexist "
|
|
+ "with %s") % (pkg, namepkg)
|
|
+ self._remove(namepkg, changeset, locked, pending, depth)
|
|
|
|
# Install packages required by this one.
|
|
for req in pkg.requires + pkg.recommends:
|
|
@@ -1176,6 +1194,8 @@ class Transaction(object):
|
|
|
|
self._policy.runStarting()
|
|
|
|
+ attempt = sysconf.has("attempt-install", soft=True)
|
|
+
|
|
try:
|
|
changeset = self._changeset.copy()
|
|
isinst = changeset.installed
|
|
@@ -1190,7 +1210,11 @@ class Transaction(object):
|
|
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
|
|
+ if attempt:
|
|
+ iface.warning(_("Can't install %s: it's locked") % pkg)
|
|
+ del changeset[pkg]
|
|
+ else:
|
|
+ raise Failed, _("Can't install %s: it's locked") % pkg
|
|
changeset.set(pkg, INSTALL)
|
|
locked[pkg] = (LOCKED_INSTALL, None)
|
|
elif op is REMOVE:
|
|
@@ -1216,9 +1240,18 @@ class Transaction(object):
|
|
else:
|
|
op = REMOVE
|
|
if op is INSTALL or op is REINSTALL:
|
|
- self._install(pkg, changeset, locked, pending)
|
|
- if pkg in changeset:
|
|
- changeset.setRequested(pkg, True)
|
|
+ try:
|
|
+ self._install(pkg, changeset, locked, pending)
|
|
+ if pkg in changeset:
|
|
+ changeset.setRequested(pkg, True)
|
|
+ except Failed, e:
|
|
+ if attempt:
|
|
+ iface.warning(_("Can't install %s: %s") % (pkg, e))
|
|
+ if pkg in changeset:
|
|
+ del changeset[pkg]
|
|
+ continue
|
|
+ else:
|
|
+ raise Failed, e
|
|
elif op is REMOVE:
|
|
self._remove(pkg, changeset, locked, pending)
|
|
elif op is UPGRADE:
|
|
--
|
|
1.9.1
|
|
|