Files
workspace/bash/git-renew-powershell.ps1
2026-03-15 13:14:04 +08:00

238 lines
7.5 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================
# Git 批量克隆/更新脚本 - PowerShell 版本
# 适用于 Windows PowerShell / PowerShell Core
# ============================================
# -------------------- 配置区 --------------------
# 父目录路径(存放所有仓库的目录)
$ParentDir = ".."
# Git 远程仓库用户名
$GitUsername = "e2hang"
# Git 远程仓库基础 URL
$GitBaseUrl = "https://huajishe.fun/git"
# 连接方式https 或 ssh
# https: https://huajishe.fun/git/e2hang/<repo>.git
# ssh: git@huajishe.fun:e2hang/<repo>.git
$ConnectionType = "https" # 可选: "https" 或 "ssh"
# SSH 主机(仅当 ConnectionType="ssh" 时使用)
$SshHost = "huajishe.fun"
# -------------------- 仓库列表模式选择 --------------------
# 模式 1: "folders" - 基于父目录下已有的文件夹
# 模式 2: "array" - 基于下面定义的 RepoList 数组
$ListMode = "folders" # 可选: "folders" 或 "array"
# 仓库列表(仅当 ListMode="array" 时使用)
$RepoList = @(
"project-one",
"project-two",
"my awesome project",
"another-repo"
)
# -------------------- 脚本主体 --------------------
# 检查父目录是否存在,不存在则创建
if (-not (Test-Path -Path $ParentDir)) {
Write-Host "警告: 父目录 '$ParentDir' 不存在,正在创建..." -ForegroundColor Yellow
try {
New-Item -Path $ParentDir -ItemType Directory -Force | Out-Null
}
catch {
Write-Host "错误: 无法创建父目录" -ForegroundColor Red
exit 1
}
}
# 转换为绝对路径
$ParentDir = (Resolve-Path -Path $ParentDir).Path
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Git 批量同步工具" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "目标目录: " -NoNewline
Write-Host $ParentDir -ForegroundColor Cyan
Write-Host "连接方式: " -NoNewline
Write-Host $ConnectionType -ForegroundColor Cyan
Write-Host "列表模式: " -NoNewline
Write-Host $ListMode -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# 统计变量
$total = 0
$cloned = 0
$updated = 0
$skipped = 0
$failed = 0
$uptodate = 0
# 构建远程仓库 URL
function Build-RemoteUrl {
param([string]$RepoName)
if ($ConnectionType -eq "ssh") {
return "git@${SshHost}:${GitUsername}/${RepoName}.git"
}
else {
return "${GitBaseUrl}/${GitUsername}/${RepoName}.git"
}
}
# 处理单个仓库
function Process-Repo {
param([string]$RepoName)
$script:total++
$repoPath = Join-Path -Path $ParentDir -ChildPath $RepoName
$remoteUrl = Build-RemoteUrl -RepoName $RepoName
Write-Host "[$script:total] 处理仓库: " -NoNewline -ForegroundColor Cyan
Write-Host $RepoName -ForegroundColor Cyan
# 情况 1: 目录不存在 - 执行 clone
if (-not (Test-Path -Path $repoPath)) {
Write-Host " → 本地目录不存在,开始克隆..." -ForegroundColor Yellow
# 进入父目录
Push-Location -Path $ParentDir
# 执行 clone
$cloneResult = git clone $remoteUrl $RepoName 2>&1
$cloneSuccess = $LASTEXITCODE -eq 0
Pop-Location
if ($cloneSuccess) {
Write-Host " ✓ [CLONED] 克隆成功" -ForegroundColor Green
$script:cloned++
}
else {
Write-Host " ✗ [ERROR] 克隆失败 - 请检查仓库是否存在或网络连接" -ForegroundColor Red
$script:failed++
}
Write-Host ""
return
}
# 情况 2: 目录存在但不是 Git 仓库 - 跳过并警告
if (-not (Test-Path -Path (Join-Path -Path $repoPath -ChildPath ".git"))) {
Write-Host " ⚠ [SKIPPED] 目录存在但不是 Git 仓库" -ForegroundColor Yellow
$script:skipped++
Write-Host ""
return
}
# 情况 3: 是 Git 仓库 - 执行 pull
Write-Host " → Git 仓库已存在,开始更新..." -ForegroundColor Yellow
# 进入仓库目录
Push-Location -Path $repoPath
# 获取当前分支
$currentBranch = git rev-parse --abbrev-ref HEAD 2>&1
if ([string]::IsNullOrWhiteSpace($currentBranch) -or $LASTEXITCODE -ne 0) {
Write-Host " ✗ [ERROR] 无法确定当前分支" -ForegroundColor Red
$script:failed++
Pop-Location
Write-Host ""
return
}
# 保存当前提交哈希
$beforeHash = git rev-parse HEAD 2>&1
# 执行 pull
$pullResult = git pull origin $currentBranch 2>&1
$pullSuccess = $LASTEXITCODE -eq 0
if ($pullSuccess) {
# 获取更新后的提交哈希
$afterHash = git rev-parse HEAD 2>&1
if ($pullResult -match "Already up.to.date|Already up-to-date") {
Write-Host " ○ [UP-TO-DATE] 已是最新版本" -ForegroundColor Cyan
$script:uptodate++
}
elseif ($beforeHash -ne $afterHash) {
Write-Host " ✓ [UPDATED] 更新成功" -ForegroundColor Green
$script:updated++
}
else {
Write-Host " ○ [UP-TO-DATE] 已是最新版本" -ForegroundColor Cyan
$script:uptodate++
}
}
else {
Write-Host " ✗ [ERROR] 更新失败" -ForegroundColor Red
$errorLines = ($pullResult | Out-String).Split("`n") | Select-Object -First 2
Write-Host " 错误信息: $($errorLines -join ' ')" -ForegroundColor Red
$script:failed++
}
Pop-Location
Write-Host ""
}
# -------------------- 主循环 --------------------
# 根据模式获取仓库列表
if ($ListMode -eq "array") {
Write-Host "使用预定义仓库列表 (共 $($RepoList.Count) 个)" -ForegroundColor Cyan
Write-Host ""
# 遍历预定义的仓库列表
foreach ($repo in $RepoList) {
Process-Repo -RepoName $repo
}
}
elseif ($ListMode -eq "folders") {
Write-Host "基于现有文件夹列表同步" -ForegroundColor Cyan
Write-Host ""
# 获取父目录下的所有子文件夹
$folders = Get-ChildItem -Path $ParentDir -Directory -ErrorAction SilentlyContinue
if ($folders.Count -eq 0) {
Write-Host "警告: 父目录为空,没有需要处理的仓库" -ForegroundColor Yellow
Write-Host "提示: 可以将 ListMode 改为 'array' 并定义 RepoList" -ForegroundColor Yellow
exit 0
}
# 遍历所有文件夹
foreach ($folder in $folders) {
Process-Repo -RepoName $folder.Name
}
}
else {
Write-Host "错误: 未知的 ListMode '$ListMode'" -ForegroundColor Red
Write-Host "请设置 ListMode 为 'folders' 或 'array'" -ForegroundColor Yellow
exit 1
}
# -------------------- 输出统计信息 --------------------
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "同步完成!" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "总计处理: " -NoNewline
Write-Host "$total 个仓库" -ForegroundColor Cyan
Write-Host ""
Write-Host "✓ 克隆成功: $cloned" -ForegroundColor Green
Write-Host "✓ 更新成功: $updated" -ForegroundColor Green
Write-Host "○ 已是最新: $uptodate" -ForegroundColor Cyan
Write-Host "⚠ 跳过: $skipped" -ForegroundColor Yellow
Write-Host "✗ 失败: $failed" -ForegroundColor Red
Write-Host ""
# 如果有失败的,返回非零退出码
if ($failed -gt 0) {
exit 1
}
exit 0