UpdateGitRep.js 5.6 KB

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