用 lua 写 VisualSvn Server 的 hook

来源:互联网 发布:日本股票行情软件 编辑:程序博客网 时间:2024/06/03 22:41

VisualSvn 的 Repositories 下面,每个库都有hooks目录这里存放9种hook.

我比较关心post-commit,要限制文件扩展名,采用白名单.


hooks支持批处理和EXE,比如post-commit.bat或post-commit.exe放在Repositories\code\hooks下面,在提交后,svn server会自动调用,

如果程序返回0表示成功,返回1表示失败. 可以把错误信息写到stderr,server会把错误信息推送到客户端


批处理语法难懂,喜欢用lua.所以写个exe,转调到lua中,在lua中实现主要判断逻辑.


下面是c++代码

#define CP_GBK      (936)       // 简体中文code pagevoid Unicode_to_GBK(const wchar_t* in, size_t len, std::string& out){int bufferlen = (int)::WideCharToMultiByte(CP_GBK,0,in,(int)len,NULL,0,NULL,NULL);char* pBuffer = new char[bufferlen + 4];if ( NULL == pBuffer ){return;}int out_len = ::WideCharToMultiByte(CP_GBK,0,in,(int)len,pBuffer,bufferlen+2,NULL,NULL);   pBuffer[bufferlen] = '\0';out.assign( pBuffer, out_len );delete[] pBuffer;}static int getShortPathName(lua_State* L){const char* lpFullPath = luaL_checkstring(L, 1);char strShortPath[MAX_PATH] = {0};GetShortPathNameA(lpFullPath, strShortPath, MAX_PATH);lua_pushstring(L, strShortPath);return 1;}static int pathFindExtension(lua_State* L){lua_pushstring(L, PathFindExtensionA(luaL_checkstring(L, 1)));return 1;}int MainImpl(){int argc = 0;LPWSTR * argv = CommandLineToArgvW(GetCommandLine(), &argc);wchar_t* lpLuaFile = StrDup(argv[0]);PathRenameExtension(lpLuaFile, L".lua") ;int ret = 0;if (PathFileExists(lpLuaFile) && argv[1] && argv[2]){std::string strLuaFile;Unicode_to_GBK(lpLuaFile, wcslen(lpLuaFile), strLuaFile);lua_State* L = luaL_newstate();luaL_openlibs(L);lua_pushcfunction(L, getShortPathName);lua_setglobal(L, "getShortPathName");lua_pushcfunction(L, pathFindExtension);lua_setglobal(L, "pathFindExtension");if (luaL_dofile(L, strLuaFile.c_str()) == 0){lua_getglobal(L, "MainCheck");if(!lua_isfunction(L, -1)){fprintf(stderr, "could not find MainCheck function");return ret;}std::string strDir, strTxn;Unicode_to_GBK(argv[1], wcslen(argv[1]), strDir);Unicode_to_GBK(argv[2], wcslen(argv[2]), strTxn);lua_pushstring(L, strDir.c_str());lua_pushstring(L, strTxn.c_str());if (lua_pcall(L, 2, 1, 0) == 0){ret = lua_tointeger(L, -1);}else{fprintf(stderr, "%s", lua_tostring(L, -1));}}lua_close(L);}LocalFree(lpLuaFile);LocalFree(argv);return ret;}int main(){return MainImpl();}int __stdcall WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ){return MainImpl();}

下面是lua代码

local svn_look = [[C:\Program Files\VisualSVN Server\bin\svnlook.exe]] -- 通过svn_look返回提交的所有文件列表print = function(...)log = log or io.open([[D:\Repositories\code\hooks\pre-commit.log]], "w")for k, v in ipairs(arg) dolog:write(tostring(v), "\t")endlog:write("\n")end-- 白名单local allow_list = {-- c,c++[".c"] = true,[".cpp"] = true,[".h"] = true,[".cxx"] = true,[".hpp"] = true,[".aps"] = true,[".idl"] = true,-- vs[".sln"] = true,[".vcproj"] = true,[".dsw"] = true,-- other[".html"] = true,[".htm"] = true,[".xml"] = true,[".lua"] = true,[".txt"] = true,[".bat"] = true,-- res[".ico"] = true,[".rc"] = true,-- office[".doc"] = true,[".docx"] = true,[".ppt"] = true,[".pptx"] = true,--image[".jpg"] = true,[".png"] = true,[".gif"] = true,[".bmp"] = true,--xar[".cfg"] = true,}function MainCheck(dir, txn)print("MainCheck", dir, txn)local cmd = string.format("%s changed \"%s\" -t \"%s\"", getShortPathName(svn_look), dir, txn)print(cmd)local p = io.popen(cmd)for line in p:lines() doprint(line, line:sub(4), pathFindExtension(line:sub(4)))local ext = pathFindExtension(line:sub(4))if ext:len() ~= 0 and not allow_list[ext:lower()] thenio.stderr:write(ext:lower().. " 不允许提交")return 1endendlog:close()return 0end


用法:把生成的exe,改名为9中hook的任意一种,然后lua文件与exe同名,放在hooks目录下.


有编译好的文件,依赖vc2005和vc2008的运行时.

http://download.csdn.net/detail/gushiaoke/4341686

原创粉丝点击