feat(git proxy): start 默认写 git http(s).proxy,stop 自动恢复,restart 继承状态(CI 用 --no-set-git)
This commit is contained in:
@@ -5,17 +5,18 @@
|
||||
```bash
|
||||
mytoolkit git proxy list
|
||||
mytoolkit git proxy status # 全部守护进程 + git config
|
||||
mytoolkit git proxy start fastgithub # 推荐:后台 + Parallels socat(默认不改 git config)
|
||||
mytoolkit git proxy stop # 停「当前」
|
||||
mytoolkit git proxy start fastgithub # 推荐:后台 + Parallels socat(默认设 git http(s).proxy)
|
||||
mytoolkit git proxy stop # 停「当前」,并恢复 start 前的 git proxy 旧值
|
||||
mytoolkit git proxy stop fastgithub
|
||||
mytoolkit git proxy restart # 重启「当前」
|
||||
mytoolkit git proxy restart # 重启「当前」,git 行为继承重启前的状态
|
||||
mytoolkit git proxy start --no-set-git fastgithub # 仅拉 daemon,不动全局 git config(CI 主机)
|
||||
mytoolkit git proxy set fastgithub # 仅写 git http(s).proxy
|
||||
mytoolkit git proxy unset
|
||||
mytoolkit git proxy run fastgithub # 旧前台模式(设 git + Ctrl-C 清理);CI 主机请用 start
|
||||
mytoolkit git proxy run fastgithub # 旧前台模式(设 git + Ctrl-C 清理)
|
||||
```
|
||||
|
||||
- `start` / `stop` / `restart`:端口 + PID(`lsof`),状态文件 `~/.mytoolkit/run/proxy-current.json`
|
||||
- CI:主机 `start fastgithub`;job 用 `HEYUE_CI_GIT_PROXY=1` / `XIAOHE_CI_GIT_PROXY=1`(勿依赖全局 git proxy)
|
||||
- `start` / `stop` / `restart`:端口 + PID(`lsof`),状态文件 `~/.mytoolkit/run/proxy-current.json`;`start` 默认写全局 git http(s).proxy,`stop` 按状态文件自动恢复旧值(`--set-git/--no-set-git` 可显式切换)
|
||||
- CI:主机 `start --no-set-git fastgithub`(daemon only,勿动全局 git config);job 用 `HEYUE_CI_GIT_PROXY=1` / `XIAOHE_CI_GIT_PROXY=1`(勿依赖全局 git proxy)
|
||||
- Parallels guest 需 `brew install socat`;可选 `XIAOHE_CI_PARALLELS_HOST_IP`
|
||||
|
||||
## 新机器安装 FastGitHub
|
||||
|
||||
+42
-11
@@ -99,6 +99,19 @@ def _proxy_loopback_port(proxy_url: str) -> int | None:
|
||||
return 443 if parsed.scheme == "https" else 80
|
||||
|
||||
|
||||
def _restore_baseline(proxy: str, port: int | None) -> str:
|
||||
"""Git proxy value to record for restore-after-stop.
|
||||
|
||||
A value already pointing at the daemon's loopback port (set manually or
|
||||
by a prior `set`/`run`) is really "no proxy" once the daemon stops —
|
||||
restoring it would dangle at a dead port. Foreign / non-loopback values
|
||||
pass through unchanged.
|
||||
"""
|
||||
if port is not None and _proxy_loopback_port(proxy) == port:
|
||||
return "(not set)"
|
||||
return proxy
|
||||
|
||||
|
||||
def _parallels_host_ips() -> list[str]:
|
||||
"""Mac IPs that Parallels guests use to reach this host (auto from ifconfig)."""
|
||||
if sys.platform != "darwin":
|
||||
@@ -354,7 +367,8 @@ def _clear_state() -> None:
|
||||
def _restore_stale_git_proxy() -> bool:
|
||||
"""Restore git proxy if it points at a dead loopback port.
|
||||
|
||||
A session that ran `start --set-git` / `run` and exited without `stop`
|
||||
A session that ran `start` (git-proxy on by default) / `run` and exited
|
||||
without `stop`
|
||||
leaves the global git proxy pointing at the daemon port; if the daemon then
|
||||
died, every git call fails behind a dead proxy. Restore the pre-proxy value
|
||||
recorded in the state file (or unset). Returns True if anything changed.
|
||||
@@ -477,6 +491,11 @@ def _start_daemon(name: str, *, set_git: bool) -> None:
|
||||
|
||||
old_http = _get_git_proxy("http.proxy")
|
||||
old_https = _get_git_proxy("https.proxy")
|
||||
# A git proxy already pointing at this daemon's loopback port (a prior
|
||||
# manual `set` or stale state) counts as "no proxy" for restore purposes —
|
||||
# restoring the daemon URL after stop would leave a dangling pointer.
|
||||
old_http = _restore_baseline(old_http, port)
|
||||
old_https = _restore_baseline(old_https, port)
|
||||
proxy_pid: int | None = None
|
||||
forward_pids: list[int] = []
|
||||
|
||||
@@ -682,15 +701,16 @@ def proxy_unset() -> None:
|
||||
@proxy_cmd.command("start")
|
||||
@click.argument("name", shell_complete=_complete_proxy_names)
|
||||
@click.option(
|
||||
"--set-git",
|
||||
is_flag=True,
|
||||
help="Also set global git http(s).proxy (default: process only)",
|
||||
"--set-git/--no-set-git",
|
||||
default=True,
|
||||
help="Set global git http(s).proxy (default). --no-set-git = daemon only.",
|
||||
)
|
||||
def proxy_start(name: str, set_git: bool) -> None:
|
||||
"""Start a proxy daemon in the background (loopback + Parallels socat).
|
||||
|
||||
Does not change global git config unless --set-git is passed.
|
||||
CI should keep using per-job GIT_CONFIG_PARAMETERS instead.
|
||||
By default also sets global git http(s).proxy; ``stop`` restores the
|
||||
previous value. CI hosts wanting daemon-only should pass ``--no-set-git``
|
||||
and keep using per-job GIT_CONFIG_PARAMETERS.
|
||||
"""
|
||||
_start_daemon(name, set_git=set_git)
|
||||
|
||||
@@ -705,12 +725,17 @@ def proxy_stop(name: str | None) -> None:
|
||||
@proxy_cmd.command("restart")
|
||||
@click.argument("name", required=False, shell_complete=_complete_proxy_names)
|
||||
@click.option(
|
||||
"--set-git",
|
||||
is_flag=True,
|
||||
help="Also set global git http(s).proxy after restart",
|
||||
"--set-git/--no-set-git",
|
||||
default=None,
|
||||
help="Set global git http(s).proxy (default: inherit previous state). "
|
||||
"--no-set-git = daemon only.",
|
||||
)
|
||||
def proxy_restart(name: str | None, set_git: bool) -> None:
|
||||
"""Restart a proxy daemon. Omit NAME to restart the current one."""
|
||||
def proxy_restart(name: str | None, set_git: bool | None) -> None:
|
||||
"""Restart a proxy daemon. Omit NAME to restart the current one.
|
||||
|
||||
Git-proxy behavior defaults to inheriting the state of the daemon being
|
||||
restarted; ``--no-set-git`` forces daemon-only.
|
||||
"""
|
||||
if name is None:
|
||||
name = _current_daemon_name()
|
||||
if name is None:
|
||||
@@ -722,6 +747,12 @@ def proxy_restart(name: str | None, set_git: bool) -> None:
|
||||
)
|
||||
sys.exit(1)
|
||||
click.echo(f"Restarting current: {name}")
|
||||
if set_git is None:
|
||||
state = _read_state()
|
||||
if state and state.get("name") == name and "set_git" in state:
|
||||
set_git = bool(state["set_git"])
|
||||
else:
|
||||
set_git = True
|
||||
_stop_daemon(name)
|
||||
_start_daemon(name, set_git=set_git)
|
||||
|
||||
|
||||
+13
-1
@@ -1,6 +1,6 @@
|
||||
"""Unit tests for git proxy helpers."""
|
||||
|
||||
from mytoolkit.commands.git import _proxy_loopback_port
|
||||
from mytoolkit.commands.git import _proxy_loopback_port, _restore_baseline
|
||||
|
||||
|
||||
def test_proxy_loopback_port_http():
|
||||
@@ -13,6 +13,18 @@ def test_proxy_loopback_port_rejects_remote():
|
||||
assert _proxy_loopback_port("socks5://127.0.0.1:1080") is None
|
||||
|
||||
|
||||
def test_restore_baseline_daemon_own_port_becomes_unset():
|
||||
# Git already pointing at the daemon's loopback port → treat as no proxy.
|
||||
assert _restore_baseline("http://127.0.0.1:38457", 38457) == "(not set)"
|
||||
assert _restore_baseline("http://localhost:38457", 38457) == "(not set)"
|
||||
|
||||
|
||||
def test_restore_baseline_foreign_values_pass_through():
|
||||
assert _restore_baseline("http://127.0.0.1:10080", 38457) == "http://127.0.0.1:10080"
|
||||
assert _restore_baseline("(not set)", 38457) == "(not set)"
|
||||
assert _restore_baseline("http://127.0.0.1:38457", None) == "http://127.0.0.1:38457"
|
||||
|
||||
|
||||
def test_procs_matching_filters_by_command():
|
||||
from mytoolkit.commands.git import _procs_matching
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user