summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/spack/defaults/config.yaml7
-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
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)