Print 'Waiting for another process to install x, y, z' in distributed builds (#28535)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
parent
5300cbbb2e
commit
e3d62b2f7b
@ -648,6 +648,49 @@ def set(self, text):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
class TermStatusLine(object):
|
||||||
|
"""
|
||||||
|
This class is used in distributed builds to inform the user that other packages are
|
||||||
|
being installed by another process.
|
||||||
|
"""
|
||||||
|
def __init__(self, enabled):
|
||||||
|
self.enabled = enabled
|
||||||
|
self.pkg_set = set()
|
||||||
|
self.pkg_list = []
|
||||||
|
|
||||||
|
def add(self, pkg_id):
|
||||||
|
"""
|
||||||
|
Add a package to the waiting list, and if it is new, update the status line.
|
||||||
|
"""
|
||||||
|
if not self.enabled or pkg_id in self.pkg_set:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.pkg_set.add(pkg_id)
|
||||||
|
self.pkg_list.append(pkg_id)
|
||||||
|
tty.msg(colorize('@*{Waiting for} @*g{%s}' % pkg_id))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
"""
|
||||||
|
Clear the status line.
|
||||||
|
"""
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
lines = len(self.pkg_list)
|
||||||
|
|
||||||
|
if lines == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.pkg_set.clear()
|
||||||
|
self.pkg_list.clear()
|
||||||
|
|
||||||
|
# Move the cursor to the beginning of the first "Waiting for" message and clear
|
||||||
|
# everything after it.
|
||||||
|
sys.stdout.write('\x1b[%sF\x1b[J' % lines)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
class PackageInstaller(object):
|
class PackageInstaller(object):
|
||||||
'''
|
'''
|
||||||
Class for managing the install process for a Spack instance based on a
|
Class for managing the install process for a Spack instance based on a
|
||||||
@ -1500,6 +1543,10 @@ def install(self):
|
|||||||
|
|
||||||
term_title = TermTitle(len(self.build_pq))
|
term_title = TermTitle(len(self.build_pq))
|
||||||
|
|
||||||
|
# Only enable the terminal status line when we're in a tty without debug info
|
||||||
|
# enabled, so that the output does not get cluttered.
|
||||||
|
term_status = TermStatusLine(enabled=sys.stdout.isatty() and not tty.is_debug())
|
||||||
|
|
||||||
while self.build_pq:
|
while self.build_pq:
|
||||||
term_title.next_pkg()
|
term_title.next_pkg()
|
||||||
|
|
||||||
@ -1523,6 +1570,7 @@ def install(self):
|
|||||||
# all subsequent tasks will have non-zero priorities or may be
|
# all subsequent tasks will have non-zero priorities or may be
|
||||||
# dependencies of this task.
|
# dependencies of this task.
|
||||||
if task.priority != 0:
|
if task.priority != 0:
|
||||||
|
term_status.clear()
|
||||||
tty.error('Detected uninstalled dependencies for {0}: {1}'
|
tty.error('Detected uninstalled dependencies for {0}: {1}'
|
||||||
.format(pkg_id, task.uninstalled_deps))
|
.format(pkg_id, task.uninstalled_deps))
|
||||||
left = [dep_id for dep_id in task.uninstalled_deps if
|
left = [dep_id for dep_id in task.uninstalled_deps if
|
||||||
@ -1545,12 +1593,14 @@ def install(self):
|
|||||||
# some package likely depends on it.
|
# some package likely depends on it.
|
||||||
if not task.explicit:
|
if not task.explicit:
|
||||||
if _handle_external_and_upstream(pkg, False):
|
if _handle_external_and_upstream(pkg, False):
|
||||||
|
term_status.clear()
|
||||||
self._flag_installed(pkg, task.dependents)
|
self._flag_installed(pkg, task.dependents)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Flag a failed spec. Do not need an (install) prefix lock since
|
# Flag a failed spec. Do not need an (install) prefix lock since
|
||||||
# assume using a separate (failed) prefix lock file.
|
# assume using a separate (failed) prefix lock file.
|
||||||
if pkg_id in self.failed or spack.store.db.prefix_failed(spec):
|
if pkg_id in self.failed or spack.store.db.prefix_failed(spec):
|
||||||
|
term_status.clear()
|
||||||
tty.warn('{0} failed to install'.format(pkg_id))
|
tty.warn('{0} failed to install'.format(pkg_id))
|
||||||
self._update_failed(task)
|
self._update_failed(task)
|
||||||
|
|
||||||
@ -1569,6 +1619,7 @@ def install(self):
|
|||||||
# determined the spec has already been installed (though the
|
# determined the spec has already been installed (though the
|
||||||
# other process may be hung).
|
# other process may be hung).
|
||||||
term_title.set('Acquiring lock for {0}'.format(pkg.name))
|
term_title.set('Acquiring lock for {0}'.format(pkg.name))
|
||||||
|
term_status.add(pkg_id)
|
||||||
ltype, lock = self._ensure_locked('write', pkg)
|
ltype, lock = self._ensure_locked('write', pkg)
|
||||||
if lock is None:
|
if lock is None:
|
||||||
# Attempt to get a read lock instead. If this fails then
|
# Attempt to get a read lock instead. If this fails then
|
||||||
@ -1583,6 +1634,8 @@ def install(self):
|
|||||||
self._requeue_task(task)
|
self._requeue_task(task)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
term_status.clear()
|
||||||
|
|
||||||
# Take a timestamp with the overwrite argument to allow checking
|
# Take a timestamp with the overwrite argument to allow checking
|
||||||
# whether another process has already overridden the package.
|
# whether another process has already overridden the package.
|
||||||
if task.request.overwrite and task.explicit:
|
if task.request.overwrite and task.explicit:
|
||||||
|
Loading…
Reference in New Issue
Block a user