调协字符编码

This commit is contained in:
Jeff
2026-05-19 15:38:12 +08:00
parent abcbc88399
commit b2b508f520
3 changed files with 202 additions and 202 deletions

View File

@@ -1,4 +1,4 @@
// GitVer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // GitVer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// //
#include "pch.h" #include "pch.h"
@@ -18,7 +18,7 @@
#define new DEBUG_NEW #define new DEBUG_NEW
#endif #endif
// 唯一的应用程序对象 // 唯一的应用程序对象
CWinApp theApp; CWinApp theApp;
@@ -41,10 +41,10 @@ const UINT DEFAULT_MINOR_WHEN_NO_TAG = 0;
int HandleSetVerCommand(int argc, TCHAR* argv[]); int HandleSetVerCommand(int argc, TCHAR* argv[]);
/// <summary> /// <summary>
/// 将宽字符字符串转换为ANSI字符串。 /// 将宽字符字符串转换为ANSI字符串。
/// </summary> /// </summary>
/// <param name="lpText">要转换的宽字符字符串。</param> /// <param name="lpText">要转换的宽字符字符串。</param>
/// <returns>转换后的ANSI字符串。</returns> /// <returns>转换后的ANSI字符串。</returns>
std::string ToAnsiString(LPCTSTR lpText) std::string ToAnsiString(LPCTSTR lpText)
{ {
if (lpText == NULL) if (lpText == NULL)
@@ -69,11 +69,11 @@ std::string ToAnsiString(LPCTSTR lpText)
} }
/// <summary> /// <summary>
/// 检查指定目录下是否存在与模式匹配的文件。 /// 检查指定目录下是否存在与模式匹配的文件。
/// </summary> /// </summary>
/// <param name="lpBaseDir">要搜索的基目录。</param> /// <param name="lpBaseDir">要搜索的基目录。</param>
/// <param name="lpPattern">要匹配的文件模式。</param> /// <param name="lpPattern">要匹配的文件模式。</param>
/// <returns>如果存在匹配的文件则返回TRUE否则返回FALSE。</returns> /// <returns>如果存在匹配的文件则返回TRUE否则返回FALSE。</returns>
BOOL HasMatchingFile(LPCTSTR lpBaseDir, LPCTSTR lpPattern) BOOL HasMatchingFile(LPCTSTR lpBaseDir, LPCTSTR lpPattern)
{ {
CString strSearchPath; CString strSearchPath;
@@ -91,12 +91,12 @@ BOOL HasMatchingFile(LPCTSTR lpBaseDir, LPCTSTR lpPattern)
} }
/// <summary> /// <summary>
/// 递归查找与模式匹配的第一个文件。 /// 递归查找与模式匹配的第一个文件。
/// </summary> /// </summary>
/// <param name="lpBaseDir">要搜索的基目录。</param> /// <param name="lpBaseDir">要搜索的基目录。</param>
/// <param name="lpPattern">要匹配的文件模式。</param> /// <param name="lpPattern">要匹配的文件模式。</param>
/// <param name="strFoundPath">找到的文件的完整路径。</param> /// <param name="strFoundPath">找到的文件的完整路径。</param>
/// <returns>如果找到匹配的文件则返回TRUE否则返回FALSE。</returns> /// <returns>如果找到匹配的文件则返回TRUE否则返回FALSE。</returns>
BOOL FindFirstFileByPatternRecursive(LPCTSTR lpBaseDir, LPCTSTR lpPattern, CString& strFoundPath) BOOL FindFirstFileByPatternRecursive(LPCTSTR lpBaseDir, LPCTSTR lpPattern, CString& strFoundPath)
{ {
strFoundPath.Empty(); strFoundPath.Empty();
@@ -155,12 +155,12 @@ BOOL FindFirstFileByPatternRecursive(LPCTSTR lpBaseDir, LPCTSTR lpPattern, CStri
} }
/// <summary> /// <summary>
/// 构建相对于仓库的路径。 /// 构建相对于仓库的路径。
/// </summary> /// </summary>
/// <param name="lpBaseDir">基目录。</param> /// <param name="lpBaseDir">基目录。</param>
/// <param name="lpFullPath">完整路径。</param> /// <param name="lpFullPath">完整路径。</param>
/// <param name="strRelativePath">相对路径。</param> /// <param name="strRelativePath">相对路径。</param>
/// <returns>如果成功构建相对路径则返回TRUE否则返回FALSE。</returns> /// <returns>如果成功构建相对路径则返回TRUE否则返回FALSE。</returns>
BOOL BuildRepoRelativePath(LPCTSTR lpBaseDir, LPCTSTR lpFullPath, CString& strRelativePath) BOOL BuildRepoRelativePath(LPCTSTR lpBaseDir, LPCTSTR lpFullPath, CString& strRelativePath)
{ {
strRelativePath.Empty(); strRelativePath.Empty();
@@ -196,10 +196,10 @@ BOOL BuildRepoRelativePath(LPCTSTR lpBaseDir, LPCTSTR lpFullPath, CString& strRe
} }
/// <summary> /// <summary>
/// 获取文件名(不包含扩展名)。 /// 获取文件名(不包含扩展名)。
/// </summary> /// </summary>
/// <param name="lpFilePath">文件路径。</param> /// <param name="lpFilePath">文件路径。</param>
/// <returns>不包含扩展名的文件名。</returns> /// <returns>不包含扩展名的文件名。</returns>
CString GetFileNameWithoutExtension(LPCTSTR lpFilePath) CString GetFileNameWithoutExtension(LPCTSTR lpFilePath)
{ {
if (lpFilePath == NULL) if (lpFilePath == NULL)
@@ -218,11 +218,11 @@ CString GetFileNameWithoutExtension(LPCTSTR lpFilePath)
} }
/// <summary> /// <summary>
/// 查找首选的C++资源文件(.rc /// 查找首选的C++资源文件(.rc
/// </summary> /// </summary>
/// <param name="lpBaseDir">要搜索的基目录。</param> /// <param name="lpBaseDir">要搜索的基目录。</param>
/// <param name="strResFile">找到的资源文件的完整路径。</param> /// <param name="strResFile">找到的资源文件的完整路径。</param>
/// <returns>如果找到首选的资源文件则返回TRUE否则返回FALSE。</returns> /// <returns>如果找到首选的资源文件则返回TRUE否则返回FALSE。</returns>
BOOL FindPreferredCppRcFileAt(LPCTSTR lpBaseDir, CString& strResFile) BOOL FindPreferredCppRcFileAt(LPCTSTR lpBaseDir, CString& strResFile)
{ {
strResFile.Empty(); strResFile.Empty();
@@ -260,11 +260,11 @@ BOOL FindPreferredCppRcFileAt(LPCTSTR lpBaseDir, CString& strResFile)
} }
/// <summary> /// <summary>
/// 查找首选的AssemblyInfo.cs文件。 /// 查找首选的AssemblyInfo.cs文件。
/// </summary> /// </summary>
/// <param name="lpBaseDir">要搜索的基目录。</param> /// <param name="lpBaseDir">要搜索的基目录。</param>
/// <param name="strResFile">找到的AssemblyInfo.cs文件的完整路径。</param> /// <param name="strResFile">找到的AssemblyInfo.cs文件的完整路径。</param>
/// <returns>如果找到首选的AssemblyInfo.cs文件则返回TRUE否则返回FALSE。</returns> /// <returns>如果找到首选的AssemblyInfo.cs文件则返回TRUE否则返回FALSE。</returns>
BOOL FindPreferredAssemblyInfoFileAt(LPCTSTR lpBaseDir, CString& strResFile) BOOL FindPreferredAssemblyInfoFileAt(LPCTSTR lpBaseDir, CString& strResFile)
{ {
strResFile.Empty(); strResFile.Empty();
@@ -290,13 +290,13 @@ BOOL FindPreferredAssemblyInfoFileAt(LPCTSTR lpBaseDir, CString& strResFile)
} }
/// <summary> /// <summary>
/// 检测项目的源码类型。 /// 检测项目的源码类型。
/// </summary> /// </summary>
/// <param name="lpBaseDir">要检测的基目录。</param> /// <param name="lpBaseDir">要检测的基目录。</param>
/// <returns>返回项目的源码类型枚举值。</returns> /// <returns>返回项目的源码类型枚举值。</returns>
int DetectProjectCodeType(LPCTSTR lpBaseDir) int DetectProjectCodeType(LPCTSTR lpBaseDir)
{ {
_tprintf(_T("检测项目源码类型:%s\n"), lpBaseDir); _tprintf(_T("检测项目源码类型:%s\n"), lpBaseDir);
if (PathFileExists(CString(lpBaseDir) + _T("\\Properties\\AssemblyInfo.cs")) if (PathFileExists(CString(lpBaseDir) + _T("\\Properties\\AssemblyInfo.cs"))
|| HasMatchingFile(lpBaseDir, _T("*.csproj")) || HasMatchingFile(lpBaseDir, _T("*.csproj"))
|| HasMatchingFile(lpBaseDir, _T("*.cs"))) || HasMatchingFile(lpBaseDir, _T("*.cs")))
@@ -326,10 +326,10 @@ int DetectProjectCodeType(LPCTSTR lpBaseDir)
} }
/// <summary> /// <summary>
/// 获取项目源码类型的名称。 /// 获取项目源码类型的名称。
/// </summary> /// </summary>
/// <param name="nCodeType">项目源码类型枚举值。</param> /// <param name="nCodeType">项目源码类型枚举值。</param>
/// <returns>项目源码类型的名称。</returns> /// <returns>项目源码类型的名称。</returns>
LPCTSTR GetProjectCodeTypeName(int nCodeType) LPCTSTR GetProjectCodeTypeName(int nCodeType)
{ {
switch (nCodeType) switch (nCodeType)
@@ -346,21 +346,21 @@ LPCTSTR GetProjectCodeTypeName(int nCodeType)
} }
/// <summary> /// <summary>
/// 打印完整的使用示例。 /// 打印完整的使用示例。
/// </summary> /// </summary>
void PrintFullUsageExamples() void PrintFullUsageExamples()
{ {
LPCTSTR lpUsageText = LPCTSTR lpUsageText =
_T("用法:\n") _T("用法:\n")
_T(" gitver (显示帮助后进入当前分支创建 tag 流程)\n") _T(" gitver (显示帮助后进入当前分支创建 tag 流程)\n")
_T(" gitver rewrite [PEType可选] [-f可选]\n") _T(" gitver rewrite [PEType可选] [-f可选]\n")
_T(" gitver setver=<pid> [repodir=<path>可选] [-test可选]\n") _T(" gitver setver=<pid> [repodir=<path>可选] [-test可选]\n")
_T(" gitver nuitkabuild=<pid> <mainPy> [repodir=<path>可选] [-test可选] [params=\"<nuitka参数>\"可选]\n") _T(" gitver nuitkabuild=<pid> <mainPy> [repodir=<path>可选] [-test可选] [params=\"<nuitka参数>\"可选]\n")
_T(" gitver nuitkapydbuild=<pid> <modulePy> [repodir=<path>可选] [-test可选] [params=\"<nuitka参数>\"可选]\n") _T(" gitver nuitkapydbuild=<pid> <modulePy> [repodir=<path>可选] [-test可选] [params=\"<nuitka参数>\"可选]\n")
_T(" gitver -setup=0|1 [pid] [repodir=<path>可选] [-test可选]\n") _T(" gitver -setup=0|1 [pid] [repodir=<path>可选] [-test可选]\n")
_T(" -setup=0: 使用 Inno Setup 脚本 (setup.iss)\n") _T(" -setup=0: 使用 Inno Setup 脚本 (setup.iss)\n")
_T(" -setup=1: 使用 NSIS 脚本 (setup.nsh)\n") _T(" -setup=1: 使用 NSIS 脚本 (setup.nsh)\n")
_T("\n示例:\n") _T("\n示例:\n")
_T(" gitver\n") _T(" gitver\n")
_T(" gitver rewrite\n") _T(" gitver rewrite\n")
_T(" gitver rewrite 2\n") _T(" gitver rewrite 2\n")
@@ -376,48 +376,48 @@ void PrintFullUsageExamples()
_T(" gitver nuitkapydbuild=5 src\\core.py repodir=E:\\Code\\MyPyProj params=\"--output-dir=dist\"\n") _T(" gitver nuitkapydbuild=5 src\\core.py repodir=E:\\Code\\MyPyProj params=\"--output-dir=dist\"\n")
_T(" gitver -setup=0 5\n") _T(" gitver -setup=0 5\n")
_T(" gitver -setup=1 5 repodir=E:\\Code\\MyProj\n") _T(" gitver -setup=1 5 repodir=E:\\Code\\MyProj\n")
_T("params: 传递给 Nuitka 的额外参数,用双引号括起来,如 params=\"--standalone --output-dir=dist\"\n") _T("params: 传递给 Nuitka 的额外参数,用双引号括起来,如 params=\"--standalone --output-dir=dist\"\n")
_T("-test: 将产品版本号的 major 和 minor 都置为 0用于测试版本构建\n") _T("-test: 将产品版本号的 major 和 minor 都置为 0用于测试版本构建\n")
_T("无参数时会读取当前分支最近三次 tag并提示选择 major 加 1 或 minor 加 1然后创建新 tag。\n") _T("无参数时会读取当前分支最近三次 tag并提示选择 major 加 1 或 minor 加 1然后创建新 tag。\n")
_T("未找到当前分支 tag 时自动使用默认版本 1.0。\n"); _T("未找到当前分支 tag 时自动使用默认版本 1.0。\n");
_tprintf(_T("%s"), lpUsageText); _tprintf(_T("%s"), lpUsageText);
} }
/// <summary> /// <summary>
/// 打印命令简要用法(用于未知命令等场景)。 /// 打印命令简要用法(用于未知命令等场景)。
/// </summary> /// </summary>
void PrintShortCommandUsage() void PrintShortCommandUsage()
{ {
_tprintf(_T("请使用gitver rewrite [PE类型可选]\n")); _tprintf(_T("请使用gitver rewrite [PE类型可选]\n"));
_tprintf(_T("请使用gitver setver=<pid> [repodir=<path>可选]\n")); _tprintf(_T("请使用gitver setver=<pid> [repodir=<path>可选]\n"));
_tprintf(_T("gitver nuitkabuild=<pid> <mainPy> [repodir=<path>可选] [params=\"<nuitka参数>\"可选]\n")); _tprintf(_T("gitver nuitkabuild=<pid> <mainPy> [repodir=<path>可选] [params=\"<nuitka参数>\"可选]\n"));
_tprintf(_T("gitver nuitkapydbuild=<pid> <modulePy> [repodir=<path>可选] [params=\"<nuitka参数>\"可选]\n")); _tprintf(_T("gitver nuitkapydbuild=<pid> <modulePy> [repodir=<path>可选] [params=\"<nuitka参数>\"可选]\n"));
} }
/// <summary> /// <summary>
/// 打印命令参数不足时的标准用法与示例。 /// 打印命令参数不足时的标准用法与示例。
/// </summary> /// </summary>
/// <param name="lpCommandName">命令名称。</param> /// <param name="lpCommandName">命令名称。</param>
/// <param name="lpRequiredArgs">必选参数占位文本。</param> /// <param name="lpRequiredArgs">必选参数占位文本。</param>
/// <param name="lpExampleRequiredArgs">示例中的必选参数。</param> /// <param name="lpExampleRequiredArgs">示例中的必选参数。</param>
void PrintCommandUsageAndExamples(LPCTSTR lpCommandName, LPCTSTR lpRequiredArgs, LPCTSTR lpExampleRequiredArgs) void PrintCommandUsageAndExamples(LPCTSTR lpCommandName, LPCTSTR lpRequiredArgs, LPCTSTR lpExampleRequiredArgs)
{ {
_tprintf(_T("用法gitver %s %s [repodir=<path>可选]\n"), lpCommandName, lpRequiredArgs); _tprintf(_T("用法gitver %s %s [repodir=<path>可选]\n"), lpCommandName, lpRequiredArgs);
if (lpExampleRequiredArgs != NULL && _tcslen(lpExampleRequiredArgs) > 0) if (lpExampleRequiredArgs != NULL && _tcslen(lpExampleRequiredArgs) > 0)
{ {
_tprintf(_T("示例gitver %s 5 %s repodir=E:\\Code\\OTH\\gitver\n"), lpCommandName, lpExampleRequiredArgs); _tprintf(_T("示例gitver %s 5 %s repodir=E:\\Code\\OTH\\gitver\n"), lpCommandName, lpExampleRequiredArgs);
_tprintf(_T("示例gitver %s 5 %s\n"), lpCommandName, lpExampleRequiredArgs); _tprintf(_T("示例gitver %s 5 %s\n"), lpCommandName, lpExampleRequiredArgs);
} }
else else
{ {
_tprintf(_T("示例gitver %s 5 repodir=E:\\Code\\OTH\\gitver\n"), lpCommandName); _tprintf(_T("示例gitver %s 5 repodir=E:\\Code\\OTH\\gitver\n"), lpCommandName);
_tprintf(_T("示例gitver %s 5\n"), lpCommandName); _tprintf(_T("示例gitver %s 5\n"), lpCommandName);
} }
} }
/// <summary> /// <summary>
/// 获取退出码的简要说明。 /// 获取退出码的简要说明。
/// </summary> /// </summary>
LPCTSTR GetExitCodeHint(int nRetCode) LPCTSTR GetExitCodeHint(int nRetCode)
{ {
@@ -493,7 +493,7 @@ LPCTSTR GetExitCodeHint(int nRetCode)
} }
/// <summary> /// <summary>
/// 在命令执行返回非零时输出统一错误日志。 /// 在命令执行返回非零时输出统一错误日志。
/// </summary> /// </summary>
void PrintCommandFailedWithCode(LPCTSTR lpCommandName, int nRetCode) void PrintCommandFailedWithCode(LPCTSTR lpCommandName, int nRetCode)
{ {
@@ -512,18 +512,18 @@ void PrintCommandFailedWithCode(LPCTSTR lpCommandName, int nRetCode)
} }
/// <summary> /// <summary>
/// 输出命令执行结束日志(含耗时和退出码)。 /// 输出命令执行结束日志(含耗时和退出码)。
/// </summary> /// </summary>
void LogCommandEnd(LPCTSTR lpCommandName, DWORD dwStartTick, int nRetCode) void LogCommandEnd(LPCTSTR lpCommandName, DWORD dwStartTick, int nRetCode)
{ {
DWORD dwElapsed = GetTickCount() - dwStartTick; DWORD dwElapsed = GetTickCount() - dwStartTick;
_tprintf(_T("命令结束: %s耗时 %u ms退出码 %d\n"), lpCommandName, dwElapsed, nRetCode); _tprintf(_T("命令结束: %s耗时 %u ms退出码 %d\n"), lpCommandName, dwElapsed, nRetCode);
} }
/// <summary> /// <summary>
/// 获取当前模块的目录信息。 /// 获取当前模块的目录信息。
/// </summary> /// </summary>
/// <returns>返回值。</returns> /// <returns>返回值。</returns>
void GetDirInfo() void GetDirInfo()
{ {
TCHAR szDrive[_MAX_DRIVE] = { 0 }; TCHAR szDrive[_MAX_DRIVE] = { 0 };
@@ -563,19 +563,19 @@ void GetDirInfo()
} }
/// <summary> /// <summary>
/// 处理设置版本命令。 /// 处理设置版本命令。
/// </summary> /// </summary>
/// <param name="argc">参数个数。</param> /// <param name="argc">参数个数。</param>
/// <param name="argv">参数数组。</param> /// <param name="argv">参数数组。</param>
/// <returns>返回值。</returns> /// <returns>返回值。</returns>
int HandleSetVerCommand(int argc, TCHAR* argv[]) int HandleSetVerCommand(int argc, TCHAR* argv[])
{ {
// 解析 "setver=N" 中的 pid // 解析 "setver=N" 中的 pid
CString strPid = CString(argv[1]).Mid(7); // 跳过 "setver=" CString strPid = CString(argv[1]).Mid(7); // 跳过 "setver="
UINT nPid = 0; UINT nPid = 0;
if (strPid.IsEmpty() || !TryParseUInt16(strPid, nPid)) if (strPid.IsEmpty() || !TryParseUInt16(strPid, nPid))
{ {
_tprintf(_T("错误: setver= 后的 pid 无效:%s应为 0-65535 范围的整数。\n"), strPid.GetString()); _tprintf(_T("错误: setver= 后的 pid 无效:%s应为 0-65535 范围的整数。\n"), strPid.GetString());
return 4; return 4;
} }
@@ -611,13 +611,13 @@ int HandleSetVerCommand(int argc, TCHAR* argv[])
{ {
strProductVersion = strProductVersion.Left(nDot2 + 1) + _T("0.0"); strProductVersion = strProductVersion.Left(nDot2 + 1) + _T("0.0");
} }
_tprintf(_T("[test] 已将 major/minor 置零: ProductVersion=%s\n"), strProductVersion.GetString()); _tprintf(_T("[test] 已将 major/minor 置零: ProductVersion=%s\n"), strProductVersion.GetString());
} }
_tprintf(_T("ProductVersion=%s\n"), strProductVersion.GetString()); _tprintf(_T("ProductVersion=%s\n"), strProductVersion.GetString());
_tprintf(_T("FileVersion=%s\n"), strFileVersion.GetString()); _tprintf(_T("FileVersion=%s\n"), strFileVersion.GetString());
// 检查是否附带了 -setup=N 标志 // 检查是否附带了 -setup=N 标志
int nSetupType = -1; int nSetupType = -1;
for (int i = 2; i < argc; ++i) for (int i = 2; i < argc; ++i)
{ {
@@ -627,7 +627,7 @@ int HandleSetVerCommand(int argc, TCHAR* argv[])
UINT nVal = 0; UINT nVal = 0;
if (!TryParseUInt16(strArg.Mid(7), nVal) || (nVal != 0 && nVal != 1)) if (!TryParseUInt16(strArg.Mid(7), nVal) || (nVal != 0 && nVal != 1))
{ {
_tprintf(_T("错误: -setup 参数值 \"%s\" 不支持,仅支持 0Inno Setup或 1NSIS\n"), _tprintf(_T("错误: -setup 参数值 \"%s\" 不支持,仅支持 0Inno Setup或 1NSIS\n"),
strArg.Mid(7).GetString()); strArg.Mid(7).GetString());
return 36; return 36;
} }
@@ -638,7 +638,7 @@ int HandleSetVerCommand(int argc, TCHAR* argv[])
if (nSetupType >= 0) if (nSetupType >= 0)
{ {
// -setup=N 存在:不回写版本信息到项目文件,只修改安装脚本并编译 // -setup=N 存在:不回写版本信息到项目文件,只修改安装脚本并编译
if (!ExecuteSetupBuild(nSetupType, strProductVersion)) if (!ExecuteSetupBuild(nSetupType, strProductVersion))
{ {
return 38; return 38;
@@ -651,13 +651,13 @@ int HandleSetVerCommand(int argc, TCHAR* argv[])
/// <summary> /// <summary>
/// <summary> /// <summary>
/// 准备C++重写内容。 /// 准备C++重写内容。
/// </summary> /// </summary>
/// <param name="strCommitId">提交ID。</param> /// <param name="strCommitId">提交ID。</param>
/// <param name="nPEType">PE类型。</param> /// <param name="nPEType">PE类型。</param>
/// <param name="strResFile">资源文件路径。</param> /// <param name="strResFile">资源文件路径。</param>
/// <param name="vtOldContent">旧内容向量。</param> /// <param name="vtOldContent">旧内容向量。</param>
/// <param name="vtNewContent">新内容向量。</param> /// <param name="vtNewContent">新内容向量。</param>
/// </summary> /// </summary>
void PrepareCppRewriteContent(const CString& strCommitId, int nPEType, CString& strResFile, std::vector<std::string>& vtOldContent, std::vector<std::string>& vtNewContent) void PrepareCppRewriteContent(const CString& strCommitId, int nPEType, CString& strResFile, std::vector<std::string>& vtOldContent, std::vector<std::string>& vtNewContent)
{ {
@@ -665,7 +665,7 @@ void PrepareCppRewriteContent(const CString& strCommitId, int nPEType, CString&
if (!FindPreferredCppRcFileAt(g_szCurModuleDir, strResFile)) if (!FindPreferredCppRcFileAt(g_szCurModuleDir, strResFile))
{ {
_tprintf(_T("错误: 未找到C++ .rc资源文件。\n")); _tprintf(_T("错误: 未找到C++ .rc资源文件。\n"));
return; return;
} }
@@ -704,7 +704,7 @@ void PrepareCppRewriteContent(const CString& strCommitId, int nPEType, CString&
vtNewContent.push_back(ToAnsiString(szValue)); vtNewContent.push_back(ToAnsiString(szValue));
_tprintf(_T("Rewrite new token: %s\n"), szValue); _tprintf(_T("Rewrite new token: %s\n"), szValue);
#if 0 #if 0
_stprintf_s(szValue, "VALUE \"FileDescription\", \"TODO: <文件说明>\""); _stprintf_s(szValue, "VALUE \"FileDescription\", \"TODO: <文件说明>\"");
vtOldContent.push_back(szValue); vtOldContent.push_back(szValue);
_stprintf_s(szValue, "VALUE \"FileDescription\", \"%s\"", strCommitId.GetString()); _stprintf_s(szValue, "VALUE \"FileDescription\", \"%s\"", strCommitId.GetString());
@@ -714,18 +714,18 @@ void PrepareCppRewriteContent(const CString& strCommitId, int nPEType, CString&
} }
/// <summary> /// <summary>
/// 准备C#重写内容。 /// 准备C#重写内容。
/// </summary> /// </summary>
/// <param name="strCommitId">提交ID。</param> /// <param name="strCommitId">提交ID。</param>
/// <param name="strResFile">资源文件路径。</param> /// <param name="strResFile">资源文件路径。</param>
/// <param name="vtOldContent">旧内容向量。</param> /// <param name="vtOldContent">旧内容向量。</param>
/// <param name="vtNewContent">新内容向量。</param> /// <param name="vtNewContent">新内容向量。</param>
void PrepareCSharpRewriteContent(const CString& strCommitId, CString& strResFile, std::vector<std::string>& vtOldContent, std::vector<std::string>& vtNewContent) void PrepareCSharpRewriteContent(const CString& strCommitId, CString& strResFile, std::vector<std::string>& vtOldContent, std::vector<std::string>& vtNewContent)
{ {
TCHAR szValue[MAX_PATH] = { 0 }; TCHAR szValue[MAX_PATH] = { 0 };
if (!FindPreferredAssemblyInfoFileAt(g_szCurModuleDir, strResFile)) if (!FindPreferredAssemblyInfoFileAt(g_szCurModuleDir, strResFile))
{ {
_tprintf(_T("错误: 未找到首选的 AssemblyInfo 文件。\n")); _tprintf(_T("错误: 未找到首选的 AssemblyInfo 文件。\n"));
return; return;
} }
@@ -752,11 +752,11 @@ void PrepareCSharpRewriteContent(const CString& strCommitId, CString& strResFile
} }
/// <summary> /// <summary>
/// 处理重写命令。 /// 处理重写命令。
/// </summary> /// </summary>
/// <param name="argc">参数个数。</param> /// <param name="argc">参数个数。</param>
/// <param name="argv">参数数组。</param> /// <param name="argv">参数数组。</param>
/// <returns>返回值。</returns> /// <returns>返回值。</returns>
int HandleRewriteCommand(int argc, TCHAR* argv[]) int HandleRewriteCommand(int argc, TCHAR* argv[])
{ {
int nCodeType = DetectProjectCodeType(g_szCurModuleDir); int nCodeType = DetectProjectCodeType(g_szCurModuleDir);
@@ -771,11 +771,11 @@ int HandleRewriteCommand(int argc, TCHAR* argv[])
if (nCodeType == PROJECT_UNKNOWN) if (nCodeType == PROJECT_UNKNOWN)
{ {
_tprintf(_T("错误: 未知项目类型。\n")); _tprintf(_T("错误: 未知项目类型。\n"));
return 15; return 15;
} }
_tprintf(_T("项目类型: %s\n"), GetProjectCodeTypeName(nCodeType)); _tprintf(_T("项目类型: %s\n"), GetProjectCodeTypeName(nCodeType));
#ifdef _DEBUG #ifdef _DEBUG
CString strValue = StartProcess(NULL, _T("cmd /c git rev-parse --short HEAD"), RC_DIR); CString strValue = StartProcess(NULL, _T("cmd /c git rev-parse --short HEAD"), RC_DIR);
@@ -787,7 +787,7 @@ int HandleRewriteCommand(int argc, TCHAR* argv[])
strValue.Trim(); strValue.Trim();
if (strValue.IsEmpty()) if (strValue.IsEmpty())
{ {
_tprintf(_T("错误: 获取提交ID失败。\n")); _tprintf(_T("错误: 获取提交ID失败。\n"));
return 2; return 2;
} }
@@ -805,7 +805,7 @@ int HandleRewriteCommand(int argc, TCHAR* argv[])
} }
else if (nCodeType == PROJECT_PYTHON) else if (nCodeType == PROJECT_PYTHON)
{ {
_tprintf(_T("错误: 不支持的项目类型: Python。\n")); _tprintf(_T("错误: 不支持的项目类型: Python。\n"));
return 16; return 16;
} }
@@ -813,11 +813,11 @@ int HandleRewriteCommand(int argc, TCHAR* argv[])
{ {
if (bForceRewrite) if (bForceRewrite)
{ {
_tprintf(_T("警告: 资源文件路径为空,已按 -f 忽略本次重写失败。\n")); _tprintf(_T("警告: 资源文件路径为空,已按 -f 忽略本次重写失败。\n"));
return 0; return 0;
} }
_tprintf(_T("错误: 资源文件路径为空。\n")); _tprintf(_T("错误: 资源文件路径为空。\n"));
return 35; return 35;
} }
@@ -825,7 +825,7 @@ int HandleRewriteCommand(int argc, TCHAR* argv[])
{ {
if (bForceRewrite) if (bForceRewrite)
{ {
_tprintf(_T("警告: 替换文件内容失败,已按 -f 忽略本次重写失败。\n")); _tprintf(_T("警告: 替换文件内容失败,已按 -f 忽略本次重写失败。\n"));
return 0; return 0;
} }
@@ -839,7 +839,7 @@ int main(int argc, TCHAR* argv[], TCHAR* envp[])
{ {
int nRetCode = 0; int nRetCode = 0;
// 添加图标; // 添加图标;
HWND hwnd = GetForegroundWindow(); HWND hwnd = GetForegroundWindow();
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON_APP))); SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON_APP)));
HMODULE hModule = ::GetModuleHandle(NULL); HMODULE hModule = ::GetModuleHandle(NULL);
@@ -847,23 +847,23 @@ int main(int argc, TCHAR* argv[], TCHAR* envp[])
GetDirInfo(); GetDirInfo();
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{ {
_tprintf(_T("错误MFC 初始化失败。\n")); _tprintf(_T("错误MFC 初始化失败。\n"));
nRetCode = 1; nRetCode = 1;
} }
else else
{ {
CString strArgs = BuildArgsForLog(argc, argv); CString strArgs = BuildArgsForLog(argc, argv);
_tprintf(_T("命令参数: %s\n"), strArgs.GetString()); _tprintf(_T("命令参数: %s\n"), strArgs.GetString());
if (argc <= 1) if (argc <= 1)
{ {
_tprintf(_T("进入交互式标签创建模式。\n")); _tprintf(_T("进入交互式标签创建模式。\n"));
PrintFullUsageExamples(); PrintFullUsageExamples();
DWORD dwStartTick = LogCommandStart(_T("interactive")); DWORD dwStartTick = LogCommandStart(_T("interactive"));
int nCmdRet = HandleCreateTagInteractive(); int nCmdRet = HandleCreateTagInteractive();
LogCommandEnd(_T("interactive"), dwStartTick, nCmdRet); LogCommandEnd(_T("interactive"), dwStartTick, nCmdRet);
PrintCommandFailedWithCode(_T("interactive"), nCmdRet); PrintCommandFailedWithCode(_T("interactive"), nCmdRet);
// 暂停便于查看输出日志Windows 控制台) // 暂停便于查看输出日志Windows 控制台)
system("pause"); system("pause");
return nCmdRet; return nCmdRet;
} }
@@ -913,7 +913,7 @@ int main(int argc, TCHAR* argv[], TCHAR* envp[])
return nCmdRet; return nCmdRet;
} }
_tprintf(_T("错误:未知命令:%s\n"), argv[1]); _tprintf(_T("错误:未知命令:%s\n"), argv[1]);
PrintShortCommandUsage(); PrintShortCommandUsage();
return 3; return 3;

View File

@@ -8,7 +8,7 @@
extern TCHAR g_szCurModuleDir[MAX_PATH]; extern TCHAR g_szCurModuleDir[MAX_PATH];
// 来自 gitver_rewrite.cpp / GitVer.cpp 的跨单元函数声明 // 来自 gitver_rewrite.cpp / GitVer.cpp 的跨单元函数声明
std::string ToAnsiString(LPCTSTR lpText); std::string ToAnsiString(LPCTSTR lpText);
BOOL ReadTextFileAsAnsi(LPCTSTR lpFile, std::string& strContent, std::string& strBomPrefix); BOOL ReadTextFileAsAnsi(LPCTSTR lpFile, std::string& strContent, std::string& strBomPrefix);
BOOL WriteTextFileAsAnsi(LPCTSTR lpFile, const std::string& strContent, const std::string& strBomPrefix); BOOL WriteTextFileAsAnsi(LPCTSTR lpFile, const std::string& strContent, const std::string& strBomPrefix);
@@ -19,13 +19,13 @@ int ParseSetVerOptions(int argc, TCHAR* argv[], int nStartIndex, LPCTSTR& lpRepo
static const UINT DEFAULT_MAJOR_WHEN_NO_TAG_FOR_SETUP = 1; static const UINT DEFAULT_MAJOR_WHEN_NO_TAG_FOR_SETUP = 1;
static const UINT DEFAULT_MINOR_WHEN_NO_TAG_FOR_SETUP = 0; static const UINT DEFAULT_MINOR_WHEN_NO_TAG_FOR_SETUP = 0;
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 内部工具:行级文本替换 // 内部工具:行级文本替换
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
/// <summary> /// <summary>
/// 在字符串内容中查找首个包含 strToken 的整行, /// 在字符串内容中查找首个包含 strToken 的整行,
/// 用 strNewLine 替换该行(不含行尾换行符)。 /// 用 strNewLine 替换该行(不含行尾换行符)。
/// </summary> /// </summary>
static BOOL ReplaceLineByToken(std::string& strContent, static BOOL ReplaceLineByToken(std::string& strContent,
const std::string& strToken, const std::string& strToken,
@@ -46,7 +46,7 @@ static BOOL ReplaceLineByToken(std::string& strContent,
nLineEnd = strContent.size(); nLineEnd = strContent.size();
} }
// 去掉可能存在的 \r // 去掉可能存在的 \r
std::string::size_type nReplEnd = nLineEnd; std::string::size_type nReplEnd = nLineEnd;
if (nReplEnd > nLineStart && strContent[nReplEnd - 1] == '\r') if (nReplEnd > nLineStart && strContent[nReplEnd - 1] == '\r')
{ {
@@ -57,13 +57,13 @@ static BOOL ReplaceLineByToken(std::string& strContent,
return TRUE; return TRUE;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 查找安装脚本 // 查找安装脚本
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
/// <summary> /// <summary>
/// 在 exe 所在目录及其上级目录中查找安装脚本。 /// 在 exe 所在目录及其上级目录中查找安装脚本。
/// nSetupType=0 查找 setup.issnSetupType=1 查找 setup.nsi。 /// nSetupType=0 查找 setup.issnSetupType=1 查找 setup.nsi。
/// </summary> /// </summary>
static BOOL FindSetupScript(int nSetupType, CString& strScriptPath) static BOOL FindSetupScript(int nSetupType, CString& strScriptPath)
{ {
@@ -71,10 +71,10 @@ static BOOL FindSetupScript(int nSetupType, CString& strScriptPath)
LPCTSTR lpFileName = (nSetupType == 0) ? _T("setup.iss") : _T("setup.nsi"); LPCTSTR lpFileName = (nSetupType == 0) ? _T("setup.iss") : _T("setup.nsi");
// 当前 exe 目录(无末尾反斜杠) // 当前 exe 目录(无末尾反斜杠)
CString strExeDir = g_szCurModuleDir; CString strExeDir = g_szCurModuleDir;
// 尝试 exe 目录 // 尝试 exe 目录
CString strCandidate; CString strCandidate;
strCandidate.Format(_T("%s\\%s"), strExeDir.GetString(), lpFileName); strCandidate.Format(_T("%s\\%s"), strExeDir.GetString(), lpFileName);
if (PathFileExists(strCandidate)) if (PathFileExists(strCandidate))
@@ -83,7 +83,7 @@ static BOOL FindSetupScript(int nSetupType, CString& strScriptPath)
return TRUE; return TRUE;
} }
// 尝试上级目录 // 尝试上级目录
int nSlash = strExeDir.ReverseFind(_T('\\')); int nSlash = strExeDir.ReverseFind(_T('\\'));
if (nSlash > 0) if (nSlash > 0)
{ {
@@ -99,12 +99,12 @@ static BOOL FindSetupScript(int nSetupType, CString& strScriptPath)
return FALSE; return FALSE;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 修改 Inno Setup 脚本 // 修改 Inno Setup 脚本
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
/// <summary> /// <summary>
/// 修改 .iss 脚本中的 AppVersion= 行。 /// 修改 .iss 脚本中的 AppVersion= 行。
/// </summary> /// </summary>
static BOOL ModifyIssScript(const CString& strScriptPath, const CString& strProductVersion) static BOOL ModifyIssScript(const CString& strScriptPath, const CString& strProductVersion)
{ {
@@ -112,40 +112,40 @@ static BOOL ModifyIssScript(const CString& strScriptPath, const CString& strProd
std::string strBomPrefix; std::string strBomPrefix;
if (!ReadTextFileAsAnsi(strScriptPath, strContent, strBomPrefix)) if (!ReadTextFileAsAnsi(strScriptPath, strContent, strBomPrefix))
{ {
_tprintf(_T("错误: 读取 .iss 文件失败: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: 读取 .iss 文件失败: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
const std::string strToken = "AppVersion="; const std::string strToken = "AppVersion=";
if (strContent.find(strToken) == std::string::npos) if (strContent.find(strToken) == std::string::npos)
{ {
_tprintf(_T("错误: .iss 文件中未找到 AppVersion= 行: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: .iss 文件中未找到 AppVersion= 行: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
std::string strNewLine = "AppVersion=" + ToAnsiString(strProductVersion.GetString()); std::string strNewLine = "AppVersion=" + ToAnsiString(strProductVersion.GetString());
if (!ReplaceLineByToken(strContent, strToken, strNewLine)) if (!ReplaceLineByToken(strContent, strToken, strNewLine))
{ {
_tprintf(_T("错误: 替换 .iss AppVersion= 行失败。\n")); _tprintf(_T("错误: 替换 .iss AppVersion= 行失败。\n"));
return FALSE; return FALSE;
} }
if (!WriteTextFileAsAnsi(strScriptPath, strContent, strBomPrefix)) if (!WriteTextFileAsAnsi(strScriptPath, strContent, strBomPrefix))
{ {
_tprintf(_T("错误: 写入 .iss 文件失败: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: 写入 .iss 文件失败: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
_tprintf(_T("成功: 已更新 .iss AppVersion=%s\n"), strProductVersion.GetString()); _tprintf(_T("成功: 已更新 .iss AppVersion=%s\n"), strProductVersion.GetString());
return TRUE; return TRUE;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 修改 NSIS 脚本 // 修改 NSIS 脚本
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
/// <summary> /// <summary>
/// 修改 .nsh 脚本中的 !define PRODUCT_VERSION 行。 /// 修改 .nsh 脚本中的 !define PRODUCT_VERSION 行。
/// </summary> /// </summary>
static BOOL ModifyNshScript(const CString& strScriptPath, const CString& strProductVersion) static BOOL ModifyNshScript(const CString& strScriptPath, const CString& strProductVersion)
{ {
@@ -153,41 +153,41 @@ static BOOL ModifyNshScript(const CString& strScriptPath, const CString& strProd
std::string strBomPrefix; std::string strBomPrefix;
if (!ReadTextFileAsAnsi(strScriptPath, strContent, strBomPrefix)) if (!ReadTextFileAsAnsi(strScriptPath, strContent, strBomPrefix))
{ {
_tprintf(_T("错误: 读取 .nsh 文件失败: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: 读取 .nsh 文件失败: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
const std::string strToken = "!define PRODUCT_VERSION"; const std::string strToken = "!define PRODUCT_VERSION";
if (strContent.find(strToken) == std::string::npos) if (strContent.find(strToken) == std::string::npos)
{ {
_tprintf(_T("错误: .nsh 文件中未找到 !define PRODUCT_VERSION 行: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: .nsh 文件中未找到 !define PRODUCT_VERSION 行: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
std::string strNewLine = "!define PRODUCT_VERSION \"" + ToAnsiString(strProductVersion.GetString()) + "\""; std::string strNewLine = "!define PRODUCT_VERSION \"" + ToAnsiString(strProductVersion.GetString()) + "\"";
if (!ReplaceLineByToken(strContent, strToken, strNewLine)) if (!ReplaceLineByToken(strContent, strToken, strNewLine))
{ {
_tprintf(_T("错误: 替换 .nsh PRODUCT_VERSION 行失败。\n")); _tprintf(_T("错误: 替换 .nsh PRODUCT_VERSION 行失败。\n"));
return FALSE; return FALSE;
} }
if (!WriteTextFileAsAnsi(strScriptPath, strContent, strBomPrefix)) if (!WriteTextFileAsAnsi(strScriptPath, strContent, strBomPrefix))
{ {
_tprintf(_T("错误: 写入 .nsh 文件失败: %s\n"), strScriptPath.GetString()); _tprintf(_T("错误: 写入 .nsh 文件失败: %s\n"), strScriptPath.GetString());
return FALSE; return FALSE;
} }
_tprintf(_T("成功: 已更新 .nsh PRODUCT_VERSION=%s\n"), strProductVersion.GetString()); _tprintf(_T("成功: 已更新 .nsh PRODUCT_VERSION=%s\n"), strProductVersion.GetString());
return TRUE; return TRUE;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 查找编译器 // 查找编译器
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
/// <summary> /// <summary>
/// 查找 Inno Setup 编译器 (ISCC.exe)。 /// 查找 Inno Setup 编译器 (ISCC.exe)。
/// 先查 PATH再尝试常见安装路径。 /// 先查 PATH再尝试常见安装路径。
/// </summary> /// </summary>
static CString FindInnoSetupCompiler() static CString FindInnoSetupCompiler()
{ {
@@ -217,8 +217,8 @@ static CString FindInnoSetupCompiler()
} }
/// <summary> /// <summary>
/// 查找 NSIS 编译器 (makensis.exe)。 /// 查找 NSIS 编译器 (makensis.exe)。
/// 先查 PATH再尝试常见安装路径。 /// 先查 PATH再尝试常见安装路径。
/// </summary> /// </summary>
static CString FindNsisCompiler() static CString FindNsisCompiler()
{ {
@@ -245,35 +245,35 @@ static CString FindNsisCompiler()
return CString(); return CString();
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 公共执行函数(供 HandleSetupCommand 和 setver -setup=N 共用) // 公共执行函数(供 HandleSetupCommand 和 setver -setup=N 共用)
// 不回写版本信息到项目文件,只修改安装脚本并调用编译器打包。 // 不回写版本信息到项目文件,只修改安装脚本并调用编译器打包。
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
BOOL ExecuteSetupBuild(int nSetupType, const CString& strProductVersion) BOOL ExecuteSetupBuild(int nSetupType, const CString& strProductVersion)
{ {
// 查找安装脚本 // 查找安装脚本
CString strScriptPath; CString strScriptPath;
if (!FindSetupScript(nSetupType, strScriptPath)) if (!FindSetupScript(nSetupType, strScriptPath))
{ {
LPCTSTR lpScriptName = (nSetupType == 0) ? _T("setup.iss") : _T("setup.nsi"); LPCTSTR lpScriptName = (nSetupType == 0) ? _T("setup.iss") : _T("setup.nsi");
_tprintf(_T("错误: 未在 exe 目录或上级目录中找到 %s。\n"), lpScriptName); _tprintf(_T("错误: 未在 exe 目录或上级目录中找到 %s。\n"), lpScriptName);
return FALSE; return FALSE;
} }
_tprintf(_T("找到安装脚本: %s\n"), strScriptPath.GetString()); _tprintf(_T("找到安装脚本: %s\n"), strScriptPath.GetString());
// 修改脚本中的版本号(不写回 .rc / AssemblyInfo.cs // 修改脚本中的版本号(不写回 .rc / AssemblyInfo.cs
BOOL bModifyOk = (nSetupType == 0) BOOL bModifyOk = (nSetupType == 0)
? ModifyIssScript(strScriptPath, strProductVersion) ? ModifyIssScript(strScriptPath, strProductVersion)
: ModifyNshScript(strScriptPath, strProductVersion); : ModifyNshScript(strScriptPath, strProductVersion);
if (!bModifyOk) if (!bModifyOk)
{ {
_tprintf(_T("错误: 修改安装脚本版本信息失败。\n")); _tprintf(_T("错误: 修改安装脚本版本信息失败。\n"));
return FALSE; return FALSE;
} }
// 查找编译器 // 查找编译器
CString strCompiler = (nSetupType == 0) CString strCompiler = (nSetupType == 0)
? FindInnoSetupCompiler() ? FindInnoSetupCompiler()
: FindNsisCompiler(); : FindNsisCompiler();
@@ -283,12 +283,12 @@ BOOL ExecuteSetupBuild(int nSetupType, const CString& strProductVersion)
LPCTSTR lpCompilerName = (nSetupType == 0) LPCTSTR lpCompilerName = (nSetupType == 0)
? _T("ISCC.exe (Inno Setup)") ? _T("ISCC.exe (Inno Setup)")
: _T("makensis.exe (NSIS)"); : _T("makensis.exe (NSIS)");
_tprintf(_T("错误: 未找到安装包编译器 %s请确认已安装并加入 PATH。\n"), lpCompilerName); _tprintf(_T("错误: 未找到安装包编译器 %s请确认已安装并加入 PATH。\n"), lpCompilerName);
return FALSE; return FALSE;
} }
_tprintf(_T("找到编译器: %s\n"), strCompiler.GetString()); _tprintf(_T("找到编译器: %s\n"), strCompiler.GetString());
// 取脚本所在目录作为工作目录 // 取脚本所在目录作为工作目录
CString strScriptDir = strScriptPath; CString strScriptDir = strScriptPath;
int nSlash = strScriptDir.ReverseFind(_T('\\')); int nSlash = strScriptDir.ReverseFind(_T('\\'));
if (nSlash >= 0) if (nSlash >= 0)
@@ -296,47 +296,47 @@ BOOL ExecuteSetupBuild(int nSetupType, const CString& strProductVersion)
strScriptDir = strScriptDir.Left(nSlash); strScriptDir = strScriptDir.Left(nSlash);
} }
// 构建并执行编译命令 // 构建并执行编译命令
CString strCmd; CString strCmd;
strCmd.Format(_T("cmd /c %s %s"), strCmd.Format(_T("cmd /c %s %s"),
QuoteCmdArg(strCompiler).GetString(), QuoteCmdArg(strCompiler).GetString(),
QuoteCmdArg(strScriptPath).GetString()); QuoteCmdArg(strScriptPath).GetString());
_tprintf(_T("执行编译: %s\n"), strCmd.GetString()); _tprintf(_T("执行编译: %s\n"), strCmd.GetString());
CString strOutput = StartProcess(NULL, strCmd.GetBuffer(), strScriptDir.GetString()); CString strOutput = StartProcess(NULL, strCmd.GetBuffer(), strScriptDir.GetString());
strCmd.ReleaseBuffer(); strCmd.ReleaseBuffer();
if (strOutput.IsEmpty()) if (strOutput.IsEmpty())
{ {
_tprintf(_T("警告: 编译器无输出,可能执行失败。\n")); _tprintf(_T("警告: 编译器无输出,可能执行失败。\n"));
} }
return TRUE; return TRUE;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 独立命令入口argv[1] 形如 "-setup=0" // 独立命令入口argv[1] 形如 "-setup=0"
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
int HandleSetupCommand(int argc, TCHAR* argv[]) int HandleSetupCommand(int argc, TCHAR* argv[])
{ {
// 解析 -setup=n 中的 n // 解析 -setup=n 中的 n
CString strSetupArg = argv[1]; CString strSetupArg = argv[1];
CString strN = strSetupArg.Mid(7); // 跳过 "-setup=" CString strN = strSetupArg.Mid(7); // 跳过 "-setup="
UINT nSetupType = UINT(-1); UINT nSetupType = UINT(-1);
if (!TryParseUInt16(strN, nSetupType) || (nSetupType != 0 && nSetupType != 1)) if (!TryParseUInt16(strN, nSetupType) || (nSetupType != 0 && nSetupType != 1))
{ {
_tprintf(_T("错误: -setup 参数值 \"%s\" 不支持,仅支持 0Inno Setup或 1NSIS\n"), _tprintf(_T("错误: -setup 参数值 \"%s\" 不支持,仅支持 0Inno Setup或 1NSIS\n"),
strN.GetString()); strN.GetString());
return 36; return 36;
} }
if (argc < 3) if (argc < 3)
{ {
_tprintf(_T("错误: 参数不足。\n")); _tprintf(_T("错误: 参数不足。\n"));
_tprintf(_T("用法gitver -setup=0|1 [pid] [repodir=<path>可选]\n")); _tprintf(_T("用法gitver -setup=0|1 [pid] [repodir=<path>可选]\n"));
_tprintf(_T("示例gitver -setup=0 5\n")); _tprintf(_T("示例gitver -setup=0 5\n"));
_tprintf(_T("示例gitver -setup=1 5 repodir=E:\\Code\\MyProj\n")); _tprintf(_T("示例gitver -setup=1 5 repodir=E:\\Code\\MyProj\n"));
return 3; return 3;
} }
@@ -379,12 +379,12 @@ int HandleSetupCommand(int argc, TCHAR* argv[])
{ {
strProductVersion = strProductVersion.Left(nDot2 + 1) + _T("0.0"); strProductVersion = strProductVersion.Left(nDot2 + 1) + _T("0.0");
} }
_tprintf(_T("[test] 已将 major/minor 置零: ProductVersion=%s\n"), strProductVersion.GetString()); _tprintf(_T("[test] 已将 major/minor 置零: ProductVersion=%s\n"), strProductVersion.GetString());
} }
_tprintf(_T("ProductVersion=%s\n"), strProductVersion.GetString()); _tprintf(_T("ProductVersion=%s\n"), strProductVersion.GetString());
// 不回写版本信息到项目文件,直接修改安装脚本并编译打包 // 不回写版本信息到项目文件,直接修改安装脚本并编译打包
if (!ExecuteSetupBuild((int)nSetupType, strProductVersion)) if (!ExecuteSetupBuild((int)nSetupType, strProductVersion))
{ {
return 38; return 38;

View File

@@ -6,7 +6,7 @@
BOOL TryGetCurrentBranch(LPCTSTR lpRepoPath, CString& strBranch) BOOL TryGetCurrentBranch(LPCTSTR lpRepoPath, CString& strBranch)
{ {
_tprintf(_T("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>\n")); _tprintf(_T("获取当前分支名称: \n"));
strBranch = StartProcess(NULL, _T("cmd /c git rev-parse --abbrev-ref HEAD"), lpRepoPath); strBranch = StartProcess(NULL, _T("cmd /c git rev-parse --abbrev-ref HEAD"), lpRepoPath);
strBranch.Replace(_T("\r"), _T("")); strBranch.Replace(_T("\r"), _T(""));
strBranch.Replace(_T("\n"), _T("")); strBranch.Replace(_T("\n"), _T(""));
@@ -92,7 +92,7 @@ BOOL GetLastMajorMinorTag(LPCTSTR lpRepoPath, const CString& strBranch, CString&
CString strTagList = StartProcess(NULL, _T("cmd /c git tag --list --sort=v:refname"), lpRepoPath); CString strTagList = StartProcess(NULL, _T("cmd /c git tag --list --sort=v:refname"), lpRepoPath);
if (strTagList.IsEmpty()) if (strTagList.IsEmpty())
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1>ǩ<EFBFBD>б<EFBFBD>ʧ<EFBFBD><CAA7>\n")); _tprintf(_T("错误: 获取标签列表失败\n"));
return FALSE; return FALSE;
} }
@@ -103,7 +103,7 @@ BOOL GetLastMajorMinorTag(LPCTSTR lpRepoPath, const CString& strBranch, CString&
strLine.Trim(); strLine.Trim();
if (strLine.Left(6).CompareNoCase(_T("fatal:")) == 0) if (strLine.Left(6).CompareNoCase(_T("fatal:")) == 0)
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1>ǩ<EFBFBD>б<EFBFBD>ʧ<EFBFBD><CAA7> %s\n"), strLine.GetString()); _tprintf(_T("错误: 获取标签列表失败 %s\n"), strLine.GetString());
return FALSE; return FALSE;
} }
@@ -125,7 +125,7 @@ BOOL GetLastMajorMinorTag(LPCTSTR lpRepoPath, const CString& strBranch, CString&
void GetFileVersionDateFromSystemTime(const SYSTEMTIME& stLocal, UINT& nYY, UINT& nMMDD) void GetFileVersionDateFromSystemTime(const SYSTEMTIME& stLocal, UINT& nYY, UINT& nMMDD)
{ {
nYY = stLocal.wYear % 100; nYY = stLocal.wYear % 100;
// Ϊ<EFBFBD><EFBFBD><EFBFBD>ð汾<EFBFBD>Ŷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·ݴ<EFBFBD>1-12ӳ<EFBFBD>11-22; // 为版本号生成文件版本号,月份映射到1-12映射到11-22;
nMMDD = (stLocal.wMonth + 10) * 100 + stLocal.wDay; nMMDD = (stLocal.wMonth + 10) * 100 + stLocal.wDay;
} }
@@ -221,32 +221,32 @@ BOOL ResolveFileVersionDateAndCommitCount(LPCTSTR lpRepoPath, const CString& str
UINT nTodayCommitCount = 0; UINT nTodayCommitCount = 0;
if (!TryGetBranchCommitCountByDate(lpRepoPath, strBranch, stTargetDate, nTodayCommitCount)) if (!TryGetBranchCommitCountByDate(lpRepoPath, strBranch, stTargetDate, nTodayCommitCount))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1BDBB><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>\n")); _tprintf(_T("错误: 获取当天提交数量失败\n"));
return FALSE; return FALSE;
} }
if (nTodayCommitCount == 0) if (nTodayCommitCount == 0)
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n")); _tprintf(_T("警告: 当天提交数量为0尝试获取最近一次提交日期\n"));
if (!TryGetLastBranchCommitDate(lpRepoPath, strBranch, stTargetDate)) if (!TryGetLastBranchCommitDate(lpRepoPath, strBranch, stTargetDate))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><E1BDBB><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>\n")); _tprintf(_T("错误: 获取最近一次提交日期失败\n"));
return FALSE; return FALSE;
} }
if (!TryGetBranchCommitCountByDate(lpRepoPath, strBranch, stTargetDate, nTodayCommitCount)) if (!TryGetBranchCommitCountByDate(lpRepoPath, strBranch, stTargetDate, nTodayCommitCount))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ[%s]<5D><EFBFBD><E1BDBB><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>\n"), strBranch.GetString()); _tprintf(_T("错误: 获取 [%s] 提交数量失败\n"), strBranch.GetString());
return FALSE; return FALSE;
} }
_tprintf(_T("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %04u-%02u-%02u, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %u\n"), _tprintf(_T("获取提交信息成功: %04u-%02u-%02u, 提交数量: %u\n"),
stTargetDate.wYear, stTargetDate.wMonth, stTargetDate.wDay, nTodayCommitCount); stTargetDate.wYear, stTargetDate.wMonth, stTargetDate.wDay, nTodayCommitCount);
} }
else else
{ {
_tprintf(_T("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %u\n"), nTodayCommitCount); _tprintf(_T("获取当天提交数量成功: %u\n"), nTodayCommitCount);
} }
GetFileVersionDateFromSystemTime(stTargetDate, nYY, nMMDD); GetFileVersionDateFromSystemTime(stTargetDate, nYY, nMMDD);
@@ -263,7 +263,7 @@ int BuildVersionsFromRepo(
UINT nDefaultMajor, UINT nDefaultMajor,
UINT nDefaultMinor) UINT nDefaultMinor)
{ {
_tprintf(_T("\xBF\xAA\xCA\xBC\xB9\xB9\xBD\xA8\xB0\xE6\xB1\xBE: \xB2\xD6\xBF\xE2\xC2\xB7\xBE\xB6=%s pid=%u default=%u.%u\n"), _tprintf(_T("开始构建版本: 仓库路径=%s pid=%u 默认Tag(%u.%u)\n"),
lpRepoPath == NULL ? _T("<null>") : lpRepoPath, lpRepoPath == NULL ? _T("<null>") : lpRepoPath,
nPid, nPid,
nDefaultMajor, nDefaultMajor,
@@ -273,17 +273,17 @@ int BuildVersionsFromRepo(
CString strBranch; CString strBranch;
if (!TryGetCurrentBranch(lpRepoPath, strBranch)) if (!TryGetCurrentBranch(lpRepoPath, strBranch))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0>֧ʧ<D6A7>ܡ<EFBFBD>\n")); _tprintf(_T("错误: 获取当前分支失败\n"));
return errorCodes.nBidErrorCode; return errorCodes.nBidErrorCode;
} }
_tprintf(_T("<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>֧: %s\n"), strBranch.GetString()); _tprintf(_T("当前分支: %s\n"), strBranch.GetString());
if (!TryGetBidFromBranch(strBranch, nBid)) if (!TryGetBidFromBranch(strBranch, nBid))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1>֧ bid ʧ<EFBFBD><EFBFBD>\n")); _tprintf(_T("错误: 获取分支 bid 失败\n"));
return errorCodes.nBidErrorCode; return errorCodes.nBidErrorCode;
} }
_tprintf(_T("<EFBFBD><EFBFBD>֧ bid: %u\n"), nBid); _tprintf(_T("分支 bid: %u\n"), nBid);
CString strLastTag; CString strLastTag;
UINT nMajor = 0; UINT nMajor = 0;
@@ -292,11 +292,11 @@ int BuildVersionsFromRepo(
{ {
nMajor = nDefaultMajor; nMajor = nDefaultMajor;
nMinor = nDefaultMinor; nMinor = nDefaultMinor;
_tprintf(_T("ʹ<EFBFBD><EFBFBD>Ĭ<EFBFBD>ϱ<EFBFBD>ǩ %u %u\n"), nMajor, nMinor); _tprintf(_T("使用默认标签 %u %u\n"), nMajor, nMinor);
} }
else else
{ {
_tprintf(_T("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>ǩ: %s (major=%u minor=%u)\n"), strLastTag.GetString(), nMajor, nMinor); _tprintf(_T("最近标签: %s (major=%u minor=%u)\n"), strLastTag.GetString(), nMajor, nMinor);
} }
UINT nYY = 0; UINT nYY = 0;
@@ -304,13 +304,13 @@ int BuildVersionsFromRepo(
UINT nId = 0; UINT nId = 0;
if (!ResolveFileVersionDateAndCommitCount(lpRepoPath, strBranch, nYY, nMMDD, nId)) if (!ResolveFileVersionDateAndCommitCount(lpRepoPath, strBranch, nYY, nMMDD, nId))
{ {
_tprintf(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>ȡ<EFBFBD><C8A1>֧<EFBFBD><EFBFBD><E1BDBB>Ϣʧ<CFA2><CAA7>\n")); _tprintf(_T("错误: 获取分支提交信息失败\n"));
return errorCodes.nCommitErrorCode; return errorCodes.nCommitErrorCode;
} }
_tprintf(_T("<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD>Ϣ: yy=%u mmdd=%u id=%u\n"), nYY, nMMDD, nId); _tprintf(_T("分支提交信息: yy=%u mmdd=%u id=%u\n"), nYY, nMMDD, nId);
strProductVersion.Format(_T("%u.%u.%u.%u"), nPid, nBid, nMajor, nMinor); strProductVersion.Format(_T("%u.%u.%u.%u"), nPid, nBid, nMajor, nMinor);
strFileVersion.Format(_T("%u.%u.%u.%u"), nPid, nYY, nMMDD, nId); strFileVersion.Format(_T("%u.%u.%u.%u"), nPid, nYY, nMMDD, nId);
_tprintf(_T("<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ: ProductVersion=%s FileVersion=%s\n"), strProductVersion.GetString(), strFileVersion.GetString()); _tprintf(_T("文件版本信息: ProductVersion=%s FileVersion=%s\n"), strProductVersion.GetString(), strFileVersion.GetString());
return 0; return 0;
} }