From 9c0c076a005e0a2ba980de773eef1e0331aa6897 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Thu, 17 Sep 2020 09:07:00 +0100 Subject: [PATCH 1/5] Detect and run shell functions --- crab/cli.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/crab/cli.py b/crab/cli.py index a62d567..320c3b7 100644 --- a/crab/cli.py +++ b/crab/cli.py @@ -2,6 +2,7 @@ from crab import router, __version__ import shlex import socket +import subprocess import sys from dotenv import dotenv_values import shutil @@ -78,12 +79,20 @@ def main(command=None): port = env.setdefault("PORT", get_free_port()) command = [item.replace("$PORT", port) for item in command] - if shutil.which(command[0], path=env["PATH"]) is None: - print('Could not find "{}" in your procfile or $PATH.'.format(command[0])) - exit(1) + if shutil.which(command[0], path=env["PATH"]) is not None: + os.execvpe(command[0], command, env) - # off we go - os.execvpe(command[0], command, env) + # Is it a shell function? + if ( + subprocess.run( + ["declare", "-f", command[0]], shell=True, stdout=subprocess.DEVNULL + ).returncode + == 0 + ): + os.execvpe(env["SHELL"], [env["SHELL"], "-ci"] + command, env) + + print('Could not find "{}" in your procfile or $PATH.'.format(command[0])) + exit(1) if __name__ == "__main__": From a94a5c0a744dc4f8526c1fe59a94a53ae2296b74 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Thu, 17 Sep 2020 09:33:36 +0100 Subject: [PATCH 2/5] Bail from main function early on execvpe calls --- crab/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crab/cli.py b/crab/cli.py index 320c3b7..828289c 100644 --- a/crab/cli.py +++ b/crab/cli.py @@ -80,7 +80,7 @@ def main(command=None): command = [item.replace("$PORT", port) for item in command] if shutil.which(command[0], path=env["PATH"]) is not None: - os.execvpe(command[0], command, env) + return os.execvpe(command[0], command, env) # Is it a shell function? if ( @@ -89,7 +89,7 @@ def main(command=None): ).returncode == 0 ): - os.execvpe(env["SHELL"], [env["SHELL"], "-ci"] + command, env) + return os.execvpe(env["SHELL"], [env["SHELL"], "-ci"] + command, env) print('Could not find "{}" in your procfile or $PATH.'.format(command[0])) exit(1) From b96b0b3d280ea182078baf09357306f6ea9799e6 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Thu, 17 Sep 2020 09:33:59 +0100 Subject: [PATCH 3/5] Make router tests pass if crab processes are running on the machine --- tests/test_router.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_router.py b/tests/test_router.py index 2e4f149..4c2064a 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -11,5 +11,5 @@ def test_get_routes(self): env={**os.environ, "VIRTUAL_HOST": "test.localhost", "PORT": "1234"}, ) as subproc: routes = get_routes() - self.assertEqual(routes, {"test.localhost": "1234"}) + self.assertEqual(routes["test.localhost"], "1234") subproc.terminate() From 1a4a8ffddda5bb05e746a86f87777a6ebd81f012 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Wed, 4 Nov 2020 08:41:03 +0000 Subject: [PATCH 4/5] Check return code is not zero rather than a specific error code --- tests/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 48f3ff9..986c30b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -21,7 +21,7 @@ def test_missing_command(self): cmd = subprocess.run( ["crab", "this-command-shouldnt-exist"], stdout=subprocess.PIPE ) - self.assertEqual(cmd.returncode, 1) + self.assertNotEqual(cmd.returncode, 0) self.assertIn( 'Could not find "this-command-shouldnt-exist" in your procfile or $PATH.', cmd.stdout.decode(), From 4852b166ef5874d958e615d97358376b6cf393c4 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Wed, 4 Nov 2020 08:42:40 +0000 Subject: [PATCH 5/5] Change order of checks so functions override binaries --- crab/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crab/cli.py b/crab/cli.py index 828289c..01ab03a 100644 --- a/crab/cli.py +++ b/crab/cli.py @@ -79,9 +79,6 @@ def main(command=None): port = env.setdefault("PORT", get_free_port()) command = [item.replace("$PORT", port) for item in command] - if shutil.which(command[0], path=env["PATH"]) is not None: - return os.execvpe(command[0], command, env) - # Is it a shell function? if ( subprocess.run( @@ -91,6 +88,9 @@ def main(command=None): ): return os.execvpe(env["SHELL"], [env["SHELL"], "-ci"] + command, env) + if shutil.which(command[0], path=env["PATH"]) is not None: + return os.execvpe(command[0], command, env) + print('Could not find "{}" in your procfile or $PATH.'.format(command[0])) exit(1)