238 lines
7.5 KiB
PowerShell
238 lines
7.5 KiB
PowerShell
# ============================================
|
||
# 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 |