Re: [gentoo-portage-dev] [PATCH] Introduce depgraph._extend_slot_operator_conflicts

2014-04-05 Thread Sergei Trofimovich
On Thu, 27 Feb 2014 20:08:49 +0100
Sebastian Luther sebastianlut...@gmx.de wrote:

 This function allows emerge to solve more slot conflicts without
 backtracking.
 
 It does this by creating more conflicts for packages with built slot
 operator dependencies. This gives more freedom to
 depgraph._solve_non_slot_operator_slot_conflicts, which is then able
 to solve conflicts it wouldn't have otherwise.
 ---

Nice patch!
For haskell packages it makes huge difference.

My typical workflow is:
- bump some package foo and it's subslot
- emerge -1 foo -j9 
- see what will get rebuilt/broken by subslot rebuild

If package would trigger 500 rebuilds portage had no chance
to find a solution with backtracks. Now sometimes it does.

Thanks!

  pym/_emerge/depgraph.py| 483 
 +++--
  pym/_emerge/resolver/output.py |   5 +-
  2 files changed, 415 insertions(+), 73 deletions(-)
 
 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
 index 835bd6b..970a9c7 100644
 --- a/pym/_emerge/depgraph.py
 +++ b/pym/_emerge/depgraph.py
 @@ -427,6 +427,12 @@ class _dynamic_depgraph_config(object):
   # Track missed updates caused by solved conflicts.
   self._conflict_missed_update = collections.defaultdict(dict)
  
 + # Rebuilds caused by slot conflicts.
 + self._slot_conflict_rebuilds = {}
 + # Rebuilds caused by missed slot operator updates or
 + # slot conflicts.
 + self._forced_rebuilds = None
 +
   for myroot in depgraph._frozen_config.trees:
   self.sets[myroot] = _depgraph_sets()
   vardb = 
 depgraph._frozen_config.trees[myroot][vartree].dbapi
 @@ -614,6 +620,9 @@ class depgraph(object):
   Fill self._forced_rebuilds with packages that cause rebuilds.
   
  
 + if self._dynamic_config._forced_rebuilds is not None:
 + return
 +
   debug = --debug in self._frozen_config.myopts
  
   # Get all atoms that might have caused a forced rebuild.
 @@ -687,19 +696,23 @@ class depgraph(object):
   writemsg_level(\n\n,
   level=logging.DEBUG, noiselevel=-1)
  
 - self._forced_rebuilds = forced_rebuilds
 + for child, parents in 
 self._dynamic_config._slot_conflict_rebuilds.items():
 + forced_rebuilds.setdefault(child.root, 
 {}).setdefault(child, set()).update(parents)
 +
 + self._dynamic_config._forced_rebuilds = forced_rebuilds
  
   def _show_abi_rebuild_info(self):
  
 - if not self._forced_rebuilds:
 + forced_rebuilds = self._dynamic_config._forced_rebuilds
 + if not forced_rebuilds:
   return
  
   writemsg_stdout(\nThe following packages are causing 
 rebuilds:\n\n, noiselevel=-1)
  
 - for root in self._forced_rebuilds:
 - for child in self._forced_rebuilds[root]:
 + for root in forced_rebuilds:
 + for child in forced_rebuilds[root]:
   writemsg_stdout(  %s causes rebuilds for:\n % 
 (child,), noiselevel=-1)
 - for parent in 
 self._forced_rebuilds[root][child]:
 + for parent in forced_rebuilds[root][child]:
   writemsg_stdout(%s\n % (parent,), 
 noiselevel=-1)
  
   def _show_ignored_binaries(self):
 @@ -968,16 +981,16 @@ class depgraph(object):
   writemsg(line + '\n', noiselevel=-1)
   writemsg('\n', noiselevel=-1)
  
 - def _solve_non_slot_operator_slot_conflicts(self):
 +
 + def _extend_slot_operator_conflicts(self):
   
 - This function solves slot conflicts which can
 - be solved by simply choosing one of the conflicting
 - and removing all the other ones.
 - It is able to solve somewhat more complex cases where
 - conflicts can only be solved simultaniously.
 + This function searches for packages that cause
 + slot conflicts by dependening on conflict packages
 + with built slot operator deps. If such a package
 + is found an alternative package is pulled in with
 + the hope that the alternative package would not
 + cuase the slot conflict.
   
 - debug = --debug in self._frozen_config.myopts
 -
   # List all conflicts. Ignore those that involve slot operator 
 rebuilds
   # as the logic there needs special slot conflict behavior which 
 isn't
   # provided by this function.
 @@ -990,9 +1003,133 @@ class depgraph(object):
   if not conflicts:
   return
  
 - # Get a set of all conflicting packages.
 + 

[gentoo-portage-dev] [PATCH] Introduce depgraph._extend_slot_operator_conflicts

2014-02-27 Thread Sebastian Luther
This function allows emerge to solve more slot conflicts without
backtracking.

It does this by creating more conflicts for packages with built slot
operator dependencies. This gives more freedom to
depgraph._solve_non_slot_operator_slot_conflicts, which is then able
to solve conflicts it wouldn't have otherwise.
---
 pym/_emerge/depgraph.py| 483 +++--
 pym/_emerge/resolver/output.py |   5 +-
 2 files changed, 415 insertions(+), 73 deletions(-)

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 835bd6b..970a9c7 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -427,6 +427,12 @@ class _dynamic_depgraph_config(object):
# Track missed updates caused by solved conflicts.
self._conflict_missed_update = collections.defaultdict(dict)
 
+   # Rebuilds caused by slot conflicts.
+   self._slot_conflict_rebuilds = {}
+   # Rebuilds caused by missed slot operator updates or
+   # slot conflicts.
+   self._forced_rebuilds = None
+
for myroot in depgraph._frozen_config.trees:
self.sets[myroot] = _depgraph_sets()
vardb = 
depgraph._frozen_config.trees[myroot][vartree].dbapi
@@ -614,6 +620,9 @@ class depgraph(object):
Fill self._forced_rebuilds with packages that cause rebuilds.

 
+   if self._dynamic_config._forced_rebuilds is not None:
+   return
+
debug = --debug in self._frozen_config.myopts
 
# Get all atoms that might have caused a forced rebuild.
@@ -687,19 +696,23 @@ class depgraph(object):
writemsg_level(\n\n,
level=logging.DEBUG, noiselevel=-1)
 
-   self._forced_rebuilds = forced_rebuilds
+   for child, parents in 
self._dynamic_config._slot_conflict_rebuilds.items():
+   forced_rebuilds.setdefault(child.root, 
{}).setdefault(child, set()).update(parents)
+
+   self._dynamic_config._forced_rebuilds = forced_rebuilds
 
def _show_abi_rebuild_info(self):
 
-   if not self._forced_rebuilds:
+   forced_rebuilds = self._dynamic_config._forced_rebuilds
+   if not forced_rebuilds:
return
 
writemsg_stdout(\nThe following packages are causing 
rebuilds:\n\n, noiselevel=-1)
 
-   for root in self._forced_rebuilds:
-   for child in self._forced_rebuilds[root]:
+   for root in forced_rebuilds:
+   for child in forced_rebuilds[root]:
writemsg_stdout(  %s causes rebuilds for:\n % 
(child,), noiselevel=-1)
-   for parent in 
self._forced_rebuilds[root][child]:
+   for parent in forced_rebuilds[root][child]:
writemsg_stdout(%s\n % (parent,), 
noiselevel=-1)
 
def _show_ignored_binaries(self):
@@ -968,16 +981,16 @@ class depgraph(object):
writemsg(line + '\n', noiselevel=-1)
writemsg('\n', noiselevel=-1)
 
-   def _solve_non_slot_operator_slot_conflicts(self):
+
+   def _extend_slot_operator_conflicts(self):

-   This function solves slot conflicts which can
-   be solved by simply choosing one of the conflicting
-   and removing all the other ones.
-   It is able to solve somewhat more complex cases where
-   conflicts can only be solved simultaniously.
+   This function searches for packages that cause
+   slot conflicts by dependening on conflict packages
+   with built slot operator deps. If such a package
+   is found an alternative package is pulled in with
+   the hope that the alternative package would not
+   cuase the slot conflict.

-   debug = --debug in self._frozen_config.myopts
-
# List all conflicts. Ignore those that involve slot operator 
rebuilds
# as the logic there needs special slot conflict behavior which 
isn't
# provided by this function.
@@ -990,9 +1003,133 @@ class depgraph(object):
if not conflicts:
return
 
-   # Get a set of all conflicting packages.
+   # Compute a mapping from parent packages to hard
+   # required conflict packages.
+   conflict_parents = collections.defaultdict(list)
+   for conflict in conflicts:
+   all_parent_atoms = set()
+   for pkg in conflict:
+   all_parent_atoms.update(
+