Skip to content

Commit f62a950

Browse files
reckless: accept a full local path as source+name
This allows installing a local plugin directly without having to modify reckless sources. Changelog-changed: Reckless can be passed a local file or directory for installation.
1 parent d8713ce commit f62a950

File tree

1 file changed

+72
-24
lines changed

1 file changed

+72
-24
lines changed

tools/reckless

+72-24
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,31 @@ def _install_plugin(src: InstInfo) -> Union[InstInfo, None]:
12981298
return staged_src
12991299

13001300

1301+
def location_from_name(plugin_name: str) -> (str, str):
1302+
"""Maybe the location was passed in place of the plugin name. Check
1303+
if this looks like a filepath or URL and return that as well as the
1304+
plugin name."""
1305+
if not Path(plugin_name).exists():
1306+
# No path included, return the name only.
1307+
return (None, plugin_name)
1308+
1309+
if os.path.isdir(plugin_name):
1310+
# Could be entrypoint or directory
1311+
return (Path(plugin_name).parent, Path(plugin_name).name)
1312+
1313+
elif os.path.isfile(plugin_name):
1314+
# Maybe the plugin entrypoint was passed?
1315+
if Path(plugin_name).with_suffix('').name != Path(plugin_name).parent.name or \
1316+
not Path(plugin_name).parent.parent.exists():
1317+
# The directory should be named for the plugin. If it's not, we
1318+
# can't infer what should be done.
1319+
# FIXME: return InstInfo with entrypoint rather than source str.
1320+
return (None, plugin_name)
1321+
# Asked for the entrypoint, but we're inferring how it should be
1322+
# named, i.e. the directory (named for the plugin, probably w/ matching entrypoint)
1323+
return (Path(plugin_name).parent.parent, Path(plugin_name).with_suffix('').name)
1324+
1325+
13011326
def install(plugin_name: str) -> Union[str, None]:
13021327
"""Downloads plugin from source repos, installs and activates plugin.
13031328
Returns the location of the installed plugin or "None" in the case of
@@ -1310,33 +1335,56 @@ def install(plugin_name: str) -> Union[str, None]:
13101335
else:
13111336
name = plugin_name
13121337
commit = None
1313-
log.debug(f"Searching for {name}")
1314-
if search(name):
1315-
global LAST_FOUND
1316-
src = LAST_FOUND
1317-
src.commit = commit
1318-
log.debug(f'Retrieving {src.name} from {src.source_loc}')
1319-
try:
1320-
installed = _install_plugin(src)
1321-
except FileExistsError as err:
1322-
log.error(f'File exists: {err.filename}')
1323-
return None
1324-
LAST_FOUND = None
1325-
if not installed:
1326-
log.warning(f'{plugin_name}: installation aborted')
1338+
# Is the install request specifying a path to the plugin?
1339+
direct_location, name = location_from_name(name)
1340+
if direct_location:
1341+
logging.debug(f"install of {name} requested from {direct_location}")
1342+
# We don't need to search here, but this populates install info and
1343+
# validates that it seems installable.
1344+
# src = _source_search(name, direct_location) # didn't work because it infers source type
1345+
src = InstInfo(name, direct_location, None)
1346+
src.srctype = Source.DIRECTORY
1347+
if src.get_inst_details():
1348+
log.debug(f"{src}, {src.srctype}")
1349+
else:
1350+
log.debug(f"could not get install details for {src}.")
1351+
src = None
1352+
# We can potentially treat a local directory as that, or as a local git
1353+
# repo. Treating it as simply a directory allows testing changes
1354+
# without commiting or pushing.
1355+
if src and src.srctype == Source.LOCAL_REPO:
1356+
src.srctype = Source.DIRECTORY
1357+
if not direct_location or not src:
1358+
log.debug(f"direct_location {direct_location}, src: {src}")
1359+
log.debug(f"Searching for {name}")
1360+
if search(name):
1361+
global LAST_FOUND
1362+
src = LAST_FOUND
1363+
src.commit = commit
1364+
log.debug(f'Retrieving {src.name} from {src.source_loc}')
1365+
else:
13271366
return None
13281367

1329-
# Match case of the containing directory
1330-
for dirname in os.listdir(RECKLESS_CONFIG.reckless_dir):
1331-
if dirname.lower() == installed.name.lower():
1332-
inst_path = Path(RECKLESS_CONFIG.reckless_dir)
1333-
inst_path = inst_path / dirname / installed.entry
1334-
RECKLESS_CONFIG.enable_plugin(inst_path)
1335-
enable(installed.name)
1336-
return f"{installed.source_loc}"
1337-
log.error(('dynamic activation failed: '
1338-
f'{installed.name} not found in reckless directory'))
1368+
try:
1369+
installed = _install_plugin(src)
1370+
except FileExistsError as err:
1371+
log.error(f'File exists: {err.filename}')
13391372
return None
1373+
LAST_FOUND = None
1374+
if not installed:
1375+
log.warning(f'{plugin_name}: installation aborted')
1376+
return None
1377+
1378+
# Match case of the containing directory
1379+
for dirname in os.listdir(RECKLESS_CONFIG.reckless_dir):
1380+
if dirname.lower() == installed.name.lower():
1381+
inst_path = Path(RECKLESS_CONFIG.reckless_dir)
1382+
inst_path = inst_path / dirname / installed.entry
1383+
RECKLESS_CONFIG.enable_plugin(inst_path)
1384+
enable(installed.name)
1385+
return f"{installed.source_loc}"
1386+
log.error(('dynamic activation failed: '
1387+
f'{installed.name} not found in reckless directory'))
13401388
return None
13411389

13421390

0 commit comments

Comments
 (0)