27 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	title, date, excerpt, tags, rating
| title | date | excerpt | tags | rating | 
|---|---|---|---|---|
| Perforce Helix Core搭建 | 2022-12-21 14:51:55 | Perforce | ⭐ | 
前言
- 知乎
- P4服务器部署、配置、备份流程详解 https://zhuanlan.zhihu.com/p/676332084
 
 
Perforce Docker
可以使用这个容器: https://hub.docker.com/r/sourcegraph/helix-p4d
但这个容器是2020年构建的,我这里重新调整了一下,并且手动构建成功,具体可以参考下文。
DockerFile构建
大致步骤如下:
- 下载blueroseslol/helix-docker仓库的所有文件。
 - 构建DockerFile。
 
cd /home/perforce/helix-docker/helix-p4d/ && \
docker build -f /home/perforce/helix-docker/helix-p4d/Dockerfile -t helix-p4d:2024.5 .
docker build --file ./helix-p4d/Dockerfile --tag helix-p4d:2023.7 .
使用
docker run -d --name helix-p4d\
    -p 1666:1666 \
    -v /home/perforce/p4:/p4 \
    helix-p4d:2024.5
docker run -d \
    -p 1666:1666 \
    -v /home/perforce/p4:/p4 \
    sourcegraph/helix-p4d:2020.2
admin pass12349ers
Github文档
docker run --rm \
    --publish 1666:1666 \
    sourcegraph/helix-p4d:2020.2
默认端口:1666, 默认用户名为 admin, 默认密码: pass12349ers。以下是所有配置的默认值。
NAME=perforce-server
P4HOME=/p4
P4NAME=master
P4TCP=1666
P4PORT=1666
P4USER=admin
P4PASSWD=pass12349ers
P4CASE=-C0
P4CHARSET=utf8
JNL_PREFIX=perforce-server
可以使用--env 覆盖上述环境变量:
docker run --rm \
    --publish 1666:1666 \
    --env P4USER=amy \
    --env P4PASSWD=securepassword \
    sourcegraph/helix-p4d:2020.2
请注意,尽管服务器在重启后仍能存活(即数据被保留),但如果你在初始启动后(即镜像的第一次运行,在选项被硬编码为Perforce Helix核心服务器自身配置时)改变选项,它可能会中断。要启动一个长期运行的生产容器,记得要把数据目录(P4HOME)容器,把--rm标志换成d(分离):
docker run -d \
    --publish 1666:1666 \
    --env P4PASSWD=securepassword \
    --volume ~/.helix-p4d-home:/p4 \
    sourcegraph/helix-p4d:2020.2
启用SSL
首先生成自签名证书:
mkdir ssl
pushd ssl
openssl genrsa -out privatekey.txt 2048
openssl req -new -key privatekey.txt -out certrequest.csr
openssl x509 -req -days 365 -in certrequest.csr -signkey privatekey.txt -out certificate.txt
rm certrequest.csr
popd
接下来设置SSL文件映射目录也就是P4SSLDIR的值,并且设置P4PORT使用SSL。
docker run --rm \
    --publish 1666:1666 \
    --env P4PORT=ssl:1666 \
    --env P4SSLDIR=/ssl \
    --volume ./ssl:/ssl \
    sourcegraph/helix-p4d:2023.1
时间显示问题
- 修改容器内系统时区。
 - 修改P4V时间显示,Edit - Preferences - Display - Show date andtime as,Server time => Local time。
 
Docker容器修改时间
方法一:配置Dockerfile镜像时修改,这样打包出来的镜像文件是需要的时区的。 操作方式:Dockerfile中添加代码
# 在安装tzdata之前最好先update和upgrade,以防apt-get获取不到tzdata
RUN apt-get update -y && apt-get upgrade -y
# 安装,中国用户填写[Asia/Shanghai] ,表示亚洲/上海 ,东八区
RUN apt-get install -y tzdata && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
缺点:由于构建时需要更新ubuntu,所以需要需要网络支持,网络不好的时候拖累构建镜像的速度。亲测,在中国白天速度快,晚上慢。
建议通过env进行指定:
ENV TZ=Asia/Shanghai
RUN In -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
方法二(强烈不推荐):在运行的容器中,进行修改 操作方式:docker attach 登录到运行的容器中执行如下代码
# 在安装tzdata之前最好先update和upgrade,以防apt-get获取不到tzdata
apt-get update -y && apt-get upgrade -y
# 安装
apt-get install -y tzdata
# 配置
echo "Asia/Shanghai" > /etc/timezone
# dpkg-reconfigure -f noninteractive tzdata 或者这个。
dpkg-reconfigure tzdata
方法三:启动容器的时候进行设置 操作方式:启动命令中添加 挂载目录,例如:
# 启动容器时挂载宿主机目录
docker run -v /etc/localtime:/etc/localtime:ro <IMAGE:TAG>
#  其中 -v 参数中ro代表只读模式(read only)
#  如果您的项目中已经使用了-v 没有关系,启动时挂载多个目录只要写多个-v就可以
缺点:依赖于宿主机,一般生产环境宿主机都是linux,如果你也是Linux内核,推荐使用
推送镜像到Dockerhub
登录
docker login
# Github
docker login ghcr.io -u 378100977@qq.com -p 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
推送
docker tag 5572f8b12de1 blueroses/perforce-helix-p4d:2024.5
docker push blueroses/perforce-helix-p4d:2024.5
# 登录github
docker push ghcr.io/blueroses/perforce-helix-p4d:2024.5
helix-proxy Docker
Package: helix-proxy Priority: optional Section: non-free/vcs Installed-Size: 30 Maintainer: Perforce Software, Inc. support+packaging@perforce.com Architecture: amd64 Source: perforce Version: 2024.1-2596294~focal
IDE设置
- VSCode - Settings - Extensions - Perforce
- Client:工作区名称
 - Dir:工作目录
 - Password:密码
 - Port:服务器ip与端口
 - User:用户名
 
 - Rider - Settings - Version Control - Perforce
- 输入Server、User、Workspace、utf8
 
 
Perforce
参考
- 官方文档
 - 知乎&UE官方文档
 - 视频
 
cmd
- 设置默认服务器IP:
p4 set P4PORT=servername:port - 设置默认用户名:
p4 set P4USER=your.username - 设置typemap:
p4 -P YourPassword typemap - 设置p4ignore
p4 set P4IGNORE=.p4ignorep4 ignores
 p4 add -f ...:add(add所有文件并且包含文件名含通配符的文件)p4 reconcile -aed:检查所有增加/修改/删除的文件并且放到Pending Changelist- p4 clean
p4 clean -a:从工作区中删除没有add的文件。p4 clean -n:不执行任何操作即可预览操作结果。p4 clean -i:可清除ignore的文件。
 
规划
开发目录设计
- 
ArtSource(美术资源:引擎中相应的美术资产应该统一从ArtSource仓库导入,这样美术人员可以集中在标准资产管线下的资产迭代,可以更加集中注意力于美术资产质量,所以前提是项目初期必须构建标准稳定的渲染和审核验收流程(这一点也是国内很多项目及经常返工,开发成本极高的原因))
 - 
Engine(引擎路径,这里我用于个人使用则不需要太多的分流)
 - 
Project(项目工程)
 
Example:
- e:\Perforce
- ArtSource
 - ShowRoom
 - UnrealEngine
 
 
ASoul P4的设计
仓库:
- Engine(Stream Depot)
- 引擎源码
 
 - Project(Stream Depot)
- 构建引擎。
 - 项目工程。
 
 - ArtSource(Local Depot)
- 美术资产。
 
 
分支
- Release
 - Mainline
 - Development
- UE4
 - UE5
 - Trunk分支(主干)
 - shiwan(线上分支)
- shiwanxxx
 - shiwanpico
 - ...
 
 
 
使用最暴力的Mainland(主干)分支开发模式,如有试玩需求,会创建shiwan分支。
用户
- admin
 - art
 - director
 remote(这个用户名无法登陆)- qa
 
权限管理
//仓库名/分支/目录/...
- 
- read://...
 
 - art:
- write://Project/Development/LiveDirector/Content/...
 
 - director
- write://Project/Development/LiveDirector/Content/...
 
 - qa
- write://Project
 
 
WorkSpace设置
- 编码使用:UTF8-no bom
 - Connection–>Edit Current Workspace–>Advanced,设置为
- Line ending characters for text file -> 
UNIX style linefeed - OnSubmit -> 
Don't submit unchanged files - 勾选
- Allwrite
 - Clobbr
 - Altsync(直播棚不要勾这个)
 
 
 - Line ending characters for text file -> 
 
.p4ignore
# Ignore IDE related files
.vscode\
.vsconfig\
# Ignore project-specific files
LiveDirector\Binaries\**\*.pdb
LiveDirector\Binaries\**\*-Debug.*
LiveDirector\Binaries\**\*-Shipping.*
LiveDirector\Build\Receipts\*
LiveDirector\DerivedDataCache\*
LiveDirector\Intermediate\*
LiveDirector\Plugins\**\Intermediate\*
LiveDirector\Saved\*
LiveDirector\*.sln
LiveDirector\*.vcxproj
LiveDirector\*.vs\
LiveDirector\*.idea\
LiveDirector\obj\
LiveDirector\**\FileOpenOrder\
Tools\VCluster\Binaries\**\*.pdb
Tools\VCluster\Binaries\**\*-Debug.*
Tools\VCluster\Binaries\**\*-Shipping.*
Tools\VCluster\Build\Receipts\*
Tools\VCluster\DerivedDataCache\*
Tools\VCluster\Intermediate\*
Tools\VCluster\Plugins\**\Intermediate\*
Tools\VCluster\Saved\*
Tools\VCluster\*.sln
Tools\VCluster\*.vcxproj
Tools\VCluster\*.vs\
Tools\VCluster\*.idea\
Tools\VCluster\obj\
Tools\VCluster\**\FileOpenOrder\
# Ignore Engine temporary files
Engine\**\__pycache__\*.pyc
# Ignore temporary files for Editor runs
Engine\Engine\Intermediate\EditorRuns\
# Add back binary-distributed plugins
!LiveDirector\Plugins\DirectorAssistanter\Intermediate\
# Ignore RiderLink
LiveDirector\Plugins\Developer\RiderLink\
# Ingore LiveCoding(?) temporary files
Engine\**\Intermediate\Build\**\*.h.old
# Ignore UnrealInsights temporary files
Engine\Engine\Programs\UnrealInsights\Saved\
Engine\Engine\Programs\UnrealInsights\Intermediate\
# Ignore Node.js moddules for RemoteControlWebInterface
Engine\Engine\Plugins\VirtualProduction\RemoteControlWebInterface\**\node_modules\
Engine\Engine\Plugins\VirtualProduction\RemoteControlWebInterface\**\package.json
Engine\Engine\Plugins\VirtualProduction\RemoteControlWebInterface\**\package-lock.json
Engine\Engine\Plugins\VirtualProduction\RemoteControlWebInterface\WebApp\**\build\
Engine\Engine\Plugins\VirtualProduction\RemoteControlWebInterface\WebApp\Server\public\
# Ignore all Engine files.
Engine\
# Ignore Ts History
LiveDirector\ts_file_versions_info.json
搭建p4顺序
- 搭建Perforce服务
 - 创建一个Stream Depot或者所有Depot。
 - 设置 p4 typemap
 - 创建MainLine分支
 - 添加.p4ignore文件
 - 创建一个工作区,设置工作区设置后上传文件。
 
Typemap
typemap 的设置能够在 Perforce 中控制文件的只读和可写的形式。 然后要做这件事情,需要管理员先在命令行cmd下设置 P4 的环境变量。
在指定仓库上右键,点击Open Command Windows Here,输入p4 typemap即可在弹出的txt文件中修改保存关闭即可。(输入UE官方推荐的内容即可)
# The form data below was edited by Jeff
# Perforce File Type Mapping Specifications.
#
#  TypeMap:	a list of filetype mappings; one per line.
#		Each line has two elements:
#
#  		Filetype: The filetype to use on 'p4 add'.
#
#  		Path:     File pattern which will use this filetype.
#
# See 'p4 help typemap' for more information.
TypeMap:
	text //....asp
	text //....cnf
	text //....css
	text //....htm
	text //....html
	text //....inc
	text //....js
	text //....ts
	text+w //....log
	text+w //....ini
	text+w //....pdm
	binary+Fl //....zip
	binary+Fl //....bz2
	binary+Fl //....rar
	binary+Fl //....gz
	binary+Fl //....avi
	binary+Fl //....jpg
	binary+Fl //....jpeg
	binary+Fl //....mpg
	binary+Fl //....gif
	binary+Fl //....tif
	binary+Fl //....mov
	binary+Fl //....jar
	binary+l //....ico
	binary+l //....exp
	binary+l //....btr
	binary+l //....bmp
	binary+l //....doc
	binary+l //....dot
	binary+l //....xls
	binary+l //....ppt
	binary+l //....pdf
	binary+l //....tar
	binary+l //....exe
	binary+l //....dll
	binary+l //....lib
	binary+l //....bin
	binary+l //....class
	binary+l //....war
	binary+l //....ear
	binary+l //....so
	binary+l //....rpt
	binary+l //....cfm
	binary+l //....ma
	binary+l //....mb
	binary+l //....pac
	binary+l //....m4a
	binary+l //....mp4
	binary+l //....aac
	binary+l //....wma
	binary+l //....docx
	binary+l //....pptx
	binary+l //....xlsx
	binary+l //....png
	binary+l //....raw
	binary+l //....odt
	binary+l //....ods
	binary+l //....odg
	binary+l //....odp
	binary+l //....otg
	binary+l //....ots
	binary+l //....ott
	binary+l //....psd
	binary+l //....sxw
	binary+S2w //....exe
	binary+S2w //....dll
	binary+S2w //....lib
	binary+S2w //....app
	binary+S2w //....dylib
	binary+S2w //....stub
	binary+S2w //....ipa
	binary //....bmp
	text //....ini
	text //....config
	text //....cpp
	text //....h
	text //....c
	text //....cs
	text //....m
	text //....mm
	text //....py
	binary+l //....uasset
	binary+l //....umap
	binary+l //....upk
	binary+l //....udk
	binary+w //....exe
	binary+w //....dll
	binary+w //....lib
	binary+w //....app
	binary+w //....dylib
	binary+w //....stub
	binary+w //....ipa
	binary //....bmp
	text //....ini
	text+w //....config
	text //....cpp
	text //....h
	text //....c
	text //....cs
	text //....m
	text //....mm
	text //....py
	binary+l //....uasset
	binary+l //....umap
	binary+l //....upk
	binary+l //....udk
	binary+l //....ubulk
	text //....ignore
相关概念
Workspace
- 官方工作区文档:https://www.perforce.com/manuals/p4guide/Content/P4Guide/configuration.workspace.options.html
 
Workspace可以理解为,depot到本地的一个映射,对应本地的一个目录,存储了该工作区域的相关设置以及历史记录。
新建Workspace,在p4admin中depot查看在服务器中存放的所有Ddepot仓库
开发的过程中可以有多个Workspace(例如一个用来开发,一个用来更新验证保证提交没有错误),但一般只推荐有一个Workspace。
WorkspaceView
PS. 非流用户可以通过以下方式更新客户端工作区视图
- 调用 p4 client 命令,打开客户端规范。
 - 编辑 View: 客户端规范中的字段。
 
AltSync
这是一种2024.1推出的新的同步技术,允许您减少从库同步到客户端工作区时的初始等待时间,从而加快工作速度。您可以节省时间、磁盘空间和网络带宽,因为您只在需要时下载所需的内容。相关文档:
- 文档:
 - p4vfs(需要额外安装)
 
P4ExcludeList
.p4ignore
创建.p4ignore文件后,执行命令行设置ignore
p4 set P4IGNORE=.p4ignore
p4 ignores
# Ignore project files in the root
*.sln
!*\*.sln
.vs
*.suo
*.opensdf
*.sdf
*.pdb
*-Debug.dll
*.xcodeproj
.\Makefile
.\CMakeLists.txt
.\.ue4dependencies
 
ipch\*
 
# Packaged engine builds
LocalBuilds\*
# DDC should never be checked in
Engine\DerivedDataCache\*
Templates\**\DerivedDataCache\*
 
# Engine intermediates & binaries
Engine\Intermediate\*
Engine\Plugins\**\Intermediate\*
Engine\Programs\**\Intermediate\*
Engine\Binaries*
Engine\Plugins\**\Binaries\*
 
# Feature Packs (they might get updated with langauge packs?)
FeaturePacks\*
# Samples & Templates
Templates\**\Intermediate\*
Templates\**\Saved\*
Samples\**\Intermediate\*
# C# Intermediate folders
Engine\Source\Programs\**\obj\*
Engine\Platforms\**\Programs\**\obj\*
 
# Saved folders for programs should not be checked in
Engine\Programs\**\Saved\*
Engine\Programs\UnrealBuildTool\*
 
# Ignore any saved local files
Engine\Saved\*
 
# Ignore any build receipts
Engine\Build\Receipts\*
 
# Ignore Unix backup files
*~
 
# Ignore Mac desktop services store files
.DS_Store
 
# Ignore crash reports
crashinfo--*
 
# Ignore linux project files
*.user
*.pro
*.pri
*.kdev4
 
#
# Setup.bat Ignores
#
# There already might be some files pushed into the repo that would otherwise be
# filtered: those are from the initial commit, coming directly from UE4-GitHub.
# After running Setup.bat, the folders below will be populated with ~46GB of 
# files. Hence we'll be blanked ignoring some directories such as ThirdParty, 
# Media, Content, etc. If we want to change anything in those blanked-ignored 
# folders, we should unignore the specific thing we're adding.
#
.git\*
Samples\**\Content\*
Samples\**\Media\*
Templates\**\Content\*
Templates\**\Media\*
Templates\Media\*
Engine\Platforms\**\Content\*
Engine\Documentation\*
Engine\Extras\*
Engine\Content\*
Engine\Build\*
Engine\Source\ThirdParty\*
Engine\Source\Programs\*
Engine\Source\Developer\*
Engine\Plugins\*
# Specific files
Engine\Config\ShaderCategories.csv
.tgitconfig
.ue4dependencies
# After all this above, there's still a couple folders and files left that doesn't
# fit the filtering criteria above, so we handle them individually here.
Engine\Source\Runtime\Navmesh\RecastDemo*
Engine\Source\Runtime\Launch\Resources\Mac*
Engine\Source\Runtime\Launch\Resources\Linux*
Engine\Source\Runtime\Experimental\Voronoi\Private\voro++*
Engine\Source\Runtime\Apple\MetalRHI\Public\ue4_stdlib.metal
Engine\Source\Runtime\AVEncoder\Private\Microsoft\Windows\ThirdParty\NvEncoder\LicenseAgreement.pdf
Engine\Source\Runtime\Experimental\Chaos\.clang-format
Engine\Source\Runtime\TraceLog\Private\Trace\LZ4\Epic.patch
Templates\TemplateResources\Standard\*.FBX
#
# PLUGINS
#
# Plugins that come with Setup.bat are ignored above altogether, so we un-ignore
# the custom plugins we want to ship with the customized UE4.
!Engine\Plugins\Marketplace*
!Engine\Plugins\Runtime\HoudiniEngine*
# ... but keep ignoring their Build & Intermediate
Engine\Plugins\Marketplace\**\Intermediate\*
Engine\Plugins\Marketplace\**\Binaries\*
Engine\Plugins\Runtime\**\Intermediate\*
Engine\Plugins\Runtime\**\Binaries\*
#
# PackageEngine.bat Ignores
#
# Packaging the engine will generate some .ini files which are safe to ignore
#
Samples\**\Saved\*
Job
- https://www.bilibili.com/video/BV13C4y1s73M/?spm_id_from=333.999.0.0&vd_source=d47c0bb42f9c72fd7d74562185cee290 可以关联多个Commit并且可以设置状态,以此追踪一个功能或者Bug的工作状态。比较像git的Issue以及工单系统。
 
分支合并
分支切换需要修改设置以防止增加工作区:Preference - Stream - "Work in this Stream" menu behavior选项设置为Reuse current workspace。
Helix4Git
- 官方文档
 - 代理商知乎
 
DockerFile搞起来太麻烦……
Perforce Proxy
一种用于同步主Perforce服务器数据的远程服务器。适合远程的分布式协作。
其他
注册源码引擎到EpicGames
经过上面的步骤,源码引擎已经构建成功,但是在对项目就行选择引擎版本的时候,发现并没有这个版本 。这是因为,构建的引擎没有注册到EpicGames中,找到EpicGames安装目录下的注册器。复制到源码工程并且运行即可。
Launcher\Engine\Binaries\Win64\UnrealVersionSelector.exe
Perforce问题解决
大小写问题解决
官方的相关解释:
我想到一个解决方案,就是删除这个文件夹,之后分别以为大写与小写文件名,再拉新就可以把资产都拉下来。
- 删除文件夹。
 - 新建 Nailin_Birthday2024_V02,拉新备份后比较效果。
 - 新建 NaiLin_Birthday2024_V02,拉新备份后比较效果。
 - 替换旧与错误资产。
 - 删除服务器上的Nailin_Birthday2024_V02与NaiLin_Birthday2024_V02文件夹。
 - 重新上传。
 
使用Trigger进行检查
- 官方文档
 - 案例
- 运行Python脚本 https://stackoverflow.com/questions/78156353/perforce-trigger-script-not-found
 - Python检查代码: https://gist.github.com/cmcginty/8d99e0eac345e06dc1ba
 - https://swarm.workshop.perforce.com/files/guest/perforce_software/sdp/dev/Unsupported/Samples/triggers/CheckCaseTrigger.py?v=%40%3D29027
 - https://swarm.workshop.perforce.com/files/guest/perforce_software/sdp/dev/Server/Unix/p4/common/bin/triggers/CheckCaseTrigger.py?v=4
 
 
添加一个Trigger
字段名称(例如Triggers:)必须左对齐(不缩进)并且必须以冒号结尾。字段值(即您添加的一组行,每个触发器一行)必须在字段名称下方的行上使用空格或制表符缩进。
表单p4 triggers如下所示:
Triggers:
  relnotecheck change-submit //depot/bld/...  "/usr/bin/rcheck.pl %user%"
  verify_jobs  change-submit //depot/...      "/usr/bin/job.py %change%"
PS.脚本内部的换行符需要跟换成unix的!
Trigger Example
on_create_workspace.sh:创建工作区自动填写设置。
workspacename=$1
workspacefile=$2
p4="p4 -u perforce_trigger"
$p4 trust -fy >/dev/null 2>&1
if [ -z "$($p4 clients -e $workspacename)" ]; then
  sed -i '/Options:/{s/noallwrite/allwrite/g}' $workspacefile
  sed -i '/Options:/{s/noclobber /clobber /g}' $workspacefile
  
  if grep -q "^SubmitOptions:" $workspacefile; then
    sed -i 's/^SubmitOptions:.*/SubmitOptions: leaveunchanged/' $workspacefile
  else
    echo "SubmitOptions: leaveunchanged" >> $workspacefile
  fi
  if grep -q "^LineEnd:" $workspacefile; then
    sed -i 's/^LineEnd:.*/LineEnd: unix/' $workspacefile
  else
    echo "LineEnd: unix" >> $workspacefile
  fi
fi
check_case_conflict.sh:大小写检查
#!/bin/bash
changelist=$1
p4="p4 -p 127.0.0.1:1666 -u perforce_trigger"
pending_files=($($p4 opened -s -c $changelist | awk '{print $1}'))
canSubmit=0
function p4_user_login()
{
  $p4 login -s ${@:2} "$1" 2>/dev/null | grep -q ^//
}
if p4_user_login; then
  echo nswl123456|$p4 -u perforce_trigger login
fi
function p4_file_exist()
{
  $p4 files -e ${@:2} "$1" 2>/dev/null | grep -q ^//
}
function p4_path_exist()
{
  $p4 dirs ${@:2} "$1" 2>/dev/null | grep -q ^//
}
function check_changelist_file_conflict()
{
  local file=$1
  local pending_list=(${@:2})
  local message=
  for other_file in ${pending_list[@]}; do
    if [ $file != $other_file ] && [ ${file,,} == ${other_file,,} ]; then
      message="$message\n$other_file"
    fi
  done
  if [ "$message" ]; then
    message="Changelist File Case Conflict(提交队列大小写冲突:文件):$message"
    printf "$message"
  fi
}
function check_changelist_path_conflict()
{
  local path=$(dirname $1)
  local pending_list=(${@:2})
  local message=
  while [ $path != '/' ]; do
    for i in ${!pending_list[@]}; do
      local other_file=${pending_list[$i]}
      if [[ "$other_file" != "$path"* ]] && [[ "${other_file,,}" == "${path,,}"* ]]; then
        message="$message\n$other_file"
        unset "pending_list[$i]"
      fi
    done
    path=$(dirname $path)
  done
  if [ "$message" ]; then
    message="Changelist Path Case Conflict(提交队列大小写冲突:路径):$message"
    printf "$message"
  fi
}
for file in ${pending_files[@]}; do
  # Check File Case Conflicted Or Not
  canSubmit=0
  message=
  if ! p4_file_exist $file && p4_file_exist $file -i; then
    #===== Output Error Message =====#
    message="$message\nDepot File Case Conflicted (仓库大小写冲突:文件):\n$($p4 files -i "$file")"
    #================================#
  fi
  # Check Path Case Conflicted Or Not
  path=$(dirname $file)
  while [ $path != '/' ]
  do
    if ! p4_path_exist $path && p4_path_exist $path -i; then
      #===== Output Error Message =====#
      message="$message\nDepot Path Case Conflicted (仓库大小写冲突:路径):\n$($p4 dirs -i "$path")"
      #================================#
      break
    fi
    path=$(dirname $path)
  done
  temp_message=$(check_changelist_file_conflict "$file" "${pending_files[@]}")
  if [ "$temp_message" ]; then
    message="$message\n$temp_message"
  fi
  temp_message=$(check_changelist_path_conflict "$file" "${pending_files[@]}")
  if [ "$temp_message" ]; then
    message="$message\n$temp_message"
  fi
  if [ "$message" ]; then
    canSubmit=1
    message="File(文件):\n$file\n$message"
    printf "\n==============================\n$message\n==============================\n"
  fi
done
exit $canSubmit
on_create_workspace form-out client "/p4/triggers/on_create_workspace.sh %formname% %formfile%"
check_case_conflict change-submit //... "/p4/triggers/check_case_conflict.sh %changelist%"
自动登录命令
echo password|p4 -u user login
工作区设置选项
https://www.perforce.com/manuals/v22.2/p4guide/Content/P4Guide/configuration.workspace.html