Internal/Git执行.ps1
|
# Git 命令执行相关的内部辅助函数 function 组成-Git参数 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) # 代理仅通过 -c 命令行参数注入本次进程(不写入任何 git 配置文件), # 因此不影响用户手动执行 git。 $完整参数 = @() if (-not [string]::IsNullOrWhiteSpace($代理)) { $完整参数 += @("-c", "http.proxy=$代理", "-c", "https.proxy=$代理") } $完整参数 += $参数 return $完整参数 } function 执行-Git命令 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) & git @(组成-Git参数 $参数 $代理) if ($LASTEXITCODE -ne 0) { throw "git $($参数 -join ' ') 执行失败。" } } function 尝试-Git命令 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) & git @(组成-Git参数 $参数 $代理) return $LASTEXITCODE -eq 0 } <# .SYNOPSIS 执行 git 命令,输出实时显示到控制台并同时收集,用于区分「用户取消」与普通失败。 .DESCRIPTION 返回对象包含 成功(退出码是否为 0)和 用户取消(输出中是否出现用户取消身份验证对话框的特征文本)。调用方在 用户取消 为真时应中止流程且不记录镜像成败。注意:输出经管道收集后 git 不再显示 \r 进度刷新(stderr 非终端时 git 自动省略进度),但 "fatal:" 等以换行结束的错误信息会逐行实时显示。 #> function Git执行并区分取消 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) $输出行 = [System.Collections.Generic.List[string]]::new() $原错误策略 = $ErrorActionPreference $ErrorActionPreference = "Continue" & git @(组成-Git参数 $参数 $代理) 2>&1 | ForEach-Object { $行 = "$_" $输出行.Add($行) if (-not [string]::IsNullOrWhiteSpace($行)) { Write-Host $行 } } $退出码 = $LASTEXITCODE $ErrorActionPreference = $原错误策略 # GCM 取消对话框会输出 "fatal: User cancelled dialog.",随后 git 报"fatal: Authentication failed for ..."。只把「用户取消对话框」这一确切特征视为取消,单独的 Authentication failed 可能来自镜像限流,仍按镜像失败处理。 $已取消 = $输出行 | Where-Object { $_ -match '(?i)user cancell' } return [pscustomobject]@{ 成功 = ($退出码 -eq 0) 用户取消 = [bool]$已取消 } } function 读取-Git文本 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) $输出 = & git @(组成-Git参数 $参数 $代理) if ($LASTEXITCODE -ne 0) { throw "git $($参数 -join ' ') 执行失败。" } return ($输出 -join "`n").Trim() } <# .SYNOPSIS 执行只读的 git 命令并返回输出,失败时返回空字符串而非抛错。 合并 stderr 并用 try/catch 兜底,确保在 EAP=Stop 下绝不影响调用者。 #> function 尝试读取-Git文本 { param( [Parameter(Mandatory = $true)] [string[]]$参数, [Parameter()] [AllowEmptyString()] [string]$代理 = "" ) try { $输出 = & git @(组成-Git参数 $参数 $代理) 2>&1 if ($LASTEXITCODE -ne 0) { return "" } return (($输出 | ForEach-Object { "$_" }) -join "`n").Trim() } catch { return "" } } |