@echo off
chcp 936 >nul 2>&1
setlocal enabledelayedexpansion
set "CRASH_LOG=%temp%\vcs_tool_crash.log"
echo 工具启动时间:%date% %time% > "!CRASH_LOG!" 2>&1
set "SELF_FILENAME=%~nx0"
echo 脚本文件名:!SELF_FILENAME! >> "!CRASH_LOG!" 2>&1
set "CONFIG_FILE=.vcs_ignore_suffix.ini"
set "IGNORE_SUFFIXES=vscode/o/d/htm/dep/lnp/_i/rar/zip/gitignore"
set "FOLDER_CONFIG_FILE=.vcs_ignore_folders.ini"
set "IGNORE_FOLDERS=bin/obj/temp/build/dist"
if exist "!CONFIG_FILE!" (
set "loaded_suffixes="
for /f "delims=" %%s in (!CONFIG_FILE!) do (
set "loaded_suffixes=!loaded_suffixes!%%s"
)
set "loaded_suffixes=!loaded_suffixes: =/!"
if "!loaded_suffixes!" neq "" (
set "IGNORE_SUFFIXES=!loaded_suffixes!"
)
echo 从配置文件加载忽略后缀:!IGNORE_SUFFIXES! >> "!CRASH_LOG!" 2>&1
) else (
echo 未找到配置文件,使用默认忽略后缀:!IGNORE_SUFFIXES! >> "!CRASH_LOG!" 2>&1
)
if exist "!FOLDER_CONFIG_FILE!" (
set "loaded_folders="
for /f "delims=" %%s in (!FOLDER_CONFIG_FILE!) do (
set "loaded_folders=!loaded_folders!%%s"
)
set "loaded_folders=!loaded_folders: =/!"
if "!loaded_folders!" neq "" (
set "IGNORE_FOLDERS=!loaded_folders!"
)
echo 从配置文件加载忽略文件夹:!IGNORE_FOLDERS! >> "!CRASH_LOG!" 2>&1
) else (
echo 未找到文件夹配置文件,使用默认忽略文件夹:!IGNORE_FOLDERS! >> "!CRASH_LOG!" 2>&1
)
:edit_suffixes
cls
echo ====================== 忽略设置 ======================
echo 当前忽略的文件后缀:!IGNORE_SUFFIXES!
echo 当前忽略的文件夹:!IGNORE_FOLDERS!
echo ----------------------------------------------------------
echo 1. 添加忽略后缀
echo 2. 移除忽略后缀
echo 3. 清空后缀忽略列表
echo 4. 添加忽略文件夹
echo 5. 移除忽略文件夹
echo 6. 清空文件夹忽略列表
echo 7. 保存配置并继续(直接回车默认此项)
==============================================================
set "SUFFIX_CHOICE="
set /p "SUFFIX_CHOICE=请选择操作(1-7,直接回车继续):"
if "!SUFFIX_CHOICE!"=="" set "SUFFIX_CHOICE=7"
if "!SUFFIX_CHOICE!"=="1" (
set "new_suffix="
set /p "new_suffix=请输入要忽略的后缀(无需输入".",例:txt):"
set "new_suffix=!new_suffix:/=!"
set "new_suffix=!new_suffix: =!"
if "!new_suffix!" neq "" (
set "is_exist=0"
set "temp_list=!IGNORE_SUFFIXES:/= !"
for %%s in (!temp_list!) do (
if /i "%%s"=="!new_suffix!" (
set "is_exist=1"
)
)
if !is_exist! equ 0 (
set "temp_suffixes=!IGNORE_SUFFIXES!"
set "temp_suffixes=!temp_suffixes://=/!"
if "!temp_suffixes!"=="" (
set "IGNORE_SUFFIXES=!new_suffix!"
) else (
set "IGNORE_SUFFIXES=!temp_suffixes!/!new_suffix!"
)
echo 已添加忽略后缀:!new_suffix!
) else (
echo 该后缀已在忽略列表中
)
) else (
echo 后缀不能为空
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="2" (
set "remove_suffix="
set /p "remove_suffix=请输入要移除的后缀:"
if "!remove_suffix!" neq "" (
for /f "delims=" %%a in ('
powershell -Command "$list='!IGNORE_SUFFIXES:/= !'; $remove='!remove_suffix!'; $arr=$list -split ' ' | Where-Object { $_ -ne $remove }; $arr -join '/'"
') do set "IGNORE_SUFFIXES=%%a"
echo 已移除:!remove_suffix!
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="3" (
set "confirm="
set /p "confirm=确定要清空后缀忽略列表吗?(Y/N):"
if /i "!confirm!"=="Y" (
set "IGNORE_SUFFIXES="
echo 已清空后缀忽略列表
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="4" (
set "new_folder="
set /p "new_folder=请输入要忽略的文件夹(例:bin):"
set "new_folder=!new_folder:/=!"
set "new_folder=!new_folder: =!"
if "!new_folder!" neq "" (
set "is_exist=0"
set "temp_list=!IGNORE_FOLDERS:/= !"
for %%s in (!temp_list!) do (
if /i "%%s"=="!new_folder!" (
set "is_exist=1"
)
)
if !is_exist! equ 0 (
:: 更新内存中的忽略列表
set "temp_folders=!IGNORE_FOLDERS!"
set "temp_folders=!temp_folders://=/!"
if "!temp_folders!"=="" (
set "IGNORE_FOLDERS=!new_folder!"
) else (
set "IGNORE_FOLDERS=!temp_folders!/!new_folder!"
)
if /i "!VCS_TYPE!"=="Git" (
set "clean_folder=!new_folder!"
if "!clean_folder:~-1!"=="/" set "clean_folder=!clean_folder:~0,-1!"
set "rule1=/!clean_folder!/"
set "rule2=/!clean_folder!/*"
set "rule3=/**/!clean_folder!/"
for %%r in ("!rule1!" "!rule2!" "!rule3!") do (
findstr /x /c:"%%~r" ".gitignore" >nul 2>&1
if !errorlevel! equ 1 (
echo %%~r >> ".gitignore"
)
)
call :clean_gitignore_duplicates
)
echo 已添加忽略文件夹:!new_folder!
) else (
echo 该文件夹已在忽略列表中
)
) else (
echo 文件夹名不能为空
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="5" (
set "remove_folder="
set /p "remove_folder=请输入要移除的文件夹:"
if "!remove_folder!" neq "" (
:: 从内存变量中移除
for /f "delims=" %%a in ('
powershell -Command "$list='!IGNORE_FOLDERS:/= !'; $remove='!remove_folder!'; $arr=$list -split ' ' | Where-Object { $_ -ne $remove }; $arr -join '/'"
') do set "IGNORE_FOLDERS=%%a"
if /i "!VCS_TYPE!"=="Git" if exist ".gitignore" (
set "clean_folder=!remove_folder!"
:: 处理文件夹名中的特殊字符
set "escaped_folder=!clean_folder:.=\.!"
set "escaped_folder=!escaped_folder:?=\?!"
set "escaped_folder=!escaped_folder:*=\*!"
set "escaped_folder=!escaped_folder: =\ !"
set "temp_file=%temp%\gitignore_temp.tmp"
powershell -Command "$folder = [regex]::Escape('!clean_folder!'); $gitignore = '.gitignore'; $temp = '%temp_file%'; Get-Content $gitignore | Where-Object { $_ -notmatch '^\/' + $folder + '\/$' -and $_ -notmatch '^\/' + $folder + '\/\*$' -and $_ -notmatch '^\*\*\/' + $folder + '\/$' } | Set-Content $temp -Encoding default; Move-Item $temp $gitignore -Force" >nul 2>&1
del "!temp_file!" >nul 2>&1
echo 已同步清理.gitignore中关于"!remove_folder!"的规则
)
echo 已移除:!remove_folder!
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="6" (
set "confirm="
set /p "confirm=确定要清空文件夹忽略列表吗?(Y/N):"
if /i "!confirm!"=="Y" (
set "IGNORE_FOLDERS="
:: 清空.gitignore中所有文件夹规则(Git专属)
if /i "!VCS_TYPE!"=="Git" if exist ".gitignore" (
set "temp_file=%temp%\gitignore_temp.tmp"
powershell -Command "$gitignore = '.gitignore'; $temp = '%temp_file%'; Get-Content $gitignore | Where-Object { $_ -notmatch '^\/.*\/$' -and $_ -notmatch '^\/.*\/\*$' -and $_ -notmatch '^\*\*\/.*\/$' } | Set-Content $temp -Encoding default; Move-Item $temp $gitignore -Force" >nul 2>&1
del "!temp_file!" >nul 2>&1
echo 已同步清空.gitignore中的文件夹规则
)
echo 已清空文件夹忽略列表
)
pause >nul
goto edit_suffixes
)
if "!SUFFIX_CHOICE!"=="7" (
set "IGNORE_SUFFIXES=!IGNORE_SUFFIXES://=/!"
if "!IGNORE_SUFFIXES:~0,1!"=="/" set "IGNORE_SUFFIXES=!IGNORE_SUFFIXES:~1!"
if "!IGNORE_SUFFIXES:~-1!"=="/" set "IGNORE_SUFFIXES=!IGNORE_SUFFIXES:~0,-1!"
if "!IGNORE_SUFFIXES!"=="" (
echo. > "!CONFIG_FILE!"
) else (
echo !IGNORE_SUFFIXES:/= ! > "!CONFIG_FILE!"
)
:: 保存文件夹配置
set "IGNORE_FOLDERS=!IGNORE_FOLDERS://=/!"
if "!IGNORE_FOLDERS:~0,1!"=="/" set "IGNORE_FOLDERS=!IGNORE_FOLDERS:~1!"
if "!IGNORE_FOLDERS:~-1!"=="/" set "IGNORE_FOLDERS=!IGNORE_FOLDERS:~0,-1!"
if "!IGNORE_FOLDERS!"=="" (
echo. > "!FOLDER_CONFIG_FILE!"
) else (
echo !IGNORE_FOLDERS:/= ! > "!FOLDER_CONFIG_FILE!"
)
echo 配置已保存 >> "!CRASH_LOG!" 2>&1
)
set "IGNORE_REGEX="
set "temp_suffixes=!IGNORE_SUFFIXES:/= !"
for %%s in (!temp_suffixes!) do (
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=\.%%s$"
) else (
set "IGNORE_REGEX=!IGNORE_REGEX!|\.%%s$"
)
)
set "temp_folders=!IGNORE_FOLDERS:/= !"
for %%f in (!temp_folders!) do (
set "escaped_folder=%%f"
set "escaped_folder=!escaped_folder:.=\.!"
set "escaped_folder=!escaped_folder:?=\?!"
set "escaped_folder=!escaped_folder:*=\*!"
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=\\!escaped_folder!\\|/!escaped_folder!/"
) else (
set "IGNORE_REGEX=!IGNORE_REGEX!|\\!escaped_folder!\\|/!escaped_folder!/"
)
)
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=^$"
)
echo 忽略正则表达式: !IGNORE_REGEX! >> "!CRASH_LOG!" 2>&1
:: ========================= 第一步:自动检测版本控制系统 =========================
set "AUTO_DETECTED_VCS="
if exist ".git" (
set "AUTO_DETECTED_VCS=Git"
echo 自动检测到Git仓库 >> "!CRASH_LOG!" 2>&1
)
if exist ".svn" (
set "AUTO_DETECTED_VCS=SVN"
echo 自动检测到SVN仓库 >> "!CRASH_LOG!" 2>&1
)
if "!AUTO_DETECTED_VCS!"=="" (
:auto_detect_failed
cls
echo ======================自动生成格式提交工具 ======================
echo 警告:未检测到Git或SVN仓库
echo 请手动选择版本控制系统:
echo 1. Git(配合TortoiseGit)
echo 2. SVN(配合TortoiseSVN)
echo 3. 退出工具
echo ==============================================================
set "VCS_CHOICE="
set /p "VCS_CHOICE=请输入选项(1/2/3):"
if "!VCS_CHOICE!" neq "1" if "!VCS_CHOICE!" neq "2" if "!VCS_CHOICE!" neq "3" (
echo 输入错误,请重新选择!
pause >nul
goto auto_detect_failed
)
if "!VCS_CHOICE!"=="3" (
echo 已退出工具
echo 用户选择退出工具 >> "!CRASH_LOG!" 2>&1
pause >nul
del "!CRASH_LOG!" >nul 2>&1
exit /b 0
)
if "!VCS_CHOICE!"=="1" (
set "VCS_TYPE=Git"
) else (
set "VCS_TYPE=SVN"
)
echo 用户手动选择VCS类型:!VCS_TYPE! >> "!CRASH_LOG!" 2>&1
) else (
set "VCS_TYPE=!AUTO_DETECTED_VCS!"
echo ====================== 自动生成格式提交工具工具 ======================
echo 自动检测到: !VCS_TYPE! 仓库
echo 正在启动提交流程...
)
:: ========================= 第二步:通用初始化 =========================
set "COMMIT_MSG_FILE=%temp%\vcs_commit_msg.txt"
echo. > "!COMMIT_MSG_FILE!" 2>&1
if not exist "!COMMIT_MSG_FILE!" (
echo 创建提交信息文件失败,可能权限不足! >> "!CRASH_LOG!" 2>&1
echo 创建提交信息文件失败,请以管理员身份运行!
pause >nul
exit /b 1
)
echo 提交信息文件创建成功:!COMMIT_MSG_FILE! >> "!CRASH_LOG!" 2>&1
set "FILE_COUNT=0"
set "DEFAULT_TITLE_PREFIX=[feat][ARM]: "
set "DEFAULT_TASKID_PREFIX=#TaskID: "
set "SELECTED_COUNT=0"
set "SELECTED_PATH[0]="
set "SELECTED_NAME[0]="
set "SELECTED_STATUS[0]="
:: ========================= 第三步:获取文件列表 =========================
set "EXCLUDE_FILES=!SELF_FILENAME! .vcs_tool_config.ini vcs_tortoise_path_git.txt vcs_tortoise_path_svn.txt"
set "FILE_LIST_TMP=%temp%\vcs_filelist.tmp"
del "!FILE_LIST_TMP!" >nul 2>&1
:: 重新生成忽略正则(确保包含文件夹过滤)
set "IGNORE_REGEX="
set "temp_suffixes=!IGNORE_SUFFIXES:/= !"
for %%s in (!temp_suffixes!) do (
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=\.%%s$"
) else (
set "IGNORE_REGEX=!IGNORE_REGEX!|\.%%s$"
)
)
set "temp_folders=!IGNORE_FOLDERS:/= !"
for %%f in (!temp_folders!) do (
set "escaped_folder=%%f"
set "escaped_folder=!escaped_folder:.=\.!"
set "escaped_folder=!escaped_folder:?=\?!"
set "escaped_folder=!escaped_folder:*=\*!"
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=\\!escaped_folder!\\|/!escaped_folder!/"
) else (
set "IGNORE_REGEX=!IGNORE_REGEX!|\\!escaped_folder!\\|/!escaped_folder!/"
)
)
if "!IGNORE_REGEX!"=="" (
set "IGNORE_REGEX=^$"
)
echo 忽略正则表达式: !IGNORE_REGEX! >> "!CRASH_LOG!" 2>&1
if /i "!VCS_TYPE!"=="Git" (
echo 开始获取Git文件列表(已应用忽略过滤) >> "!CRASH_LOG!" 2>&1
:: 确保.gitignore存在(首次使用时创建)
if not exist ".gitignore" echo. > ".gitignore"
:: 清理Git缓存(仅处理当前忽略列表中的文件夹)
for %%f in (!temp_folders!) do (
set "clean_folder=%%f"
if "!clean_folder:~-1!"=="/" set "clean_folder=!clean_folder:~0,-1!"
if exist "!clean_folder!/" (
git rm -r --cached "!clean_folder!/" 2>> "!CRASH_LOG!" >nul 2>&1
git rm -r --cached "!clean_folder!/*" 2>> "!CRASH_LOG!" >nul 2>&1
)
)
:: 提交.gitignore变更
git add ".gitignore" 2>> "!CRASH_LOG!"
:: 重新获取文件列表(此时.gitignore已生效)
git status --porcelain 2>nul | powershell -Command "$ignoreRegex='!IGNORE_REGEX!'; $input | ForEach-Object { [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::Default.GetBytes($_)) } | Where-Object { $_ -notmatch $ignoreRegex } | Out-File -Encoding default '!FILE_LIST_TMP!'"
:: 新增过滤逻辑:处理未跟踪文件(??状态)的特殊情况
type "!FILE_LIST_TMP!" | findstr /v /c:"?? 多项??" > "!FILE_LIST_TMP!.tmp"
move /y "!FILE_LIST_TMP!.tmp" "!FILE_LIST_TMP!" >nul 2>&1
for /f "delims=" %%a in ('type "!FILE_LIST_TMP!"') do (
set "line=%%a"
set "line=!line:"=!"
set "status=!line:~0,2!"
set "status=!status: =!"
set "file_path=!line:~3!"
:trim_git_path
if "!file_path:~0,1!"==" " set "file_path=!file_path:~1!" & goto trim_git_path
call :process_file "!status!" "!file_path!"
)
) else (
echo 开始获取SVN文件列表(已应用忽略过滤) >> "!CRASH_LOG!" 2>&1
svn status --non-interactive --recursive 2>nul | powershell -Command "$ignoreRegex='!IGNORE_REGEX!'; $input | Where-Object { $_ -notmatch $ignoreRegex } | Out-File -Encoding default '!FILE_LIST_TMP!'"
for /r %%f in (*) do (
echo "%%f" | findstr /i /c:"\.svn\\" >nul 2>&1
if !errorlevel! equ 1 (
echo "%%f" | findstr /i /r "!IGNORE_REGEX!" >nul 2>&1
if !errorlevel! equ 1 (
set "is_new=1"
for /f "tokens=2*" %%s in ('type "!FILE_LIST_TMP!"') do (
if "%%~f"=="%%~s%%t" set "is_new=0"
)
set "is_excluded=0"
for %%x in (!EXCLUDE_FILES!) do (
if /i "%%~nxf"=="%%x" set "is_excluded=1"
)
if !is_new! equ 1 if !is_excluded! equ 0 (
echo ? "%%f" >> "!FILE_LIST_TMP!"
)
) else (
echo SVN扫描时忽略文件(后缀/文件夹匹配): %%f >> "!CRASH_LOG!" 2>&1
)
)
)
for /f "delims=" %%a in ('type "!FILE_LIST_TMP!"') do (
set "line=%%a"
set "line=!line:"=!"
set "status=!line:~0,1!"
set "file_path=!line:~2!"
:trim_svn_path
if "!file_path:~0,1!"==" " set "file_path=!file_path:~1!" & goto trim_svn_path
set "final_status=!"
if "!status!"=="M" set "final_status=M"
if "!status!"=="A" set "final_status=A"
if "!status!"=="?" set "final_status=A"
if "!status!"=="!" set "final_status=D"
if "!status!"=="D" set "final_status=D"
if not "!final_status!"=="" (
if not "!final_status!"=="D" (
if exist "!file_path!" (
if not exist "!file_path!\" (
call :process_file "!final_status!" "!file_path!"
) else (
echo 跳过目录: !file_path! >> "!CRASH_LOG!" 2>&1
)
) else (
call :process_file "!final_status!" "!file_path!"
)
)
)
)
)
del "!FILE_LIST_TMP!" >nul 2>&1
echo 获取文件列表完成,共!FILE_COUNT!个修改文件 >> "!CRASH_LOG!" 2>&1
:: ========================= 第四步:无修改文件处理 =========================
if !FILE_COUNT! equ 0 (
echo.
echo 没有发现任何修改的文件
echo 请按任意键退出...
echo 无修改文件,工具退出 >> "!CRASH_LOG!" 2>&1
pause >nul
del "!COMMIT_MSG_FILE!" >nul 2>&1
del "!CRASH_LOG!" >nul 2>&1
exit /b 0
)
:: ========================= 第五步:显示文件列表 =========================
set "DUPLICATE_MARK=**"
if /i "!VCS_TYPE!"=="Git" (
set "STATUS_DESC=Git: M=修改,A=新增,??=未跟踪"
) else (
set "STATUS_DESC=SVN: M=修改,A=新增,?=未跟踪"
)
set "name_counts=" :: 存储 "文件名:出现次数" 的列表
for /l %%i in (1,1,!FILE_COUNT!) do (
call set "full_path=%%FILE_REL_PATH[%%i]%%"
for %%f in ("!full_path!") do set "file_name=%%~nxf" :: 提取文件名
set "found=0"
set "new_counts="
for %%c in (!name_counts!) do (
for /f "tokens=1,2 delims=:" %%n in ("%%c") do (
if "%%n"=="!file_name!" (
:: 已存在,次数+1
set /a new_count=%%o+1
set "new_counts=!new_counts! !file_name!:!new_count!"
set "found=1"
) else (
:: 不存在,保留原记录
set "new_counts=!new_counts! %%c"
)
)
)
if !found! equ 0 (
set "new_counts=!new_counts! !file_name!:1"
)
set "name_counts=!new_counts:~1,-1!"
)
for /l %%i in (1,1,!FILE_COUNT!) do (
call set "full_path=%%FILE_REL_PATH[%%i]%%"
for %%f in ("!full_path!") do set "file_name=%%~nxf"
set "is_duplicate=0"
for %%c in (!name_counts!) do (
for /f "tokens=1,2 delims=:" %%n in ("%%c") do (
if "%%n"=="!file_name!" if %%o geq 2 (
set "is_duplicate=1"
)
)
)
:: 保存标记结果
set "IS_DUPLICATE[%%i]=!is_duplicate!"
)
echo.
echo 本次修改的文件(!STATUS_DESC! **为重名文件):
echo ----------------------------------------------------------
for /l %%i in (1,1,!FILE_COUNT!) do (
call set "STATUS=%%FILE_STATUS[%%i]%%"
call set "REL_PATH=%%FILE_REL_PATH[%%i]%%"
call set "is_duplicate=%%IS_DUPLICATE[%%i]%%"
if "!is_duplicate!"=="1" (
echo %%i. [!STATUS!] !DUPLICATE_MARK! 路径: !REL_PATH!
) else (
echo %%i. [!STATUS!] 路径: !REL_PATH!
)
)
echo ----------------------------------------------------------
echo.
:: ========================= 第六步:自动暂存所有修改 =========================
echo 正在自动暂存所有修改... >> "!CRASH_LOG!" 2>&1
if /i "!VCS_TYPE!"=="Git" (
git add . 2>> "!CRASH_LOG!"
if !errorlevel! equ 0 (
echo Git自动暂存完成
) else (
echo Git暂存警告:部分文件可能未暂存(详见崩溃日志)
ping -n 2 127.0.0.1 >nul 2>&1
)
) else (
for /l %%i in (1,1,!FILE_COUNT!) do (
call set "STATUS=%%FILE_STATUS[%%i]%%"
call set "FULL_PATH=%%FILE_FULL_PATH[%%i]%%"
if "!STATUS!"=="A" (
svn add "!FULL_PATH!" 2>> "!CRASH_LOG!"
ping -n 1 127.0.0.1 >nul 2>&1
)
)
echo SVN自动暂存完成
)
echo 暂存操作结束 >> "!CRASH_LOG!" 2>&1
:: ========================= 第七步:确认提交文件 =========================
echo.
echo ====================== 确认提交文件 ======================
echo 请确认以下文件是否需要提交(输入 Y 提交,N 跳过,直接回车默认提交)
echo ----------------------------------------------------------
set "current_file=1"
:file_loop
if !current_file! gtr !FILE_COUNT! goto end_file_loop
call set "CUR_STATUS=%%FILE_STATUS[!current_file!]%%"
call set "CUR_REL_PATH=%%FILE_REL_PATH[!current_file!]%%"
call set "CUR_NAME=%%FILE_LIST[!current_file!]%%"
:confirm_retry
set "USER_CHOICE="
call set /p "USER_CHOICE=!current_file!. [%%CUR_STATUS%%] %%CUR_REL_PATH%% 是否提交?(Y/N/回车默认Y): "
if "!USER_CHOICE!"=="" set "USER_CHOICE=Y"
if /i "!USER_CHOICE!" neq "Y" if /i "!USER_CHOICE!" neq "N" (
echo 输入错误!仅支持 Y(提交)、N(跳过)或直接回车(默认提交),请重新输入。
goto confirm_retry
)
if /i "!USER_CHOICE!"=="Y" (
set /a SELECTED_COUNT+=1
call set "SELECTED_PATH[!SELECTED_COUNT!]=%%CUR_REL_PATH%%"
call set "SELECTED_NAME[!SELECTED_COUNT!]=%%CUR_NAME%%"
call set "SELECTED_STATUS[!SELECTED_COUNT!]=%%CUR_STATUS%%"
) else (
echo 用户选择跳过:!CUR_REL_PATH! >> "!CRASH_LOG!" 2>&1
)
set /a current_file+=1
goto file_loop
:end_file_loop
if !SELECTED_COUNT! equ 0 (
echo.
echo 未选择任何文件提交,即将退出工具...
echo 未选中任何提交文件,工具退出 >> "!CRASH_LOG!" 2>&1
del "%COMMIT_MSG_FILE%" >nul 2>&1
for /l %%s in (3,-1,1) do (
echo 倒计时 %%s 秒...
call :accurate_delay 1000
)
del "!CRASH_LOG!" >nul 2>&1
exit /b 0
)
echo.
echo ----------------------------------------------------------
echo 本次确认提交的文件(共 !SELECTED_COUNT! 个):
for /l %%i in (1,1,!SELECTED_COUNT!) do (
echo %%i. [!SELECTED_STATUS[%%i]!] !SELECTED_PATH[%%i]!
)
echo ----------------------------------------------------------
echo 选中!SELECTED_COUNT!个文件待提交 >> "!CRASH_LOG!" 2>&1
:: ========================= 第八步:提交信息输入 =========================
:type_input
echo 第一项(类型)可选:feat(新功能开发),fix(问题修复),docs(文档变更),style(代码格式调整),refactor(代码重构),perf(优化性能),init(初次提交),safety(安规变更),tag(归档软件),branch(创建分支)
set "COMMIT_TYPE_INPUT="
set /p "COMMIT_TYPE_INPUT=请输入提交类型(例:feat): "
set "temp_type=!COMMIT_TYPE_INPUT: =!"
if "!temp_type!"=="" (
echo 提交类型不能为空,请重新输入!
goto type_input
)
set "valid_types=feat fix docs style refactor perf init safety tag branch test"
set "is_valid=0"
for %%t in (!valid_types!) do (
if /i "!temp_type!"=="%%t" set "is_valid=1"
)
if "!is_valid!"=="0" (
echo 提交类型无效,请从可选项中选择!
goto type_input
)
echo 提交类型:!COMMIT_TYPE_INPUT! >> "!CRASH_LOG!" 2>&1
:module_input
echo 第二项(模块)可选:ARM(ARM软件),DSP(DSP软件),BAT(电池软件),HMI(显示软件),AFCI(拉弧软件),BI(BI盒软件),PID(PID软件)
set "COMMIT_MODULE_INPUT="
set /p "COMMIT_MODULE_INPUT=请输入所属模块(不区分大小写. 例:ARM): "
set "temp_module=!COMMIT_MODULE_INPUT: =!"
if "!temp_module!"=="" (
echo 所属模块不能为空,请重新输入!
goto module_input
)
set "valid_modules=ARM DSP BAT HMI AFCI BI PID"
set "is_valid=0"
for %%m in (!valid_modules!) do (
if /i "!temp_module!"=="%%m" set "is_valid=1"
)
if "!is_valid!"=="0" (
echo 所属模块无效,请从可选项中选择!
goto module_input
)
echo 提交模块:!COMMIT_MODULE_INPUT! >> "!CRASH_LOG!" 2>&1
:desc_input
echo 请选择提交模式:
echo 1. 默认提交(需填写修改描述,任意输入或回车默认此项)
echo 2. 跳过流程提交(初次提交或无内容,填充为无描述,跳过后续输入)
set "commit_mode="
set /p "commit_mode=请选择(1/2):"
if "!commit_mode!"=="" set "commit_mode=1"
if "!commit_mode!"=="2" (
set "COMMIT_DESC_INPUT=本次为初次/省略上传提交文件"
echo 已自动填充提交描述 >> "!CRASH_LOG!" 2>&1
) else (
set "COMMIT_DESC_INPUT="
set /p "COMMIT_DESC_INPUT=请输入提交修改描述概要(至少10个字符.例:本次对主程序关键功能进行完善。): "
set "temp_desc=!COMMIT_DESC_INPUT: =!"
if "!temp_desc!"=="" (
echo 提交描述不能为空,请重新输入!
goto desc_input
)
if "!temp_desc:~10!"=="" (
echo 提交描述长度不足10个字符,请重新输入!
goto desc_input
)
)
echo 提交描述:!COMMIT_DESC_INPUT! >> "!CRASH_LOG!" 2>&1
set "COMMIT_TITLE=[!COMMIT_TYPE_INPUT!][!COMMIT_MODULE_INPUT!]: !COMMIT_DESC_INPUT!"
powershell -Command "$text = '!COMMIT_TITLE!'; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
echo 提交标题写入完成 >> "!CRASH_LOG!" 2>&1
if "!commit_mode!"=="2" (
set "TASK_ID_INPUT=req-0"
set "TASK_ID=!DEFAULT_TASKID_PREFIX!!TASK_ID_INPUT!"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n!TASK_ID!\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Description:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
for /l %%i in (1,1,!SELECTED_COUNT!) do (
set "REL_PATH=!SELECTED_PATH[%%i]!"
for %%f in ("!REL_PATH!") do set "PURE_FILENAME=%%~nxf"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n-%%i#.!PURE_FILENAME!:无描述\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
)
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Test Suggestions:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n- 无\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Self Testing Items:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n- 无\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
goto call_tortoise
)
:taskid_input
set "TASK_ID_INPUT="
set /p "TASK_ID_INPUT=请输入TaskID内容(统一对象为禅道号,前缀:%DEFAULT_TASKID_PREFIX%,需以bug或req开头.例:req-1,直接回车默认req-0): "
if "!TASK_ID_INPUT!"=="" (
echo 未输入TaskID,已自动填充默认值:req-0
set "TASK_ID_INPUT=req-0"
) else (
set "temp_taskid=!TASK_ID_INPUT!"
for /f "delims=" %%i in ('powershell -Command "$input.ToLower()" ^<nul ^& echo !temp_taskid!') do set "temp_taskid_lower=%%i"
if "!temp_taskid_lower:~0,3!" neq "bug" if "!temp_taskid_lower:~0,3!" neq "req" (
echo TaskID不符合规范,请重新输入!
goto taskid_input
)
)
set "TASK_ID=!DEFAULT_TASKID_PREFIX!!TASK_ID_INPUT!"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n!TASK_ID!\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Description:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
for /l %%i in (1,1,!SELECTED_COUNT!) do (
set "REL_PATH=!SELECTED_PATH[%%i]!"
set "DESC_TEMP_FILE=%temp%\desc_%%i.tmp"
del "!DESC_TEMP_FILE!" >nul 2>&1
echo 请输入对 !REL_PATH! 的描述(分段式输入,空行回车结束输入,例:修改该文件的xx接口功能)
call :read_robust_segment "!DESC_TEMP_FILE!"
if exist "!DESC_TEMP_FILE!" (
for %%f in ("!REL_PATH!") do set "PURE_FILENAME=%%~nxf"
powershell -Command "$content = (Get-Content '!DESC_TEMP_FILE!' -Raw) -replace '[\r\n\s]+', ''; $text = Get-Content '!COMMIT_MSG_FILE!' -Raw; $text += \"`r`n-%%i#.!PURE_FILENAME!:$content\"; Set-Content '!COMMIT_MSG_FILE!' -Value $text -Encoding UTF8"
del "!DESC_TEMP_FILE!" >nul 2>&1
) else (
for %%f in ("!REL_PATH!") do set "PURE_FILENAME=%%~nxf"
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n-%%i#.!PURE_FILENAME!:无描述\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
)
)
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Test Suggestions:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
set "TEST_SUGGESTION_TEMP=%temp%\test_suggestion.tmp"
del "!TEST_SUGGESTION_TEMP!" >nul 2>&1
echo 请输入测试建议(非必填,可直接回车跳过,分段式输入,空行回车结束输入)
call :read_robust_segment "!TEST_SUGGESTION_TEMP!"
if exist "!TEST_SUGGESTION_TEMP!" (
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $desc = [System.IO.File]::ReadAllText('!TEST_SUGGESTION_TEMP!', [System.Text.Encoding]::Default); $lines = $desc -split \"`r`n\"; foreach ($line in $lines) { if ($line -ne \"\") { $text += \"`r`n- $line\" } }; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
del "!TEST_SUGGESTION_TEMP!" >nul 2>&1
) else (
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n- 无\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
)
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n#Self Testing Items:\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
set "SELF_TEST_TEMP=%temp%\self_test.tmp"
del "!SELF_TEST_TEMP!" >nul 2>&1
echo 请输入自测项目(非必填,可直接回车跳过,分段式输入,空行回车结束输入)
call :read_robust_segment "!SELF_TEST_TEMP!"
if exist "!SELF_TEST_TEMP!" (
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $desc = [System.IO.File]::ReadAllText('!SELF_TEST_TEMP!', [System.Text.Encoding]::Default); $lines = $desc -split \"`r`n\"; foreach ($line in $lines) { if ($line -ne \"\") { $text += \"`r`n- $line\" } }; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
del "!SELF_TEST_TEMP!" >nul 2>&1
) else (
powershell -Command "$text = [System.IO.File]::ReadAllText('!COMMIT_MSG_FILE!', [System.Text.Encoding]::UTF8); $text += \"`r`n- 无\"; [System.IO.File]::WriteAllText('!COMMIT_MSG_FILE!', $text, [System.Text.Encoding]::UTF8)"
)
:call_tortoise
:: ========================= 第九步:调用Tortoise工具 =========================
if /i "!VCS_TYPE!"=="Git" (
set "TORTOISE_EXE=TortoiseGitProc.exe"
set "TORTOISE_NAME=TortoiseGit"
set "PATH_CACHE_FILE=%temp%\vcs_tortoise_path_git.txt"
) else (
set "TORTOISE_EXE=TortoiseProc.exe"
set "TORTOISE_NAME=TortoiseSVN"
set "PATH_CACHE_FILE=%temp%\vcs_tortoise_path_svn.txt"
)
set "TORTOISE_PATH="
if exist "!PATH_CACHE_FILE!" (
set /p "TORTOISE_PATH_CACHED=" < "!PATH_CACHE_FILE!"
if exist "!TORTOISE_PATH_CACHED!" (
set "TORTOISE_PATH=!TORTOISE_PATH_CACHED!"
echo 使用上次记录的 !TORTOISE_NAME! 路径: !TORTOISE_PATH!
)
)
if not exist "!TORTOISE_PATH!" (
if /i "!VCS_TYPE!"=="Git" (
set "REG_KEY=HKLM\SOFTWARE\TortoiseGit"
) else (
set "REG_KEY=HKLM\SOFTWARE\TortoiseSVN"
)
for /f "tokens=2* skip=2" %%a in ('reg query "!REG_KEY!" /v "InstallPath" 2^>nul') do (
set "TORTOISE_PATH=%%b\bin\!TORTOISE_EXE!"
)
if not exist "!TORTOISE_PATH!" (
if /i "!VCS_TYPE!"=="Git" (
set "REG_KEY=HKLM\SOFTWARE\Wow6432Node\TortoiseGit"
) else (
set "REG_KEY=HKLM\SOFTWARE\Wow6432Node\TortoiseSVN"
)
for /f "tokens=2* skip=2" %%a in ('reg query "!REG_KEY!" /v "InstallPath" 2^>nul') do (
set "TORTOISE_PATH=%%b\bin\!TORTOISE_EXE!"
)
)
if not exist "!TORTOISE_PATH!" (
if /i "!VCS_TYPE!"=="Git" (
set "TORTOISE_PATH=C:\Program Files\TortoiseGit\bin\!TORTOISE_EXE!"
if not exist "!TORTOISE_PATH!" (
set "TORTOISE_PATH=C:\Program Files (x86)\TortoiseGit\bin\!TORTOISE_EXE!"
)
) else (
set "TORTOISE_PATH=C:\Program Files\TortoiseSVN\bin\!TORTOISE_EXE!"
if not exist "!TORTOISE_PATH!" (
set "TORTOISE_PATH=C:\Program Files (x86)\TortoiseSVN\bin\!TORTOISE_EXE!"
)
)
)
)
:path_input_loop
if not exist "!TORTOISE_PATH!" (
echo.
echo 提示:未找到 !TORTOISE_NAME! 安装路径
if exist "!PATH_CACHE_FILE!" (
echo 上次记录的路径已失效: !TORTOISE_PATH_CACHED!
)
echo 请输入 !TORTOISE_EXE! 的完整路径(示例):
if /i "!VCS_TYPE!"=="Git" (
echo C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe
) else (
echo C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe
)
set "user_input_path="
set /p "user_input_path=请输入路径:"
if "!user_input_path!"=="" (
echo 错误:路径不能为空,请重新输入!
set "TORTOISE_PATH="
goto path_input_loop
)
if not exist "!user_input_path!" (
echo 错误:路径不存在,请检查后重新输入!
set "TORTOISE_PATH="
goto path_input_loop
)
set "TORTOISE_PATH=!user_input_path!"
echo !TORTOISE_PATH! > "!PATH_CACHE_FILE!"
echo 已保存 !TORTOISE_NAME! 路径到缓存文件
)
if not exist "!PATH_CACHE_FILE!" (
echo !TORTOISE_PATH! > "!PATH_CACHE_FILE!"
echo 已自动保存 !TORTOISE_NAME! 路径到缓存文件
)
:commit_attempt
echo 正在打开 !TORTOISE_NAME! 提交界面...
start /wait "" "!TORTOISE_PATH!" /command:commit /path:. /logmsgfile:"%COMMIT_MSG_FILE%"
:: 检查提交结果并询问是否重试
echo.
echo ==============================================================
echo 检测到提交界面已关闭
echo 1. 不需要重新上传(直接回车默认此项)
echo 2. 需要重新上传(再次打开提交界面)
echo ==============================================================
set "retry_choice="
set /p "retry_choice=请选择操作:"
if "!retry_choice!"=="" set "retry_choice=1"
if "!retry_choice!"=="2" (
echo 用户选择重新上传 >> "!CRASH_LOG!" 2>&1
goto commit_attempt
) else (
echo 用户选择不重新上传 >> "!CRASH_LOG!" 2>&1
)
:: ========================= 清理并退出 =========================
del "%COMMIT_MSG_FILE%" >nul 2>&1
echo.
echo ==============================================================
echo 操作完成,即将关闭程序...
echo ==============================================================
for /l %%s in (5,-1,1) do (
echo 倒计时 %%s 秒...
call :accurate_delay 1000
)
endlocal
exit /b 0
:: ========================= 子程序 =========================
:accurate_delay
setlocal
set "ms=%1"
powershell -Command "$sw = [System.Diagnostics.Stopwatch]::StartNew(); while ($sw.ElapsedMilliseconds -lt %ms%) {}; $sw.Stop()" >nul 2>&1
endlocal
exit /b 0
:read_robust_segment
set "output_file=%~1"
del "!output_file!" >nul 2>&1
set "segment_count=0"
:robust_segment_loop
set /a segment_count+=1
set "input_line="
set /p "input_line=第!segment_count!段: "
if "!input_line!"=="" goto end_robust_segment
if "!input_line!" neq "" (
if not exist "!output_file!" (
echo !input_line! > "!output_file!"
) else (
echo !input_line! >> "!output_file!"
)
)
goto robust_segment_loop
:end_robust_segment
exit /b
:clean_gitignore_duplicates
:: 清理.gitignore中的重复行(保留顺序)
if not exist ".gitignore" exit /b 0
set "temp_ignore=%temp%\gitignore_clean.tmp"
powershell -Command "$content = Get-Content '.gitignore' | Where-Object { $_ -notmatch '^\s*$' }; $unique = @(); foreach ($line in $content) { if ($unique -notcontains $line) { $unique += $line } }; $unique | Set-Content '%temp_ignore%' -Encoding default" >nul 2>&1
move /y "%temp_ignore%" ".gitignore" >nul 2>&1
exit /b 0
:process_file
set "status=%~1"
set "file_path=%~2"
if "!file_path!"=="" exit /b
set "trimmed_path=!file_path!"
:trim_left
if "!trimmed_path:~0,1!"==" " set "trimmed_path=!trimmed_path:~1!" & goto trim_left
:trim_right
if "!trimmed_path:~-1!"==" " set "trimmed_path=!trimmed_path:~0,-1!" & goto trim_right
if "!trimmed_path:~-1!"=="\" exit /b
if exist "!trimmed_path!\" exit /b
echo "!trimmed_path!" | findstr /i /r /c:"\\.svn\\" /c:"/.svn/" /c:"^.svn" >nul 2>&1
if !errorlevel! equ 0 (
echo 排除.svn相关文件:!trimmed_path! >> "!CRASH_LOG!" 2>&1
exit /b
)
set "should_exclude=0"
for %%f in (%EXCLUDE_FILES%) do (
if /i "!trimmed_path!"=="%%f" (
set "should_exclude=1"
echo 排除文件:!trimmed_path! >> "!CRASH_LOG!" 2>&1
)
)
if "!should_exclude!"=="1" exit /b
if "!status!"=="D" (
echo 跳过删除的文件:!trimmed_path! >> "!CRASH_LOG!" 2>&1
exit /b
)
if /i "!VCS_TYPE!"=="SVN" (
if "!status!"=="?" set "status=A"
)
set /a FILE_COUNT+=1
set "FILE_REL_PATH[!FILE_COUNT!]=!trimmed_path!"
set "FILE_LIST[!FILE_COUNT!]=!trimmed_path!"
set "FILE_STATUS[!FILE_COUNT!]=!status!"
for %%p in ("!trimmed_path!") do (
if "%%~dp"=="" (
set "FILE_FULL_PATH[!FILE_COUNT!]=%cd%\%%~p"
) else (
set "FILE_FULL_PATH[!FILE_COUNT!]=%%~fp"
)
)
echo 处理文件 [!FILE_COUNT!]: [!status!] !trimmed_path! >> "!CRASH_LOG!" 2>&1
exit /b 0我现在这个程序如果运行在SVN环境中,不能做到同git部分屏蔽文件夹名来跳过扫描整个文件夹及其子目录的功能,是否是因为SVN部分屏蔽所需条件不同,如果被SVN追踪的文件是否也会导致哪怕屏蔽名输入也被全部扫描到,我希望你实现和git完全相同的功能,采取针对SVN环境的实现方式,做到能通过输入文件夹名字来在扫描文件阶段直接跳过整个文件夹
最新发布