C++ 小工具一键解决SVN Clean Up 失败的问题

 参考文章:

  1.http://blog.csdn.net/luochao_tj/article/details/46358145

  2.http://blog.csdn.net/segen_jaa/article/details/7938959

可执行文件地址

  http://pan.baidu.com/s/1nvi7kW5

使用方法:

  下载压缩包,解压出可执行文件 SvnCleanUp.exe (Debug 和 Release 均可),放到SVN目录下面,双击运行即可.

完整VS工程地址:http://pan.baidu.com/s/1skECVDF 提取码 : lk5e

原理:

  TortoiseSVN 把项目的cleanup信息和lock信息放在了.svn目录下的wd.db文件里面,这是一个sqlite数据库文件,如果手动CleanUp失败,我们只需要杀掉占用这个文件的SVN进程,然后把这个文件中的 WC_LOCK 和 WORK_QUEUE 表清空就好了.

sqlite3源码文件官网地址:https://www.sqlite.org/2017/sqlite-amalgamation-3160100.zip 

主要逻辑代码:

#include <stdint.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <io.h>
#include <windows.h>
#include <tlhelp32.h>
#include "sqlite3/sqlite3.h"

struct ProcessData
{
    std::string name;
    int32_t id;
};

void ScanWCDBFiles(const std::string &startPath, std::vector<std::string> &files, const std::string &dbFileName);
int32_t CleanOneDB(const std::string &dbFile);
int32_t DeleteCallback(void *NotUsed, int argc, char **argv, char **azColName);

void GetAllProcess(std::vector<ProcessData> &processes);
bool KillProcessByID(int32_t pid);

int32_t main(int32_t argc, char *argv[])
{
    int32_t ret = 0;
    // kill all TSVN* processes
    const char *svnProcesses = "TSVN";
    std::vector<ProcessData> processes;
    GetAllProcess(processes);
    for (const ProcessData &p : processes)
    {
        ret = p.name.find(svnProcesses);
        if (ret >= 0)
        {
            printf("kill %s
", p.name.c_str());
            if (!KillProcessByID(p.id))
            {
                printf("	failed!
");
            }
        }
    }
    int32_t succCount = 0, failCount = 0;
    std::vector<std::string> files;
    printf("scanning...
");
    ScanWCDBFiles(".", files, "wc.db");
    for (const std::string &file : files)
    {
        printf("cleaning [%s]
", file.c_str());
        ret = CleanOneDB(file);
        if (ret == S_OK)
        {
            ++succCount;
        }
        else
        {
            printf("clean [%s] failed!!!
", file.c_str());
            ++failCount;
        }
    }
    printf("clean finished.succ(s) %d, fail(s) %d.
", succCount, failCount);
    getchar();
    return 0;
}

void ScanWCDBFiles(const std::string &startPath, std::vector<std::string> &files, const std::string &dbFileName)
{
    struct _finddata_t fileinfo;
    long hFile = 0;
    char tmpPath[MAX_PATH] = { 0 };
    sprintf_s(tmpPath, "%s\*", startPath.c_str());
    if ((hFile = _findfirst(tmpPath, &fileinfo)) == -1){ return; }
    do
    {
        if ((fileinfo.attrib &  _A_SUBDIR))
        {
            if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
            {
                sprintf_s(tmpPath, "%s\%s", startPath.c_str(), fileinfo.name);
                ScanWCDBFiles(tmpPath, files, dbFileName);
            }
        }
        else
        {
            if (dbFileName == fileinfo.name)
            {
                sprintf_s(tmpPath, "%s\%s", startPath.c_str(), fileinfo.name);
                files.push_back(tmpPath);
            }
        }
    } while (_findnext(hFile, &fileinfo) == 0);
    _findclose(hFile);
}

int32_t CleanOneDB(const std::string &dbFile)
{
    const char* tables[] =
    {
        "WC_LOCK",
        "WORK_QUEUE",
        "LOCK"
    };
    sqlite3 * pDB = NULL;
    int32_t ret = sqlite3_open(dbFile.c_str(), &pDB);
    if (ret != SQLITE_OK)
    {
        printf("	open db %s failed.
", dbFile.c_str());
        return ret;
    }
    for (int32_t i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i)
    {
        printf("	delete [%s]...
", tables[i]);
        char sql[256] = { 0 };
        sprintf_s(sql, "DELETE FROM %s;", tables[i]);
        char* errorMsg = NULL;
        ret = sqlite3_exec(pDB, sql, DeleteCallback, 0, &errorMsg);
        if (ret != SQLITE_OK)
        {
            printf("	select %s error![%s]
", tables[i], errorMsg);
            return ret;
        }
    }
    return 0;
}

int32_t DeleteCallback(void *NotUsed, int argc, char **argv, char **azColName)
{
    return 0;
}

void GetAllProcess(std::vector<ProcessData> &processes)
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        return;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        ProcessData data;
        data.name = pe.szExeFile;
        data.id = pe.th32ProcessID;
        processes.push_back(data);
        //printf("%-6d %s
", pe.th32ProcessID, pe.szExeFile);
    }
    CloseHandle(hSnapshot);
}

bool KillProcessByID(int32_t pid)
{
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
    if (hProcess == NULL) {
        return FALSE;
    }
    return TerminateProcess(hProcess, 0) != 0;
}

运行效果:

原文地址:https://www.cnblogs.com/tangxin-blog/p/6253442.html