diff options
-rw-r--r-- | pym/_emerge/__init__.py | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index fb04b304f..772a2df3f 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -9770,6 +9770,17 @@ class Scheduler(PollScheduler): for k in self._task_queues.allowed_keys: setattr(self._task_queues, k, SequentialTaskQueue()) + + # Holds merges that will wait to be executed when no builds are + # executing. This is useful for system packages since dependencies + # on system packages are frequently unspecified. + self._merge_wait_queue = [] + # Holds merges that have been transfered from the merge_wait_queue to + # the actual merge queue. They are removed from this list upon + # completion. Other packages can start building only when this list is + # empty. + self._merge_wait_scheduled = [] + self._status_display = JobStatusDisplay() self._max_load = myopts.get("--load-average") max_jobs = myopts.get("--jobs") @@ -10496,6 +10507,10 @@ class Scheduler(PollScheduler): elif isinstance(pkg, Blocker): pass + def _merge_wait_exit_handler(self, task): + self._merge_wait_scheduled.remove(task) + self._merge_exit(task) + def _merge_exit(self, merge): self._do_merge_exit(merge) self._deallocate_config(merge.merge.settings) @@ -10548,9 +10563,15 @@ class Scheduler(PollScheduler): if build.returncode == os.EX_OK: self.curval += 1 merge = PackageMerge(merge=build) - merge.addExitListener(self._merge_exit) - self._task_queues.merge.add(merge) - self._status_display.merges = len(self._task_queues.merge) + system_set = build.pkg.root_config.sets["system"] + if system_set.findAtomForPackage(build.pkg): + # Since dependencies on system packages are frequently + # unspecified, merge them only when no builds are executing. + self._merge_wait_queue.append(merge) + else: + merge.addExitListener(self._merge_exit) + self._task_queues.merge.add(merge) + self._status_display.merges = len(self._task_queues.merge) else: settings = build.settings build_dir = settings.get("PORTAGE_BUILDDIR") @@ -10728,6 +10749,16 @@ class Scheduler(PollScheduler): not (self._failed_pkgs and not self._build_opts.fetchonly)) def _schedule_tasks(self): + + # When the number of jobs drops to zero, process all waiting merges. + if not self._jobs and self._merge_wait_queue: + for task in self._merge_wait_queue: + task.addExitListener(self._merge_wait_exit_handler) + self._task_queues.merge.add(task) + self._status_display.merges = len(self._task_queues.merge) + self._merge_wait_scheduled.extend(self._merge_wait_queue) + del self._merge_wait_queue[:] + self._schedule_tasks_imp() self._status_display.display() @@ -10782,6 +10813,7 @@ class Scheduler(PollScheduler): return bool(state_change) if self._choose_pkg_return_early or \ + self._merge_wait_scheduled or \ not self._can_add_job() or \ self._job_delay(): return bool(state_change) |