c++实现svn提交日志校验

关于svn日志提交的简介请参考 点击打开链接


下面直接上代码,如下:


#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <windows.h>

#define BUFF_SIZE 2048

const char* commitfmtlogs = "\
请按照如下格式填写提交修改记录信息:\n\
【修改内容】\n\
此处说明你的修改内容,不少于20个字。\n\
【修改原因】\n\
此处说明你为什么要做出这样的修改,不少于20个字。\n\
【影响范围】\n\
此处说明你的修改会对其它什么地方产生影响,不少于10个字。\n\
【TODO列表】\n\
此处说明针对这次提交,还有什么事情没有做,如可能想到一些功能缺陷,以后要进行修改。 字数不限,如没有内容请填写 无。\n\
【问题列表】\n\
fixes #Redmine上的问题编号。(已解决某问题)\n\
或\n\
refs #Redmine上的问题编号。(关联到某问题)\n";

//HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\VisualSVN\VisualSVN Server\InstallDir

bool getSvnBinPath(std::string& svnBinPath)
{

    HKEY hKey = NULL;
    LONG retVal = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\VisualSVN\\VisualSVN Server", 0, KEY_ALL_ACCESS, &hKey);
    if (ERROR_SUCCESS != retVal)
    {
        OutputDebugStringA("打开svn注册表失败");
        return false;
    }

    char buff[MAX_PATH] = { 0 };
    DWORD len = MAX_PATH;
    DWORD type = REG_SZ;
    retVal = RegQueryValueExA(hKey, "InstallDir", NULL, &type, (unsigned char*)buff, &len);
    if (ERROR_SUCCESS != retVal)
    {
        OutputDebugStringA("读取svn注册表项InstallDir失败");
        return false;
    }

    svnBinPath = buff;
    svnBinPath += "bin\\";

    return true;
}

/**
* @brief 通过svnlook获取提交的日志信息。
* 函数功能详述:
* @param
* @return
* @note	no
* @warning no
* @see		no
*/
void getSvnLog(const char* cmd, std::string& commitLogs)
{
    //创建匿名管道从svnlook进程中获取提交的日志信息
    HANDLE hReadPipe = NULL;
    HANDLE hWritePipe = NULL;
    SECURITY_ATTRIBUTES stSecurity;
    stSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
    stSecurity.lpSecurityDescriptor = NULL;
    stSecurity.bInheritHandle = TRUE;//继承性
    CreatePipe(&hReadPipe, &hWritePipe, &stSecurity, 0);
    STARTUPINFOA siStartInfo;
    GetStartupInfo(&siStartInfo);
    siStartInfo.hStdInput = hReadPipe;
    siStartInfo.hStdOutput = hWritePipe;
    siStartInfo.hStdError = hWritePipe;
    siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    siStartInfo.wShowWindow = SW_HIDE;

    PROCESS_INFORMATION procInfo;

    if (CreateProcessA(NULL, (char*)cmd, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &siStartInfo, &procInfo))
    {
        char buff[BUFF_SIZE + 1] = { 0 };
        DWORD bytes_read = BUFF_SIZE;

        while (true)
        {
            PeekNamedPipe(hReadPipe, buff, BUFF_SIZE, &bytes_read, NULL, NULL);
            if (0 != bytes_read)
            {
                ReadFile(hReadPipe, buff, bytes_read, &bytes_read, NULL);
                OutputDebugStringA(buff);
                break;
            }
        }

        commitLogs = buff;
    }
}


/**
* @brief 按照指定规则进行格式化字符串。
* 函数功能详述:
* @param
* @return
* @note	no
* @warning no
* @see		no
*/
bool splitString(const std::string& src,
                 std::vector<std::string>& fields,
                 const std::string& pattern)
{
    int size = src.size();
    int pos = 0;
    int i = 0;
    for (; i < size; ++i)
    {
        pos = src.find(pattern, i);

        if (std::string::npos == pos)
        {
            break;
        }
        fields.push_back(src.substr(i, pos - i));
        i = pos + pattern.size() - 1;
    }

    //判断最后是否是以pattern结尾
    if (i != size)
    {
        fields.push_back(src.substr(i, size - i));
    }

    return true;
}

/**
 * @brief 判断问题号是否为数字。
 * 函数功能详述:
 * @param 
 * @return 
 * @note	no
 * @warning no
 * @see		no
 */
bool isDigit(std::string issue)
{
    int len = issue.size();
    for (int i = 0; i < len; ++i)
    {
        if (issue[i] >= '0' && issue[i] <= '9')
        {
            return true;
        }
    }
    return false;
}

/**
* @brief 检查日志规则。
* 函数功能详述:
* @param
* @return
* @note	no
* @warning no
* @see		no
*/
bool checkSvnLog(const std::string& commitLogs)
{
    std::string subLogs;
    std::vector<std::string> fields;
    splitString(commitLogs, fields, "\r\n");
    int flag = 10;  //至少需要10行内容,才能匹配规则
    int cnts = fields.size();
    if (cnts < flag)
    {
        OutputDebugStringA("cnts < flag");
        return false;
    }

    //第一项 修改内容检查
    if (std::string::npos == fields[0].find("修改内容"))
    {
        OutputDebugStringA("缺少【修改内容】");
        return false;
    }
    if (fields[1].size() < 20)
    {
        OutputDebugStringA("【修改内容】字数不够");
        return false;
    }

    //第二项 修改原因检查
    if (std::string::npos == fields[2].find("修改原因"))
    {
        OutputDebugStringA("缺少【修改原因】");
        return false;
    }
    if (fields[3].size() < 20)
    {
        OutputDebugStringA("【修改原因】字数不够");
        return false;
    }

    //第三项 影响范围检查
    if (std::string::npos == fields[4].find("影响范围"))
    {
        OutputDebugStringA("缺少【影响范围】");
        return false;
    }
    if (fields[5].size() < 10)
    {
        OutputDebugStringA("【影响范围】字数不够");
        return false;
    }

    /*if (fields[1] == fields[3] ||
        fields[2] == fields[3] ||
        fields[1] == fields[2])
        {
        OutputDebugStringA("【修改内容】【修改原因】【影响范围】三处内容不能一样");
        return false;
        }*/

    //第四项 TODO列表检查
    if (std::string::npos == fields[6].find("TODO列表"))
    {
        OutputDebugStringA("缺少【TODO列表】");
        return false;
    }
    
    //第五项 问题列表检查
    if (std::string::npos == fields[8].find("问题列表"))
    {
        OutputDebugStringA("缺少【问题列表】");
        return false;
    }
    if (std::string::npos == fields[9].find("fixes #") &&
        std::string::npos == fields[9].find("refs #"))
    {
        OutputDebugStringA("【问题列表】内容不对");
        return false;
    }
    std::string issueId = fields[9].substr(fields[9].find("#"));
    
    if (!isDigit(issueId))
    {
        OutputDebugStringA("问题号为非数字");
        return false;
    }

    return true;
}

int main(int argc, char** argv)
{
    if (argc < 3)
    {
        return 0;
    }

    std::string svnlookpath = "";
    getSvnBinPath(svnlookpath);
    std::string cmd = "\"" + svnlookpath + "svnlook.exe\" log \"" + argv[1] + "\" -t " + argv[2];

    std::string commitLogs = "";
    getSvnLog(cmd.c_str(), commitLogs);

    if (!checkSvnLog(commitLogs))
    {
        std::cerr << commitfmtlogs;
        return 1;
    }

    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值