fix(git): start FastGitHub before Parallels socat forwards.

Binding socat first occupied :38457 and made FastGitHub fail to listen.
This commit is contained in:
Zhengshou Lai
2026-08-11 10:32:47 +08:00
parent 5b0739a397
commit 755157ab6c
+68 -29
View File
@@ -256,8 +256,9 @@ def proxy_run(name: str, command: tuple[str, ...]) -> None:
If no COMMAND is given, tries to run a program with the same name as the proxy.
If that program is not found, sets the proxy and waits for Ctrl-C.
For loopback proxies (e.g. fastgithub on 127.0.0.1), also opens socat
forwards on auto-detected Parallels host IPs so Windows/Linux VMs can connect.
For loopback proxies (e.g. fastgithub on 127.0.0.1), start the proxy
process first, then socat-forward auto-detected Parallels host IPs so
Windows/Linux VMs can connect. Socat must not bind before the proxy.
"""
proxies = _get_proxies()
if name not in proxies:
@@ -265,7 +266,6 @@ def proxy_run(name: str, command: tuple[str, ...]) -> None:
click.echo(f"Available: {', '.join(proxies.keys())}", err=True)
sys.exit(1)
# Save current state
old_http = _get_git_proxy("http.proxy")
old_https = _get_git_proxy("https.proxy")
@@ -280,20 +280,21 @@ def proxy_run(name: str, command: tuple[str, ...]) -> None:
forward_procs: list[subprocess.Popen] = []
port = _proxy_loopback_port(proxy_url)
if port is not None:
forward_procs = _start_parallels_forwards(port)
proxy_proc: subprocess.Popen | None = None
# Determine what to run
already_up = port is not None and _port_listening_on("127.0.0.1", port)
cmd_to_run = list(command) if command else None
if cmd_to_run is None:
if already_up:
click.secho(f"{name} already listening on :{port}", fg="cyan")
elif shutil.which(name):
if cmd_to_run is None and shutil.which(name):
cmd_to_run = [name]
def cleanup():
def cleanup() -> None:
_stop_procs(forward_procs)
if proxy_proc is not None and proxy_proc.poll() is None:
proxy_proc.send_signal(signal.SIGINT)
try:
proxy_proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proxy_proc.terminate()
proxy_proc.wait()
if old_http == "(not set)":
_unset_git_proxy("http.proxy")
else:
@@ -312,27 +313,65 @@ def proxy_run(name: str, command: tuple[str, ...]) -> None:
)
click.secho("Git proxy restored", fg="green")
try:
# Loopback proxy (fastgithub): ensure 127.0.0.1:port is up BEFORE socat.
if port is not None:
if _port_listening_on("127.0.0.1", port):
click.secho(
f"{name} already listening on 127.0.0.1:{port}", fg="cyan"
)
elif cmd_to_run:
click.secho(f"Running: {' '.join(cmd_to_run)}", fg="cyan")
proxy_proc = subprocess.Popen(cmd_to_run)
ready = False
for _ in range(60):
if _port_listening_on("127.0.0.1", port):
ready = True
break
if proxy_proc.poll() is not None:
break
time.sleep(0.25)
if not ready:
click.secho(
f"ERROR: {name} failed to listen on 127.0.0.1:{port}",
fg="red",
err=True,
)
sys.exit(1)
else:
click.secho(
f"ERROR: nothing on 127.0.0.1:{port} and `{name}` not found",
fg="red",
err=True,
)
sys.exit(1)
forward_procs = _start_parallels_forwards(port)
click.secho(
"Press Ctrl-C to stop and auto-unset proxy\n", fg="cyan"
)
try:
if proxy_proc is not None:
proxy_proc.wait()
else:
signal.pause()
except KeyboardInterrupt:
pass
sys.exit(proxy_proc.returncode if proxy_proc is not None else 0)
# Non-loopback proxy: original behavior.
if cmd_to_run:
click.secho(f"Running: {' '.join(cmd_to_run)}", fg="cyan")
click.secho("Press Ctrl-C to stop and auto-unset proxy\n", fg="cyan")
proc = None
click.secho(
"Press Ctrl-C to stop and auto-unset proxy\n", fg="cyan"
)
try:
proc = subprocess.Popen(cmd_to_run)
proc.wait()
proxy_proc = subprocess.Popen(cmd_to_run)
proxy_proc.wait()
except KeyboardInterrupt:
if proc is not None:
proc.send_signal(signal.SIGINT)
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.terminate()
proc.wait()
finally:
cleanup()
if proc is not None:
sys.exit(proc.returncode)
sys.exit(0)
else:
pass
sys.exit(proxy_proc.returncode if proxy_proc is not None else 0)
click.secho(
"Proxy active. Press Ctrl-C to stop and auto-unset proxy", fg="cyan"
)