用 Jenkins 把上游 P4 镜像同步到本地 P4
February 21, 2024About 3 min
用 Jenkins 把上游 P4 镜像同步到本地 P4
把上游(比如 Epic 的 UE 源码 P4)的改动按 CL 区间镜像同步到自己团队的本地 P4。整体分两步:先在 client P4 里 sync 到目标 CL,再把这批文件 reconcile 提交进本地 P4,用一个文件记录「上次同步到哪个 CL」串起增量。
初始化:两个 workspace 放同一空目录
- 把 client P4 的 workspace 和 local P4 的 workspace 建在同一个空目录下。
- 在 client P4 里 get latest,记下当前 CL。
- 把目录里所有文件提交进 local P4 作为基线:
dir /b /s /a-d | p4 -x - add # 添加当前目录及子目录下所有文件
p4 submit --parallel 8 -f revertunchanged -d "Upload Epic Changes @<NowCL>"
第一步:在 client P4 sync 到目标 CL,并算出增量区间
用一个 LastCL.txt 记上次同步到的 CL。本次目标 CL(UpdateCL)由参数指定;不指定就取 client 里最新一次 submitted 的 CL。算出 [LastCL, NowCL] 区间后 sync,并把这次涉及的文件列表导出给第二步用。
$CLIENT = "ue-mirror-client"
p4 set P4PORT=<p4-port>
p4 set P4CLIENT=$CLIENT
p4 set P4USER=<p4-user>
echo ${ENV:P4PSD} | p4 login
$LastCLStr = Get-Content "E:\Msg\LastCL.txt"
echo LastCLStr=$LastCLStr
# 本地 CL + 1 作为区间起点
[int]$LastCL = $LastCLStr
$LastCL = $LastCL + 1
echo LastCL=$LastCL
echo UpdateCL=${ENV:UpdateCL}
if (${ENV:UpdateCL}) {
# 指定的目标 CL 必须比本地 CL 大
if (${ENV:UpdateCL} -lt "$LastCL") {
$NowCL = $LastCL - 1
$LastCL = ${ENV:UpdateCL}
} else {
$NowCL = ${ENV:UpdateCL}
}
} else {
# 没指定就取最新一次 submitted 的 CL
$CLMsg = p4 changes -m 1 -s submitted //$CLIENT/...
$NowCL = ($CLMsg -split " ")[1]
}
echo NowCL=$NowCL
if ($LastCLStr -ne $NowCL) {
p4 sync -f --parallel 8 "//$CLIENT/...@${LastCL},@${NowCL}"
$NowCL | Out-File E:\Msg\NowCL.txt utf8 -NoNewline
# 导出本次区间涉及的文件,顺手把 depot 路径换成本地磁盘路径
p4 files "//$CLIENT/...@${LastCL},@${NowCL}" | foreach {
$file = ($_ -split "#")[0] -replace "//UE5/Release-5.0", "E:\ue5_stage"
echo $file
} | Out-File E:\Msg\filelist.txt utf8
} else {
echo "NowCL:${NowCL} = LastCL:${LastCLStr}"
}
第二步:把这批文件 reconcile 提交进本地 P4
读第一步导出的 filelist.txt,逐个 p4 reconcile 到本地 P4 的 default changelist,再一次性 submit。revertunchanged 保证没真正变化的文件不会进提交。
# clientSyncToLocal.ps1
p4 set P4PORT=<local-p4-port>
p4 set P4CLIENT=<local-client>
p4 set P4USER=<local-user>
echo ${ENV:P4PSD} | p4 login
p4 info
$LastCLPath = "E:\Msg\LastCL.txt"
$LastCL = Get-Content "$LastCLPath"
$NowCL = Get-Content "E:\Msg\NowCL.txt"
cd ${ENV:WORKSPACE}
p4 flush
$len = 0
Get-Content E:\Msg\filelist.txt | foreach {
echo $_
p4 reconcile -f -c default "$_"
$len = $len + 1
}
echo "All update file num = $len"
$CLFiles = p4 opened -c default
echo "CLFiles=$($CLFiles.count)"
p4 submit --parallel 8 -f revertunchanged -d "Upload Epic Changes from @$LastCL to @$NowCL"
# 把本次 NowCL 写回 LastCL,作为下次增量的起点
$NowCL | Out-File $LastCLPath -NoNewline utf8
几个关键点:
p4 flush(即p4 sync -k)只更新本地的 have 记录、不真正传文件,因为文件已经在第一步 sync 下来了。reconcile自动判断每个文件是 add / edit / delete,不用手动 open。--parallel 8在文件量大时显著加速 sync 和 submit。- 用
LastCL.txt串增量,任何一步失败都不更新它,下次重跑会从上次成功的 CL 接着来。