summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Kuhn <michael.kuhn@ovgu.de>2023-11-05 23:32:09 +0100
committerGitHub <noreply@github.com>2023-11-05 14:32:09 -0800
commit141c7de5d89f32b203438e1d6fca1efd817299f7 (patch)
tree2a3ffa8d750b1f16314a91efe46e9df17c0de7ec
parentf6b23b4653c73f60e826086154cad3040c1b61a7 (diff)
downloadspack-141c7de5d89f32b203438e1d6fca1efd817299f7.tar.gz
spack-141c7de5d89f32b203438e1d6fca1efd817299f7.tar.bz2
spack-141c7de5d89f32b203438e1d6fca1efd817299f7.tar.xz
spack-141c7de5d89f32b203438e1d6fca1efd817299f7.zip
Add command and package suggestions (#40895)
* Add command suggestions This adds suggestions of similar commands in case users mistype a command. Before: ``` $ spack spack ==> Error: spack is not a recognized Spack command or extension command; check with `spack commands`. ``` After: ``` $ spack spack ==> Error: spack is not a recognized Spack command or extension command; check with `spack commands`. Did you mean one of the following commands? spec patch ``` * Add package name suggestions * Remove suggestion to run spack clean -m
-rw-r--r--lib/spack/spack/cmd/dev_build.py5
-rw-r--r--lib/spack/spack/cmd/edit.py5
-rw-r--r--lib/spack/spack/extensions.py12
-rw-r--r--lib/spack/spack/repo.py14
-rw-r--r--lib/spack/spack/test/cmd/dev_build.py11
5 files changed, 35 insertions, 12 deletions
diff --git a/lib/spack/spack/cmd/dev_build.py b/lib/spack/spack/cmd/dev_build.py
index d8a7b447a2..90008c8b3e 100644
--- a/lib/spack/spack/cmd/dev_build.py
+++ b/lib/spack/spack/cmd/dev_build.py
@@ -99,10 +99,7 @@ def dev_build(self, args):
spec = specs[0]
if not spack.repo.PATH.exists(spec.name):
- tty.die(
- "No package for '{0}' was found.".format(spec.name),
- " Use `spack create` to create a new package",
- )
+ raise spack.repo.UnknownPackageError(spec.name)
if not spec.versions.concrete_range_as_version:
tty.die(
diff --git a/lib/spack/spack/cmd/edit.py b/lib/spack/spack/cmd/edit.py
index 15aeea31b3..79f441a67a 100644
--- a/lib/spack/spack/cmd/edit.py
+++ b/lib/spack/spack/cmd/edit.py
@@ -43,10 +43,7 @@ def edit_package(name, repo_path, namespace):
if not os.access(path, os.R_OK):
tty.die("Insufficient permissions on '%s'!" % path)
else:
- tty.die(
- "No package for '{0}' was found.".format(spec.name),
- " Use `spack create` to create a new package",
- )
+ raise spack.repo.UnknownPackageError(spec.name)
editor(path)
diff --git a/lib/spack/spack/extensions.py b/lib/spack/spack/extensions.py
index af900722cc..0ee01a22a1 100644
--- a/lib/spack/spack/extensions.py
+++ b/lib/spack/spack/extensions.py
@@ -5,6 +5,7 @@
"""Service functions and classes to implement the hooks
for Spack's command extensions.
"""
+import difflib
import importlib
import os
import re
@@ -176,10 +177,19 @@ class CommandNotFoundError(spack.error.SpackError):
"""
def __init__(self, cmd_name):
- super().__init__(
+ msg = (
"{0} is not a recognized Spack command or extension command;"
" check with `spack commands`.".format(cmd_name)
)
+ long_msg = None
+
+ similar = difflib.get_close_matches(cmd_name, spack.cmd.all_commands())
+
+ if 1 <= len(similar) <= 5:
+ long_msg = "\nDid you mean one of the following commands?\n "
+ long_msg += "\n ".join(similar)
+
+ super().__init__(msg, long_msg)
class ExtensionNamingError(spack.error.SpackError):
diff --git a/lib/spack/spack/repo.py b/lib/spack/spack/repo.py
index a89b5dd407..5918454005 100644
--- a/lib/spack/spack/repo.py
+++ b/lib/spack/spack/repo.py
@@ -6,6 +6,7 @@
import abc
import collections.abc
import contextlib
+import difflib
import errno
import functools
import importlib
@@ -1516,7 +1517,18 @@ class UnknownPackageError(UnknownEntityError):
long_msg = "Did you mean to specify a filename with './{0}'?"
long_msg = long_msg.format(name)
else:
- long_msg = "You may need to run 'spack clean -m'."
+ long_msg = "Use 'spack create' to create a new package."
+
+ if not repo:
+ repo = spack.repo.PATH
+
+ # We need to compare the base package name
+ pkg_name = name.rsplit(".", 1)[-1]
+ similar = difflib.get_close_matches(pkg_name, repo.all_package_names())
+
+ if 1 <= len(similar) <= 5:
+ long_msg += "\n\nDid you mean one of the following packages?\n "
+ long_msg += "\n ".join(similar)
super().__init__(msg, long_msg)
self.name = name
diff --git a/lib/spack/spack/test/cmd/dev_build.py b/lib/spack/spack/test/cmd/dev_build.py
index c5a7b5c3bb..85199eddd6 100644
--- a/lib/spack/spack/test/cmd/dev_build.py
+++ b/lib/spack/spack/test/cmd/dev_build.py
@@ -163,8 +163,15 @@ def test_dev_build_fails_multiple_specs(mock_packages):
def test_dev_build_fails_nonexistent_package_name(mock_packages):
- output = dev_build("no_such_package", fail_on_error=False)
- assert "No package for 'no_such_package' was found" in output
+ output = ""
+
+ try:
+ dev_build("no_such_package")
+ assert False, "no exception was raised!"
+ except spack.repo.UnknownPackageError as e:
+ output = e.message
+
+ assert "Package 'no_such_package' not found" in output
def test_dev_build_fails_no_version(mock_packages):