diff --git a/backend/api/server.py b/backend/api/server.py index 390a1e4..af253c1 100644 --- a/backend/api/server.py +++ b/backend/api/server.py @@ -787,14 +787,30 @@ class AgentState: repo = config.cwd if not (repo / '.git').exists(): raise ValueError(f'当前工作目录不是 git 仓库:{repo}') + git_prefix: list[str] = [] + if os.name == 'posix' and hasattr(os, 'geteuid') and os.geteuid() == 0: + try: + repo_owner = pwd.getpwuid(repo.stat().st_uid).pw_name + except (KeyError, OSError): + repo_owner = '' + if repo_owner and repo_owner != 'root': + git_prefix = [ + 'sudo', + '-H', + '-u', + repo_owner, + 'env', + 'GIT_TERMINAL_PROMPT=0', + ] def run_git(args: list[str], *, timeout: int = 60) -> subprocess.CompletedProcess[str]: env = { **os.environ, 'GIT_TERMINAL_PROMPT': '0', } + command = [*git_prefix, 'git', *args] if git_prefix else ['git', *args] proc = subprocess.run( - ['git', *args], + command, cwd=repo, capture_output=True, text=True, @@ -803,7 +819,8 @@ class AgentState: ) if proc.returncode != 0: detail = (proc.stderr or proc.stdout or '').strip() - raise ValueError(f'git {" ".join(args)} 失败:{detail}') + run_as = f'(以 {git_prefix[3]} 用户执行)' if git_prefix else '' + raise ValueError(f'git {" ".join(args)}{run_as} 失败:{detail}') return proc dirty = run_git(['status', '--porcelain', '--untracked-files=no']).stdout.strip()