mirror of
https://github.com/ElementsProject/lightning.git
synced 2026-08-20 13:27:36 +02:00
Fix Reckless search command not finding partial matches
The Reckless search command was only returning a result if you searched a perfect match, which is not too helpful. This updates the command so that partial search matches return a result. Before: reckless search bolt Search exhausted all sources reckless search bol Search exhausted all sources reckless search bolt12-pris Search exhausted all sources After: reckless search bolt Plugins matching 'bolt': bolt12-prism (https://github.com/lightningd/plugins) reckless search bol Plugins matching 'bol': bolt12-prism (https://github.com/lightningd/plugins) reckless search bolt12-pris Plugins matching 'bolt12-pris': bolt12-prism (https://github.com/lightningd/plugins) Changelog-Fixed: reckless search now returns partial matches instead of requiring exact plugin names.
This commit is contained in:
parent
ff34e485bc
commit
0173610527
2 changed files with 81 additions and 9 deletions
|
|
@ -224,6 +224,32 @@ def test_search(node_factory):
|
|||
assert r.search_stdout('found testplugpass in source: https://github.com/lightningd/plugins')
|
||||
|
||||
|
||||
def test_search_partial_match(node_factory):
|
||||
"""test that partial/substring search returns multiple matches"""
|
||||
n = get_reckless_node(node_factory)
|
||||
|
||||
# Search for partial name "testplug" - should find all test plugins
|
||||
r = reckless([f"--network={NETWORK}", "search", "testplug"], dir=n.lightning_dir)
|
||||
# Should show the "Plugins matching" header
|
||||
assert r.search_stdout("Plugins matching 'testplug':")
|
||||
# Should list multiple plugins (all start with "testplug")
|
||||
assert r.search_stdout('testplugpass')
|
||||
assert r.search_stdout('testplugfail')
|
||||
assert r.search_stdout('testplugpyproj')
|
||||
assert r.search_stdout('testpluguv')
|
||||
|
||||
# Search for "pass" - should find testplugpass
|
||||
r = reckless([f"--network={NETWORK}", "search", "pass"], dir=n.lightning_dir)
|
||||
assert r.search_stdout("Plugins matching 'pass':")
|
||||
assert r.search_stdout('testplugpass')
|
||||
# Should not find plugins without "pass" in name
|
||||
assert not r.search_stdout('testplugfail')
|
||||
|
||||
# Search for something that doesn't exist
|
||||
r = reckless([f"--network={NETWORK}", "search", "nonexistent"], dir=n.lightning_dir)
|
||||
assert r.search_stdout("Search exhausted all sources")
|
||||
|
||||
|
||||
def test_install(node_factory):
|
||||
"""test search, git clone, and installation to folder."""
|
||||
n = get_reckless_node(node_factory)
|
||||
|
|
|
|||
|
|
@ -1548,6 +1548,32 @@ def uninstall(plugin_name: str) -> str:
|
|||
return "uninstalled"
|
||||
|
||||
|
||||
def _get_all_plugins_from_source(src: str) -> list:
|
||||
"""Get all plugin directories from a source repository.
|
||||
Returns a list of (plugin_name, source_url) tuples."""
|
||||
plugins = []
|
||||
srctype = Source.get_type(src)
|
||||
if srctype == Source.UNKNOWN:
|
||||
return plugins
|
||||
|
||||
try:
|
||||
root = SourceDir(src, srctype=srctype)
|
||||
root.populate()
|
||||
except Exception as e:
|
||||
log.debug(f"Failed to populate source {src}: {e}")
|
||||
return plugins
|
||||
|
||||
plugins.append((root.name, src))
|
||||
|
||||
for item in root.contents:
|
||||
if isinstance(item, SourceDir):
|
||||
# Skip archive directories
|
||||
if 'archive' in item.name.lower():
|
||||
continue
|
||||
plugins.append((item.name, src))
|
||||
return plugins
|
||||
|
||||
|
||||
def search(plugin_name: str) -> Union[InstInfo, None]:
|
||||
"""searches plugin index for plugin"""
|
||||
ordered_sources = RECKLESS_SOURCES.copy()
|
||||
|
|
@ -1563,6 +1589,22 @@ def search(plugin_name: str) -> Union[InstInfo, None]:
|
|||
if Source.get_type(src) in [Source.DIRECTORY, Source.LOCAL_REPO]:
|
||||
ordered_sources.remove(src)
|
||||
ordered_sources.insert(0, src)
|
||||
|
||||
# First, collect all partial matches to display to user
|
||||
partial_matches = []
|
||||
for source in ordered_sources:
|
||||
for plugin_name_found, src_url in _get_all_plugins_from_source(source):
|
||||
if plugin_name.lower() in plugin_name_found.lower():
|
||||
partial_matches.append((plugin_name_found, src_url))
|
||||
|
||||
# Display all partial matches
|
||||
if partial_matches:
|
||||
log.info(f"Plugins matching '{plugin_name}':")
|
||||
for name, src_url in partial_matches:
|
||||
log.info(f" {name} ({src_url})")
|
||||
|
||||
# Now try exact match for installation purposes
|
||||
exact_match = None
|
||||
for source in ordered_sources:
|
||||
srctype = Source.get_type(source)
|
||||
if srctype == Source.UNKNOWN:
|
||||
|
|
@ -1573,17 +1615,21 @@ def search(plugin_name: str) -> Union[InstInfo, None]:
|
|||
found = _source_search(plugin_name, source)
|
||||
if found:
|
||||
log.debug(f"{found}, {found.srctype}")
|
||||
if not found:
|
||||
continue
|
||||
log.info(f"found {found.name} in source: {found.source_loc}")
|
||||
log.debug(f"entry: {found.entry}")
|
||||
if found.subdir:
|
||||
log.debug(f'sub-directory: {found.subdir}')
|
||||
exact_match = found
|
||||
break
|
||||
|
||||
if exact_match:
|
||||
log.info(f"found {exact_match.name} in source: {exact_match.source_loc}")
|
||||
log.debug(f"entry: {exact_match.entry}")
|
||||
if exact_match.subdir:
|
||||
log.debug(f'sub-directory: {exact_match.subdir}')
|
||||
global LAST_FOUND
|
||||
# Stashing the search result saves install() a call to _source_search.
|
||||
LAST_FOUND = found
|
||||
return str(found.source_loc)
|
||||
log.info("Search exhausted all sources")
|
||||
LAST_FOUND = exact_match
|
||||
return str(exact_match.source_loc)
|
||||
|
||||
if not partial_matches:
|
||||
log.info("Search exhausted all sources")
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue