UpdateGitRep.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. const fs = require("fs");
  2. const path = require("path");
  3. const child_process = require("child_process");
  4. let totalGitRepPath = new Set();
  5. const InputRepURLJsonName = "RepUrls.json";
  6. const PluginDirName = "Plugins";
  7. const dirNameBlackList = [
  8. "node_modules",
  9. "dist",
  10. "Build",
  11. "Content",
  12. "Binaries",
  13. "Config",
  14. "DerivedDataCache",
  15. "Intermediate",
  16. "pipeline",
  17. "Saved",
  18. ".vs",
  19. "ThirdParty",
  20. ]
  21. class RepItem
  22. {
  23. constructor(inPath, inUrl) {
  24. this.path = inPath; // 仓库名称
  25. this.url = inUrl; // 仓库地址
  26. }
  27. }
  28. class RepUrls{
  29. RepItems = [];
  30. }
  31. // 拉取 Git 仓库最新代码到指定路径
  32. function pullGitRepository(repositoryUrl, localPath) {
  33. if (fs.existsSync(localPath)) {
  34. // 切换路径 我发现不切换路径 经常会出现一些 bug
  35. process.chdir(localPath);
  36. // 路径已存在则拉取最新代码
  37. console.log(`Pull ${repositoryUrl} to ${localPath}...`);
  38. // 只检查 并提示 仍然尝试 Pull 操作
  39. checkEditFileRep(localPath);
  40. child_process.exec("git pull", localPath, (error, stdout, stderr) => {
  41. totalGitRepPath.delete(localPath);
  42. let logContent = `update repo dir ${localPath} update log -> ${stdout.trim()}, error -> ${stderr.trim()}, remain count = ${totalGitRepPath.size}`;
  43. if (error) {
  44. console.log('\x1B[31m%s\x1B[0m', logContent);
  45. }
  46. else {
  47. console.log(logContent);
  48. }
  49. });
  50. } else {
  51. // 路径不存在则克隆仓库
  52. console.log(`Clone ${repositoryUrl} to ${localPath}...`);
  53. child_process.exec(`git clone ${repositoryUrl} ${localPath}`, (error, stdout, stderr) => {
  54. let logContent = `clone repo dir ${localPath} update log -> ${stdout.trim()}, error -> ${stderr.trim()}`;
  55. if (error) {
  56. console.log("'\x1B[31m%s\x1B[0m',", logContent);
  57. }else{
  58. console.log(logContent);
  59. }
  60. });
  61. }
  62. }
  63. // 获取路径下所有文件夹
  64. function getAllChildrenDir(inPath)
  65. {
  66. if(inPath === undefined || inPath === null || !fs.existsSync(inPath)) {
  67. return [];
  68. }
  69. return fs.readdirSync(inPath, { withFileTypes: true }).filter(dirent => dirent.isDirectory()).map(dirent => dirent.name);
  70. }
  71. // 获取路径下所有文件
  72. function getAllChildrenFile(inPath)
  73. {
  74. if(inPath === undefined || inPath === null || !fs.existsSync(inPath)) {
  75. return [];
  76. }
  77. return fs.readdirSync(inPath, { withFileTypes: true }).filter(dirent => dirent.isFile()).map(dirent => dirent.name);
  78. }
  79. // 判断是否存在被修改的文件
  80. function checkEditFileRep(inPath)
  81. {
  82. if(inPath === undefined || inPath === null || !fs.existsSync(inPath)) {
  83. return false;
  84. }
  85. try {
  86. // `git -C "${inPath}" status --porcelain`,
  87. const output = child_process.execSync(
  88. `git -C "${inPath}" diff --name-only`,
  89. { encoding: 'utf-8' }
  90. );
  91. if(output.trim().length > 0)
  92. {
  93. console.log("'\x1B[31m%s\x1B[0m',", `${inPath} 存在被修改的文件 无法更新 使用 git restore 还原文件: ${output.trim()}`);
  94. totalGitRepPath.delete(inPath);
  95. }
  96. return output.trim().length <= 0;
  97. } catch (error) {
  98. console.error(`检查子目录失败: ${error.message}`);
  99. return false;
  100. }
  101. }
  102. function findAllGitRep(inPath)
  103. {
  104. console.log(`find path: ${inPath}`);
  105. let childrenDirs = getAllChildrenDir(inPath);
  106. if(childrenDirs.indexOf(".git") !== -1) {
  107. // 如果当前目录下有 .git 目录,则认为是一个 Git 仓库
  108. totalGitRepPath.add(inPath);
  109. }
  110. childrenDirs.forEach((dir) => {
  111. if(!dir || dir.trim().startsWith(".") || dirNameBlackList.includes(dir.trim())) {
  112. // 跳过隐藏目录
  113. return;
  114. }
  115. // console.log(`Checking directory: ${dir} in ${inPath}`);
  116. let childPath = path.join(inPath, dir);
  117. findAllGitRep(childPath);
  118. });
  119. }
  120. function updateAllRep(allPath)
  121. {
  122. allPath.forEach((inPath) => {
  123. if(inPath === undefined)
  124. {
  125. return;
  126. }
  127. pullGitRepository("", inPath);
  128. });
  129. }
  130. function updateRep()
  131. {
  132. let rootPath = __dirname;
  133. findAllGitRep(rootPath);
  134. updateAllRep(totalGitRepPath);
  135. }
  136. function cloneRep()
  137. {
  138. let rootPath = __dirname;
  139. let inputRepURLJsonFile = path.join(rootPath, InputRepURLJsonName);
  140. if(!fs.existsSync(inputRepURLJsonFile)) {
  141. let temp = new RepUrls();
  142. temp.RepItems = [new RepItem("cpp", "https://xxx.com/test/url.git")];
  143. fs.writeFileSync(inputRepURLJsonFile, JSON.stringify(temp, null, 4), "utf-8");
  144. console.error(`找不到 ${InputRepURLJsonName} 文件,已生成该文件,请填充内容`);
  145. return;
  146. }
  147. let repUrls = JSON.parse(fs.readFileSync(inputRepURLJsonFile, "utf-8"));
  148. repUrls.RepItems.forEach((item) => {
  149. let url = item.url;
  150. let relativePath = item.path;
  151. if(!url || url.trim() === "") {
  152. console.error(`无效的 Git 仓库 URL: ${url}`);
  153. return;
  154. }
  155. let locationPath = path.join(rootPath, PluginDirName, relativePath);
  156. let localPath = path.join(locationPath, path.basename(url, ".git"));
  157. pullGitRepository(url, localPath);
  158. });
  159. }
  160. function main()
  161. {
  162. if(process.argv.length < 3) {
  163. console.log("请输入 clone 或者 update 来选择下载或更新 Git 仓库");
  164. return;
  165. }
  166. let param = process.argv[2].toLowerCase();
  167. if(param === "update") {
  168. // 更新 Git 仓库
  169. updateRep();
  170. }
  171. else if(param === "clone") {
  172. // 克隆 Git 仓库
  173. cloneRep();
  174. }
  175. else {
  176. console.error(`无效的参数 "${param}",请输入 clone 或 update`);
  177. return;
  178. }
  179. }
  180. main();