summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/config_yaml.rst13
-rw-r--r--lib/spack/llnl/util/tty/log.py2
-rw-r--r--lib/spack/spack/installer.py29
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)