diff --git a/GitVer/GitVer_pyinstaller.cpp b/GitVer/GitVer_pyinstaller.cpp index 978b7b9..4827268 100644 --- a/GitVer/GitVer_pyinstaller.cpp +++ b/GitVer/GitVer_pyinstaller.cpp @@ -462,6 +462,125 @@ static BOOL UpdateVersionInfoFile(LPCTSTR lpPath, LPCTSTR lpProductVersion, LPCT 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 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 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[]) { #ifdef _DEBUG @@ -535,19 +654,43 @@ int HandlePyinstallerBuildCommand(int argc, TCHAR* argv[]) CString strExistingVersionPath; if (ReadVersionPathFromSpec(strSpecPath, strExistingVersionPath)) { - // spec 已有 version=,直接更新所指向的文件(不存在则创建) + // spec 已有 version=,解析其指向的文件路径 CString strVersionInfoFullPath; if (PathIsRelative(strExistingVersionPath)) strVersionInfoFullPath.Format(_T("%s\\%s"), szSpecDir, strExistingVersionPath.GetString()); else strVersionInfoFullPath = strExistingVersionPath; - if (!UpdateVersionInfoFile(strVersionInfoFullPath, strProductVersion, strFileVersion)) + if (PathFileExists(strVersionInfoFullPath)) { - _tprintf(_T("错误: 无法更新版本信息文件: %s。\n"), strVersionInfoFullPath.GetString()); + // 外部版本信息文件存在,直接更新 + if (!UpdateVersionInfoFile(strVersionInfoFullPath, strProductVersion, strFileVersion)) + { + _tprintf(_T("错误: 无法更新版本信息文件: %s。\n"), strVersionInfoFullPath.GetString()); + return 45; + } + _tprintf(_T("版本信息文件已更新: %s\n"), strVersionInfoFullPath.GetString()); + } + 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("版本信息文件已更新: %s\n"), strVersionInfoFullPath.GetString()); + _tprintf(_T("spec 内联版本块已更新: %s\n"), strSpecPath.GetString()); } else {