installer: Support showing status information in terminal title (#16259)
Installing packages with a lot of dependencies does not have an easy way of judging the current progress (apart from running `spack spec -I pkg` in another terminal). This change allows Spack to update the terminal's title with status information, including its current progress as well as information about the current and total number of packages.
This commit is contained in:
parent
8f62039d45
commit
d1f3279607
@ -190,3 +190,8 @@ config:
|
||||
# Set to 'false' to allow installation on filesystems that doesn't allow setgid bit
|
||||
# manipulation by unprivileged user (e.g. AFS)
|
||||
allow_sgid: true
|
||||
|
||||
# Whether to set the terminal title to display status information during
|
||||
# building and installing packages. This gives information about Spack's
|
||||
# current progress as well as the current and total number of packages.
|
||||
terminal_title: false
|
||||
|
@ -259,3 +259,16 @@ and ld.so will ONLY search for dependencies in the ``RUNPATH`` of
|
||||
the loading object.
|
||||
|
||||
DO NOT MIX the two options within the same install tree.
|
||||
|
||||
----------------------
|
||||
``terminal_title``
|
||||
----------------------
|
||||
|
||||
By setting this option to ``true``, Spack will update the terminal's title to
|
||||
provide information about its current progress as well as the current and
|
||||
total package numbers.
|
||||
|
||||
To work properly, this requires your terminal to reset its title after
|
||||
Spack has finished its work, otherwise Spack's status information will
|
||||
remain in the terminal's title indefinitely. Most terminals should already
|
||||
be set up this way and clear Spack's status information.
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
# Use this to strip escape sequences
|
||||
_escape = re.compile(r'\x1b[^m]*m|\x1b\[?1034h')
|
||||
_escape = re.compile(r'\x1b[^m]*m|\x1b\[?1034h|\x1b\][0-9]+;[^\x07]*\x07')
|
||||
|
||||
# control characters for enabling/disabling echo
|
||||
#
|
||||
|
@ -627,6 +627,27 @@ def package_id(pkg):
|
||||
return "{0}-{1}-{2}".format(pkg.name, pkg.version, pkg.spec.dag_hash())
|
||||
|
||||
|
||||
class TermTitle(object):
|
||||
def __init__(self, pkg_count):
|
||||
# Counters used for showing status information in the terminal title
|
||||
self.pkg_num = 0
|
||||
self.pkg_count = pkg_count
|
||||
|
||||
def next_pkg(self):
|
||||
self.pkg_num += 1
|
||||
|
||||
def set(self, text):
|
||||
if not spack.config.get('config:terminal_title', False):
|
||||
return
|
||||
|
||||
if not sys.stdout.isatty():
|
||||
return
|
||||
|
||||
status = '{0} [{1}/{2}]'.format(text, self.pkg_num, self.pkg_count)
|
||||
sys.stdout.write('\033]0;Spack: {0}\007'.format(status))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
class PackageInstaller(object):
|
||||
'''
|
||||
Class for managing the install process for a Spack instance based on a
|
||||
@ -1476,7 +1497,11 @@ def install(self):
|
||||
failed_explicits = []
|
||||
exists_errors = []
|
||||
|
||||
term_title = TermTitle(len(self.build_pq))
|
||||
|
||||
while self.build_pq:
|
||||
term_title.next_pkg()
|
||||
|
||||
task = self._pop_task()
|
||||
if task is None:
|
||||
continue
|
||||
@ -1486,6 +1511,7 @@ def install(self):
|
||||
keep_prefix = install_args.get('keep_prefix')
|
||||
|
||||
pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec
|
||||
term_title.set('Processing {0}'.format(pkg.name))
|
||||
tty.verbose('Processing {0}: task={1}'.format(pkg_id, task))
|
||||
# Ensure that the current spec has NO uninstalled dependencies,
|
||||
# which is assumed to be reflected directly in its priority.
|
||||
@ -1541,6 +1567,7 @@ def install(self):
|
||||
# another process is likely (un)installing the spec or has
|
||||
# determined the spec has already been installed (though the
|
||||
# other process may be hung).
|
||||
term_title.set('Acquiring lock for {0}'.format(pkg.name))
|
||||
ltype, lock = self._ensure_locked('write', pkg)
|
||||
if lock is None:
|
||||
# Attempt to get a read lock instead. If this fails then
|
||||
@ -1561,6 +1588,7 @@ def install(self):
|
||||
task.request.overwrite_time = time.time()
|
||||
|
||||
# Determine state of installation artifacts and adjust accordingly.
|
||||
term_title.set('Preparing {0}'.format(pkg.name))
|
||||
self._prepare_for_install(task)
|
||||
|
||||
# Flag an already installed package
|
||||
@ -1605,6 +1633,7 @@ def install(self):
|
||||
|
||||
# Proceed with the installation since we have an exclusive write
|
||||
# lock on the package.
|
||||
term_title.set('Installing {0}'.format(pkg.name))
|
||||
try:
|
||||
action = self._install_action(task)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user