UpdateGitRep.js 5.6 KB

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