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 | |
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.
-rw-r--r-- | etc/spack/defaults/config.yaml | 7 | ||||
-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 |
4 files changed, 49 insertions, 2 deletions
diff --git a/etc/spack/defaults/config.yaml b/etc/spack/defaults/config.yaml index 88a19d3222..3487d33162 100644 --- a/etc/spack/defaults/config.yaml +++ b/etc/spack/defaults/config.yaml @@ -134,7 +134,7 @@ config: # enabling locks. locks: true - # The default url fetch method to use. + # The default url fetch method to use. # If set to 'curl', Spack will require curl on the user's system # If set to 'urllib', Spack will use python built-in libs to fetch url_fetch_method: urllib @@ -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 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) |