支持spec内置版本信息的处理

This commit is contained in:
2026-05-21 20:18:38 +08:00
parent 4a4c51d124
commit 67d24d69f5

View File

@@ -462,6 +462,125 @@ static BOOL UpdateVersionInfoFile(LPCTSTR lpPath, LPCTSTR lpProductVersion, LPCT
return TRUE; return TRUE;
} }
// 检查 spec 文件中 version= 是否为无引号标识符(表示 spec 内内联 VSVersionInfo 对象)
static BOOL HasInlineVersionInfoBlock(LPCTSTR lpSpecPath)
{
if (!PathFileExists(lpSpecPath)) return FALSE;
CFile myFile;
CFileException fileEx;
if (!myFile.Open(lpSpecPath, CFile::modeRead, &fileEx)) return FALSE;
DWORD dwLen = (DWORD)myFile.GetLength();
std::vector<char> buf(dwLen + 1, 0);
myFile.Read(buf.data(), dwLen);
myFile.Close();
std::string strContent(buf.data(), dwLen);
std::string::size_type nPos = 0;
while ((nPos = strContent.find("version=", nPos)) != std::string::npos)
{
bool bIsParam = (nPos == 0
|| strContent[nPos - 1] == '\n'
|| strContent[nPos - 1] == '\r'
|| strContent[nPos - 1] == ' '
|| strContent[nPos - 1] == '\t');
if (bIsParam)
{
std::string::size_type nValStart = nPos + 8;
while (nValStart < strContent.size() && strContent[nValStart] == ' ')
nValStart++;
if (nValStart < strContent.size())
{
char c = strContent[nValStart];
// 无引号且以字母或下划线开头,视为 Python 标识符
if (c != '\'' && c != '"' && (isalpha((unsigned char)c) || c == '_'))
return TRUE;
}
break;
}
nPos += 8;
}
return FALSE;
}
// 修改 spec 文件中 version= 的引号值(内联版本号字符串场景)
// 当 version= 后是非外部文件路径的字符串字面量时,直接替换该值为新版本号
static BOOL UpdateVersionStringInSpec(LPCTSTR lpSpecPath, LPCTSTR lpNewValue)
{
if (!PathFileExists(lpSpecPath))
{
_tprintf(_T("错误: spec 文件不存在: %s\n"), lpSpecPath);
return FALSE;
}
CFile myFile;
CFileException fileEx;
if (!myFile.Open(lpSpecPath, CFile::modeReadWrite, &fileEx))
{
_tprintf(_T("错误: 无法打开 spec 文件: %s\n"), lpSpecPath);
return FALSE;
}
DWORD dwLen = (DWORD)myFile.GetLength();
std::vector<char> buf(dwLen + 1, 0);
myFile.Read(buf.data(), dwLen);
myFile.Close();
std::string strContent(buf.data(), dwLen);
CStringA strNewValueA(lpNewValue);
std::string strNewValue(strNewValueA);
std::string::size_type nPos = 0;
bool bUpdated = false;
while ((nPos = strContent.find("version=", nPos)) != std::string::npos)
{
bool bIsParam = (nPos == 0
|| strContent[nPos - 1] == '\n'
|| strContent[nPos - 1] == '\r'
|| strContent[nPos - 1] == ' '
|| strContent[nPos - 1] == '\t');
if (bIsParam)
{
std::string::size_type nValStart = nPos + 8; // skip "version="
while (nValStart < strContent.size() && strContent[nValStart] == ' ')
nValStart++;
if (nValStart < strContent.size())
{
char cQuote = strContent[nValStart];
if (cQuote == '\'' || cQuote == '"')
{
std::string::size_type nValEnd = strContent.find(cQuote, nValStart + 1);
if (nValEnd != std::string::npos)
{
strContent.replace(nValStart + 1, nValEnd - nValStart - 1, strNewValue);
bUpdated = true;
_tprintf(_T("成功: 已更新 spec 内联版本号 -> %s\n"), lpNewValue);
break;
}
}
}
break;
}
nPos += 8;
}
if (!bUpdated)
{
_tprintf(_T("错误: 未在 spec 文件中找到可替换的 version= 引号值。\n"));
return FALSE;
}
if (!myFile.Open(lpSpecPath, CFile::modeCreate | CFile::modeWrite, &fileEx))
{
_tprintf(_T("错误: 无法写入 spec 文件: %s\n"), lpSpecPath);
return FALSE;
}
myFile.Write(strContent.c_str(), (UINT)strContent.size());
myFile.Close();
return TRUE;
}
int HandlePyinstallerBuildCommand(int argc, TCHAR* argv[]) int HandlePyinstallerBuildCommand(int argc, TCHAR* argv[])
{ {
#ifdef _DEBUG #ifdef _DEBUG
@@ -535,13 +654,16 @@ int HandlePyinstallerBuildCommand(int argc, TCHAR* argv[])
CString strExistingVersionPath; CString strExistingVersionPath;
if (ReadVersionPathFromSpec(strSpecPath, strExistingVersionPath)) if (ReadVersionPathFromSpec(strSpecPath, strExistingVersionPath))
{ {
// spec 已有 version=直接更新所指向的文件(不存在则创建) // spec 已有 version=解析其指向的文件路径
CString strVersionInfoFullPath; CString strVersionInfoFullPath;
if (PathIsRelative(strExistingVersionPath)) if (PathIsRelative(strExistingVersionPath))
strVersionInfoFullPath.Format(_T("%s\\%s"), szSpecDir, strExistingVersionPath.GetString()); strVersionInfoFullPath.Format(_T("%s\\%s"), szSpecDir, strExistingVersionPath.GetString());
else else
strVersionInfoFullPath = strExistingVersionPath; strVersionInfoFullPath = strExistingVersionPath;
if (PathFileExists(strVersionInfoFullPath))
{
// 外部版本信息文件存在,直接更新
if (!UpdateVersionInfoFile(strVersionInfoFullPath, strProductVersion, strFileVersion)) if (!UpdateVersionInfoFile(strVersionInfoFullPath, strProductVersion, strFileVersion))
{ {
_tprintf(_T("错误: 无法更新版本信息文件: %s。\n"), strVersionInfoFullPath.GetString()); _tprintf(_T("错误: 无法更新版本信息文件: %s。\n"), strVersionInfoFullPath.GetString());
@@ -550,6 +672,27 @@ int HandlePyinstallerBuildCommand(int argc, TCHAR* argv[])
_tprintf(_T("版本信息文件已更新: %s\n"), strVersionInfoFullPath.GetString()); _tprintf(_T("版本信息文件已更新: %s\n"), strVersionInfoFullPath.GetString());
} }
else else
{
// version= 后的值不是有效的外部文件路径,视为 spec 内联版本号定义,直接修改 spec
_tprintf(_T("版本信息文件未找到(%s将修改 spec 内联版本号。\n"), strVersionInfoFullPath.GetString());
if (!UpdateVersionStringInSpec(strSpecPath, strFileVersion))
{
_tprintf(_T("错误: 无法修改 spec 文件内联版本号。\n"));
return 46;
}
}
}
else if (HasInlineVersionInfoBlock(strSpecPath))
{
// spec 中 version=<标识符>,标识符指向 spec 内定义的 VSVersionInfo 对象,直接更新 spec 文件中的版本字段
if (!UpdateVersionInfoFile(strSpecPath, strProductVersion, strFileVersion))
{
_tprintf(_T("错误: 无法更新 spec 内联版本块: %s。\n"), strSpecPath.GetString());
return 45;
}
_tprintf(_T("spec 内联版本块已更新: %s\n"), strSpecPath.GetString());
}
else
{ {
// spec 未指定 version=,生成 version_info.txt 并注入 spec // spec 未指定 version=,生成 version_info.txt 并注入 spec
CString strVersionInfoPath; CString strVersionInfoPath;