Openembedded Core Discussions
 help / color / mirror / Atom feed
* [PATCH v2] python-smartpm: Fix attemptonly builds when file conflicts occur
@ 2015-01-22  5:31 Mark Hatle
  2015-01-22 14:34 ` Mark Hatle
  0 siblings, 1 reply; 2+ messages in thread
From: Mark Hatle @ 2015-01-22  5:31 UTC (permalink / raw)
  To: openembedded-core

[YOCTO #7299]

When file conflicts occur, the RPM transaction aborts.  Instead of
simply accepting the failure, we now identify, capture, and remove
the offending package(s) from the transaction and retry.

Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
---
 .../python/python-smartpm/smart-attempt.patch      | 97 +++++++++++++++-------
 1 file changed, 66 insertions(+), 31 deletions(-)

diff --git a/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
index 45f7947..648114a 100644
--- a/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
+++ b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
@@ -9,40 +9,24 @@ failures (usually conflicts).
 
 This option only works for the install operation.
 
+If a complementary install fails, an actual error occurred, one that
+we can't ignore without losing the entire attempted transaction.  Keep
+this as an error so that we can catch these cases in the futre.
+
 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
+Index: smart-1.4.1/smart/commands/install.py
+===================================================================
+--- smart-1.4.1.orig/smart/commands/install.py
++++ smart-1.4.1/smart/commands/install.py
 @@ -50,6 +50,8 @@ def option_parser():
      parser = OptionParser(usage=USAGE,
                            description=DESCRIPTION,
@@ -62,10 +46,10 @@ index 590222c..6ef9682 100644
      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
+Index: smart-1.4.1/smart/transaction.py
+===================================================================
+--- smart-1.4.1.orig/smart/transaction.py
++++ smart-1.4.1/smart/transaction.py
 @@ -555,6 +555,8 @@ class Transaction(object):
          changeset.set(pkg, INSTALL)
          isinst = changeset.installed
@@ -183,6 +167,57 @@ index 5730a42..e3e61c6 100644
                  elif op is REMOVE:
                      self._remove(pkg, changeset, locked, pending)
                  elif op is UPGRADE:
--- 
-1.9.1
-
+Index: smart-1.4.1/smart/backends/rpm/pm.py
+===================================================================
+--- smart-1.4.1.orig/smart/backends/rpm/pm.py
++++ smart-1.4.1/smart/backends/rpm/pm.py
+@@ -243,15 +253,48 @@ class RPMPackageManager(PackageManager):
+         cb = RPMCallback(prog, upgradednames)
+         cb.grabOutput(True)
+         probs = None
++        retry = 0
+         try:
+             probs = ts.run(cb, None)
+         finally:
+             del getTS.ts
+             cb.grabOutput(False)
++            if probs and sysconf.has("attempt-install", soft=True):
++                def remove_conflict(pkgNEVR):
++                    for key in changeset.keys():
++                        if pkgNEVR == str(key):
++                            del changeset[key]
++                            del pkgpaths[key]
++                            iface.warning("Removing %s due to file %s conflicting with %s" % (pkgNEVR, fname, altNEVR))
++                            break
++
++                retry = 1
++                for prob in probs:
++                    if prob[1][0] == rpm.RPMPROB_NEW_FILE_CONFLICT:
++                        msg = prob[0].split()
++                        fname = msg[1]
++                        pkgNEVR = msg[7]
++                        altNEVR = msg[9]
++                        pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
++                        altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
++                        remove_conflict(pkgNEVR)
++                    elif prob[1][0] == rpm.RPMPROB_FILE_CONFLICT:
++                        msg = prob[0].split()
++                        fname = msg[1]
++                        pkgNEVR = msg[5]
++                        altNEVR = msg[11]
++                        pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
++                        altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
++                        remove_conflict(pkgNEVR)
++                    else:
++                        retry = 0
++
+             prog.setDone()
+-            if probs:
++            if probs and (!retry):
+                 raise Error, "\n".join([x[0] for x in probs])
+             prog.stop()
++            if retry and len(changeset):
++                self.commit(changeset, pkgpaths)
+ 
+ class RPMCallback:
+     def __init__(self, prog, upgradednames):
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] python-smartpm: Fix attemptonly builds when file conflicts occur
  2015-01-22  5:31 [PATCH v2] python-smartpm: Fix attemptonly builds when file conflicts occur Mark Hatle
@ 2015-01-22 14:34 ` Mark Hatle
  0 siblings, 0 replies; 2+ messages in thread
From: Mark Hatle @ 2015-01-22 14:34 UTC (permalink / raw)
  To: openembedded-core

On 1/21/15 11:31 PM, Mark Hatle wrote:
> [YOCTO #7299]
> 
> When file conflicts occur, the RPM transaction aborts.  Instead of
> simply accepting the failure, we now identify, capture, and remove
> the offending package(s) from the transaction and retry.

Please hold off on this.  I typo'd something else in the actual code right
before sending it.  (This is what I get sending it late at night when I'm half
asleep...)

v3 coming soon.

--Mark

> Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
> ---
>  .../python/python-smartpm/smart-attempt.patch      | 97 +++++++++++++++-------
>  1 file changed, 66 insertions(+), 31 deletions(-)
> 
> diff --git a/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
> index 45f7947..648114a 100644
> --- a/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
> +++ b/meta/recipes-devtools/python/python-smartpm/smart-attempt.patch
> @@ -9,40 +9,24 @@ failures (usually conflicts).
>  
>  This option only works for the install operation.
>  
> +If a complementary install fails, an actual error occurred, one that
> +we can't ignore without losing the entire attempted transaction.  Keep
> +this as an error so that we can catch these cases in the futre.
> +
>  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
> +Index: smart-1.4.1/smart/commands/install.py
> +===================================================================
> +--- smart-1.4.1.orig/smart/commands/install.py
> ++++ smart-1.4.1/smart/commands/install.py
>  @@ -50,6 +50,8 @@ def option_parser():
>       parser = OptionParser(usage=USAGE,
>                             description=DESCRIPTION,
> @@ -62,10 +46,10 @@ index 590222c..6ef9682 100644
>       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
> +Index: smart-1.4.1/smart/transaction.py
> +===================================================================
> +--- smart-1.4.1.orig/smart/transaction.py
> ++++ smart-1.4.1/smart/transaction.py
>  @@ -555,6 +555,8 @@ class Transaction(object):
>           changeset.set(pkg, INSTALL)
>           isinst = changeset.installed
> @@ -183,6 +167,57 @@ index 5730a42..e3e61c6 100644
>                   elif op is REMOVE:
>                       self._remove(pkg, changeset, locked, pending)
>                   elif op is UPGRADE:
> --- 
> -1.9.1
> -
> +Index: smart-1.4.1/smart/backends/rpm/pm.py
> +===================================================================
> +--- smart-1.4.1.orig/smart/backends/rpm/pm.py
> ++++ smart-1.4.1/smart/backends/rpm/pm.py
> +@@ -243,15 +253,48 @@ class RPMPackageManager(PackageManager):
> +         cb = RPMCallback(prog, upgradednames)
> +         cb.grabOutput(True)
> +         probs = None
> ++        retry = 0
> +         try:
> +             probs = ts.run(cb, None)
> +         finally:
> +             del getTS.ts
> +             cb.grabOutput(False)
> ++            if probs and sysconf.has("attempt-install", soft=True):
> ++                def remove_conflict(pkgNEVR):
> ++                    for key in changeset.keys():
> ++                        if pkgNEVR == str(key):
> ++                            del changeset[key]
> ++                            del pkgpaths[key]
> ++                            iface.warning("Removing %s due to file %s conflicting with %s" % (pkgNEVR, fname, altNEVR))
> ++                            break
> ++
> ++                retry = 1
> ++                for prob in probs:
> ++                    if prob[1][0] == rpm.RPMPROB_NEW_FILE_CONFLICT:
> ++                        msg = prob[0].split()
> ++                        fname = msg[1]
> ++                        pkgNEVR = msg[7]
> ++                        altNEVR = msg[9]
> ++                        pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
> ++                        altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
> ++                        remove_conflict(pkgNEVR)
> ++                    elif prob[1][0] == rpm.RPMPROB_FILE_CONFLICT:
> ++                        msg = prob[0].split()
> ++                        fname = msg[1]
> ++                        pkgNEVR = msg[5]
> ++                        altNEVR = msg[11]
> ++                        pkgNEVR = pkgNEVR.rsplit('.', 1)[0] + '@' + pkgNEVR.rsplit('.', 1)[1]
> ++                        altNEVR = altNEVR.rsplit('.', 1)[0] + '@' + altNEVR.rsplit('.', 1)[1]
> ++                        remove_conflict(pkgNEVR)
> ++                    else:
> ++                        retry = 0
> ++
> +             prog.setDone()
> +-            if probs:
> ++            if probs and (!retry):
> +                 raise Error, "\n".join([x[0] for x in probs])
> +             prog.stop()
> ++            if retry and len(changeset):
> ++                self.commit(changeset, pkgpaths)
> + 
> + class RPMCallback:
> +     def __init__(self, prog, upgradednames):
> 



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-01-22 14:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-22  5:31 [PATCH v2] python-smartpm: Fix attemptonly builds when file conflicts occur Mark Hatle
2015-01-22 14:34 ` Mark Hatle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox