diff options
author | Michael Kuhn <michael.kuhn@ovgu.de> | 2021-10-11 17:54:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-11 17:54:59 +0200 |
commit | d1f327960793ffdf5d83538ed636da0181f906a2 (patch) | |
tree | 15fe8fbca478b65ecdd37e3e5fc42e98add57fb5 /lib | |
parent | 8f62039d45ec6545d0a226611bdf8998665844d8 (diff) | |
download | spack-d1f327960793ffdf5d83538ed636da0181f906a2.tar.gz spack-d1f327960793ffdf5d83538ed636da0181f906a2.tar.bz2 spack-d1f327960793ffdf5d83538ed636da0181f906a2.tar.xz spack-d1f327960793ffdf5d83538ed636da0181f906a2.zip |
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/docs/config_yaml.rst | 13 | ||||
-rw-r--r-- | lib/spack/llnl/util/tty/log.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/installer.py | 29 |
3 files changed, 43 insertions, 1 deletions
diff --git a/lib/spack/docs/config_yaml.rst b/lib/spack/docs/config_yaml.rst index 631b8f6b1b..8173e8a0a9 100644 --- a/lib/spack/docs/config_yaml.rst +++ b/lib/spack/docs/config_yaml.rst @@ -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. diff --git a/lib/spack/llnl/util/tty/log.py b/lib/spack/llnl/util/tty/log.py index bc79b32335..7003f58f8d 100644 --- a/lib/spack/llnl/util/tty/log.py +++ b/lib/spack/llnl/util/tty/log.py @@ -33,7 +33,7 @@ except ImportError: # 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 # diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 11430bfc94..d7a6ca0a67 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -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 @@ class PackageInstaller(object): 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 @@ class PackageInstaller(object): 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 @@ class PackageInstaller(object): # 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 @@ class PackageInstaller(object): 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 @@ class PackageInstaller(object): # 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) |