git,gitea-tool-creatGiteaEmptyRepDir
- 电脑硬件
- 2025-08-27 21:09:02

文章目录 git,gitea - tool - creat Gitea Empty Rep Dir概述笔记编译输出使用方式生成后的子库目录使用说明 用写好的bat来建立gitea库的步骤step1step2step3step4step5step6other工具源码END git,gitea - tool - creat Gitea Empty Rep Dir 概述
现在想采用小库的方式来使用gitea. 这样就涉及到开小库时,要用gitea命令行来做新的小库的目录。 以前做了实验,这样的脚本已经有了。 但是以这些脚本为模板,建立新的gitea库的目录时,需要改多个脚本中的绝对路径,很繁琐,容易错。 如果用git bash, 写一个脚本(e.g. sed), 来替换.bat中的绝对路径,控制的不细致。如果想控制的细致,对bash编程也没有那么熟悉。 那就用C来手搓一个工具,花了1天,挺好使的。
笔记 编译输出就一个 creatGiteaEmptyRepDir.exe,拷贝到自己的gitea库的根目录
使用方式 creatGiteaEmptyRepDir.exe <新的小库名称 e.g. my_test>因为操作的是gitea小库的初始目录,为了安全,如果库目录中已经有预期的文件夹,不会再操作,会提示并退出。没啥风险。 生成完的目录在./creatGiteaEmptyRepDir_out中的子目录中(e.g. ./creatGiteaEmptyRepDir_out/rep_my_test), 由用户(me)手工拷贝到gitea库的根目录,规避风险。
生成后的子库目录 使用说明 用写好的bat来建立gitea库的步骤 step1关掉其他gitea控制台(因为端口都是3000)
运行 a1_run_gitea_rep_console.bat, 等待服务启动完成
step2在浏览器中运行网页 http://localhost:3000/
选择sqlite3作为数据库, 将网页拉到底部,点击"立即安装"
等待安装完成,出现登录页面为止。
step3建立库的用户
运行 a2_create_rep_user_pwd.bat 建立库用户
运行 b1_list_rep_user.bat 查看用户是否建立成功
step4登录gitea库网页
在网页右上角的用户头像处点击下拉列表,选择设置 => SSH密钥 => 增加密钥,将生成在 C:\Users\me\.ssh 中的公钥id_rsa.pub内容增加未SSH密钥
创建仓库(只需要给出仓库名), 网页拉到尾部,点击"创建仓库"
step5复制仓库地址, 好像本地ssh库地址不好使,只能复制http的库地址。
step6迁出库地址。
首次迁出时,有警告,说库是空的,这是正常的,不用理会。
正常git提交。
other如果要修改用户名和口令, 执行 b2_modify_rep_user_pwd.bat
如果要检查库的健康度, 执行 b3_run_gitea_doctor.bat
如果要查看gitea版本,执行 b4_show_git_env_info.bat
如果要打开一个cmd窗口, 执行 c1_call_cmd_here.bat
如果要手工执行git命令, 执行 c2_env_git.bat
工具源码VS2019 c++ console 800行代码
// @file creatGiteaEmptyRepDir.cpp // 生成gitea用的库目录脚本, 用户自己拷贝生成的子目录(e.g. <./creatGiteaEmptyRepDir_out/sub_rep_dir>)到总的库目录(e.g. E:\my_git_rep), 防止意外操作或程序bug #include <windows.h> #include <iostream> #include <sstream> #include <iomanip> #include <fstream> #include "resource.h" #define MY_VER "1.0.0.0" #define DIR_OUT "creatGiteaEmptyRepDir_out" // 目录默认都要带尾巴上的\\ #define SET_GIT_GITEA_PATH "set PATH=C:\\Program Files\\Git\\bin;C:\\Program Files\\Git\\cmd;C:\\soft\\gitea;%PATH%" #define MY_DEFAULT_GITEA_REP_ROOT_DIR "E:\\my_git_rep\\" #define GIT_USER_NAME "name" #define GIT_USER_PWD "password" #define GIT_USER_EMAIL "me@x " void usage(); void show_error(const char* psz_reason); bool check_param(int argc, char** argv); bool is_dir_exist(const char* psz_path_name); std::string get_cur_dir_path_name(); bool create_dir(const char* pszPath); std::string Wstring2String(std::wstring strW); bool string_find(const std::string& strA, char c); bool write_res_file(const char* psz_write_to); bool write_ascii_file(const std::string& strFileName, const std::string& strText); bool DoTask(); bool DoTask_a1_run_gitea_rep_console_bat();// a1_run_gitea_rep_console.bat bool DoTask_a2_create_rep_user_pwd_bat();// a2_create_rep_user_pwd.bat bool DoTask_b1_modify_rep_user_pwd_bat();// b1_list_rep_user.bat bool DoTask_b2_modify_rep_user_pwd_bat();// b2_modify_rep_user_pwd.bat bool DoTask_b3_run_gitea_doctor_bat();// b3_run_gitea_doctor.bat bool DoTask_b4_show_git_env_info_bat();// b4_show_git_env_info.bat bool DoTask_c1_call_cmd_here_bat();// c1_call_cmd_here.bat bool DoTask_c2_env_git_bat();// c2_env_git.bat bool DoTask_Readme_md(); // readme.md(在资源中, BIN_RES/IDR_BIN_RES_README_MD) std::string g_new_sub_rep_name; std::string g_cur_dir; std::string g_dir_out; // 当前目录下的输出目录 std::string g_dir_out_obj; // 在当前输出目录中的目标目录, 需要用户手工拷贝到总库目录下 e.g. debug/out/rep_my_test std::string g_dir_out_obj_rep; // 在当前输出目录中的目标目录中的库目录中的实际库目录 e.g. debug/out/rep_my_test/my_test std::string g_dir_obj; // 要拷贝到的总目录下的子库目录 std::string g_dir_obj_rep; // 要拷贝到的总目录下的子库目录中的gitea库目录 int main(int argc, char** argv) { do { if (!check_param(argc, argv)) { usage(); break; } if (!DoTask()) { break; } printf("do task ok\r\n"); } while (false); printf("\r\n"); printf("END\r\n"); system("pause"); return 0; } bool DoTask() { bool b_rc = false; do { if (!DoTask_a1_run_gitea_rep_console_bat()) { break; } if (!DoTask_a2_create_rep_user_pwd_bat()) { break; } if (!DoTask_b1_modify_rep_user_pwd_bat()) { break; } if (!DoTask_b2_modify_rep_user_pwd_bat()) { break; } if (!DoTask_b3_run_gitea_doctor_bat()) { break; } if (!DoTask_b4_show_git_env_info_bat()) { break; } if (!DoTask_c1_call_cmd_here_bat()) { break; } if (!DoTask_c2_env_git_bat()) { break; } if (!DoTask_Readme_md()) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_a1_run_gitea_rep_console_bat() {// a1_run_gitea_rep_console.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "a1_run_gitea_rep_console.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; // @echo off ss << "@echo off\r\n"; // rem a1_run_gitea_rep_console.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH=C:\\Program Files\\Git\\bin;C:\\Program Files\\Git\\cmd;C:\\soft\\gitea;%PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // call gitea --work - path E : \my_git_rep\rep_my_template\my_template ss << "call gitea --work-path "; ss << g_dir_obj_rep << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_a2_create_rep_user_pwd_bat() {// a2_create_rep_user_pwd.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "a2_create_rep_user_pwd.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; // @echo off ss << "@echo off\r\n"; // rem a2_create_rep_user_pwd.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // call gitea --work - path E : \my_git_rep\rep_my_template\my_template ss << "call gitea --work-path "; ss << g_dir_obj_rep << " "; // admin user create --admin --username name --password pwd --email me@x --access-token ss << "admin user create --admin --username " << GIT_USER_NAME << " "; ss << "--password " << GIT_USER_PWD << " "; ss << "--email " << GIT_USER_EMAIL << " --access-token\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_b1_modify_rep_user_pwd_bat() {// b1_list_rep_user.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "b1_list_rep_user.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem b1_list_rep_user.bat ss << "rem b1_list_rep_user.bat" << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // call gitea --work - path E : \my_git_rep\rep_my_tools\my_tools admin user list ss << "call gitea --work-path " << g_dir_obj_rep << " admin user list" << "\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_b2_modify_rep_user_pwd_bat() {// b2_modify_rep_user_pwd.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "b2_modify_rep_user_pwd.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem b1_modify_rep_user_pwd.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // call gitea --work - path E : \my_git_rep\rep_my_template\my_template admin user change-password -u name -p pwd11111 // 修改密码时, 密码的最小长度要为8 ss << "call gitea --work-path " << g_dir_obj_rep << " "; ss << "admin user change-password -u " << GIT_USER_NAME << " "; ss << "-p " << " " << GIT_USER_PWD << "\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_b3_run_gitea_doctor_bat() {// b3_run_gitea_doctor.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "b3_run_gitea_doctor.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem b2_run_gitea_doctor.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // echo next, list gitea doctor runing ss << "echo next, list gitea doctor runing" << "\r\n"; // call gitea --work - path E : \my_git_rep\rep_my_template\my_template doctor check ss << "call gitea --work-path " << g_dir_obj_rep << " "; ss << "doctor check" << "\r\n"; // echo END ss << "echo END" << "\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_b4_show_git_env_info_bat() {// b4_show_git_env_info.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "b4_show_git_env_info.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem b4_show_git_env_info.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // gitea --version ss << "gitea --version" << "\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_c1_call_cmd_here_bat() {// c1_call_cmd_here.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "c1_call_cmd_here.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem c1_call_cmd_here.bat ss << "rem " << pszShortFileName << "\r\n"; // call cmd.exe ss << "call cmd.exe" << "\r\n"; // PAUSE ss << "PAUSE" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_c2_env_git_bat() {// c2_env_git.bat bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "c2_env_git.bat"; do { strFileName = g_dir_out_obj; strFileName += pszShortFileName; std::stringstream ss; //@echo off ss << "@echo off" << "\r\n"; // rem c2_env_git.bat ss << "rem " << pszShortFileName << "\r\n"; // set PATH = C:\Program Files\Git\bin; C:\Program Files\Git\cmd; C:\soft\gitea; % PATH% ss << SET_GIT_GITEA_PATH << "\r\n"; // call cmd.exe ss << "call cmd.exe" << "\r\n"; strText = ss.str(); if (!write_ascii_file(strFileName, strText)) { break; } b_rc = true; } while (false); return b_rc; } bool DoTask_Readme_md() {// readme.md(在资源中, BIN_RES/IDR_BIN_RES_README_MD) bool b_rc = false; std::string strFileName; std::string strText; const char* pszShortFileName = "readme.md"; do { // 将嵌入资源中的readme.md写入输出文件夹中的库目录中 strFileName = g_dir_out_obj; strFileName += pszShortFileName; if (!write_res_file(strFileName.c_str())) { break; } b_rc = true; } while (false); return b_rc; } bool write_res_file(const char* psz_write_to) { // 定义资源标识符(根据实际资源头文件中的定义) const TCHAR* lpType = TEXT("BIN_RES"); // 自定义资源类型 const int resId = IDR_BIN_RES_README_MD; // 资源ID if (NULL == psz_write_to) return false; // 获取模块句柄 HMODULE hModule = GetModuleHandle(NULL); if (!hModule) return false; // 查找资源 HRSRC hRes = FindResource(hModule, MAKEINTRESOURCE(resId), lpType); if (!hRes) return false; // 获取资源大小 DWORD dwSize = SizeofResource(hModule, hRes); if (dwSize == 0) return false; // 加载资源 HGLOBAL hGlobal = LoadResource(hModule, hRes); if (!hGlobal) return false; // 锁定资源获取指针 LPVOID lpResData = LockResource(hGlobal); if (!lpResData) return false; // 创建输出文件 HANDLE hFile = CreateFileA(psz_write_to, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return false; // 写入文件 DWORD dwWritten = 0; BOOL bResult = WriteFile(hFile, lpResData, dwSize, &dwWritten, NULL); // 清理资源 CloseHandle(hFile); FreeResource(hGlobal); return (bResult && (dwWritten == dwSize)); } bool check_param(int argc, char** argv) { bool b_rc = false; std::string str_msg; char* psz = NULL; do { if (2 != argc) { break; } // g_new_sub_rep_name psz = argv[1]; if ((NULL == psz) || (strlen(psz) <= 0)) { std::stringstream ss; ss << "参数1是子库名称, 不能为空"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } g_new_sub_rep_name = psz; if (string_find(g_new_sub_rep_name, '/') || string_find(g_new_sub_rep_name, '\\')) { std::stringstream ss; ss << "新建的子库名称不能包含路径字符"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } g_cur_dir = get_cur_dir_path_name(); if (!is_dir_exist(g_cur_dir.c_str())) { break; } // param1 = for_test g_dir_obj = MY_DEFAULT_GITEA_REP_ROOT_DIR; g_dir_obj += "rep_"; g_dir_obj += g_new_sub_rep_name; g_dir_obj += "\\"; // E:\my_git_rep\rep_for_test\ g_dir_obj_rep = g_dir_obj; g_dir_obj_rep += g_new_sub_rep_name; g_dir_obj_rep += "\\"; // E:\my_git_rep\rep_for_test\for_test\ if (is_dir_exist(g_dir_obj.c_str())) { std::stringstream ss; ss << "总库下的子目录[" << g_dir_obj << "]已经存在, 为了安全, 请重新给定子库名称"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } g_dir_out = g_cur_dir; g_dir_out += DIR_OUT; g_dir_out += "\\"; // 如果输出目录不存在,就建立目录 if (!is_dir_exist(g_dir_out.c_str())) { // 建立输出目录 if (!create_dir(g_dir_out.c_str())) { std::stringstream ss; ss << "目录[" << g_dir_out << "]建立失败"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } } // 建立输出目录中的子库目录 g_dir_out_obj = g_dir_out; g_dir_out_obj += "rep_"; g_dir_out_obj += g_new_sub_rep_name; g_dir_out_obj += "\\"; if (!is_dir_exist(g_dir_out_obj.c_str())) { // 建立输出目录 if (!create_dir(g_dir_out_obj.c_str())) { std::stringstream ss; ss << "目录[" << g_dir_out << "]建立失败"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } } else { // 如果目录存在,就不干活了, 必须用户移走了目录,才能干活 std::stringstream ss; ss << "目录[" << g_dir_out_obj << "]已经存在,请移动目录到总库目录 或者 删除输出目录中的子库目录再运行程序"; str_msg = ss.str(); show_error(str_msg.c_str()); break; } b_rc = true; } while (false); if (!b_rc) { show_error("命令行参数错误"); } return b_rc; } std::string get_cur_dir_path_name() { // 使用MAX_PATH+1确保足够缓冲区 char buffer[MAX_PATH + 1] = { 0 }; // 获取EXE完整路径(ANSI版本) DWORD ret = GetModuleFileNameA(nullptr, buffer, MAX_PATH); if (ret == 0 || ret == MAX_PATH) { // 失败或路径过长 return ""; } // 反向查找最后一个路径分隔符 char* last_sep = strrchr(buffer, '\\'); if (last_sep == nullptr) { // 异常情况处理 return ""; } // 截断到目录部分(包含结尾反斜杠) *(last_sep + 1) = '\0'; // 转换为标准字符串并返回 return std::string(buffer); } bool is_dir_exist(const char* psz_path_name) { if (!psz_path_name) return false; const char* path = psz_path_name; struct _stat fileStat; if (_stat(path, &fileStat) == 0) { return (fileStat.st_mode & _S_IFDIR) != 0; } return false; } void show_error(const char* psz_reason) { printf("error"); if ((NULL != psz_reason) && (strlen(psz_reason) > 0)) { printf(" : %s\r\n", psz_reason); } else { printf("\r\n"); } printf("\r\n"); } void usage() { printf("-------- creatGiteaEmptyRepDir v%s --------\r\n", MY_VER); printf("usage :\r\n"); printf("\t<THE_EXE> <gitea_rep_name>\r\n"); printf("\tgitea_rep_name e.g. like my_gitea_study_rep\r\n"); printf("function :\r\n"); printf("\t生成gitea用的库目录脚本\r\n"); printf("\t用户自己拷贝生成的子目录(e.g. <./creatGiteaEmptyRepDir_out/sub_rep_dir>)\r\n"); printf("\t到总的库目录(e.g.E:/my_git_rep), 防止意外操作或程序bug\r\n"); } bool create_dir(const char* pszPath) { if (!pszPath || *pszPath == '\0') { SetLastError(ERROR_INVALID_PARAMETER); return false; } // 转换UTF-8到宽字符(支持中文路径) const int bufferSize = MultiByteToWideChar(CP_UTF8, 0, pszPath, -1, nullptr, 0); if (bufferSize == 0) return false; std::wstring wPath(bufferSize, L'\0'); if (MultiByteToWideChar(CP_UTF8, 0, pszPath, -1, &wPath[0], bufferSize) == 0) { return false; } // 检查路径有效性 DWORD attrs = GetFileAttributesW(wPath.c_str()); if (attrs != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { SetLastError(ERROR_ALREADY_EXISTS); return false; } SetLastError(ERROR_FILE_EXISTS); return false; } // 创建目录(含基础权限) SECURITY_ATTRIBUTES sa = { sizeof(sa), nullptr, TRUE }; if (CreateDirectoryW(wPath.c_str(), &sa)) { return true; } // 错误处理(可扩展记录日志) const DWORD err = GetLastError(); if (err != ERROR_PATH_NOT_FOUND) { return false; } // 尝试创建父目录(可选递归) const std::wstring parentDir = wPath.substr(0, wPath.find_last_of(L'\\')); std::string parentDirA = Wstring2String(parentDir); if (!parentDir.empty() && create_dir(parentDirA.c_str())) { return CreateDirectoryW(wPath.c_str(), &sa) != 0; } return false; } std::string Wstring2String(std::wstring strW) { if (strW.empty()) return std::string(); // 计算转换后需要的缓冲区大小 int len = WideCharToMultiByte( CP_ACP, // 使用系统默认 ANSI 编码(如中文系统下为 GBK) 0, // 无特殊标志 strW.c_str(), // 输入宽字符串 (int)strW.size(), // 输入字符串长度(不含终止符) NULL, 0, NULL, NULL // 输出缓冲区和长度置空以计算所需空间 ); if (len == 0) return std::string(); // 直接操作 std::string 的缓冲区 std::string result; result.resize(len); WideCharToMultiByte( CP_ACP, 0, strW.c_str(), (int)strW.size(), &result[0], len, // 输出到 result 的缓冲区 NULL, NULL ); return result; } bool string_find(const std::string& strA, char c) { return strA.find(c) != std::string::npos; } bool write_ascii_file(const std::string& strFileName, const std::string& strText) { std::ofstream outFile; outFile.open(strFileName, std::ios::out | std::ios::trunc); // 覆盖模式写入 if (!outFile.is_open()) { // 检查文件是否成功打开 return false; } outFile << strText; // 写入内容 outFile.close(); // 显式关闭文件 return !outFile.fail(); // 返回写入是否成功 }; ENDgit,gitea-tool-creatGiteaEmptyRepDir由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“git,gitea-tool-creatGiteaEmptyRepDir”