utils.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. const { GitProcess } = require('dugite');
  2. const fs = require('fs');
  3. const os = require('os');
  4. const path = require('path');
  5. const ELECTRON_DIR = path.resolve(__dirname, '..', '..');
  6. const SRC_DIR = path.resolve(ELECTRON_DIR, '..');
  7. const RELEASE_BRANCH_PATTERN = /(\d)+-(?:(?:[0-9]+-x$)|(?:x+-y$))/;
  8. // TODO(main-migration): Simplify once main branch is renamed
  9. const MAIN_BRANCH_PATTERN = /^(main|master)$/;
  10. const ORIGIN_MAIN_BRANCH_PATTERN = /^origin\/(main|master)$/;
  11. require('colors');
  12. const pass = '✓'.green;
  13. const fail = '✗'.red;
  14. function getElectronExec () {
  15. const OUT_DIR = getOutDir();
  16. switch (process.platform) {
  17. case 'darwin':
  18. return `out/${OUT_DIR}/Electron.app/Contents/MacOS/Electron`;
  19. case 'win32':
  20. return `out/${OUT_DIR}/electron.exe`;
  21. case 'linux':
  22. return `out/${OUT_DIR}/electron`;
  23. default:
  24. throw new Error('Unknown platform');
  25. }
  26. }
  27. function getOutDir (options = {}) {
  28. const shouldLog = options.shouldLog || false;
  29. const presetDirs = ['Testing', 'Release', 'Default', 'Debug'];
  30. if (options.outDir || process.env.ELECTRON_OUT_DIR) {
  31. const outDir = options.outDir || process.env.ELECTRON_OUT_DIR;
  32. const outPath = path.resolve(SRC_DIR, 'out', outDir);
  33. // Check that user-set variable is a valid/existing directory
  34. if (fs.existsSync(outPath)) {
  35. if (shouldLog) console.log(`OUT_DIR is: ${outDir}`);
  36. return outDir;
  37. }
  38. // Throw error if user passed/set nonexistent directory.
  39. throw new Error(`${outDir} directory not configured on your machine.`);
  40. } else {
  41. for (const buildType of presetDirs) {
  42. const outPath = path.resolve(SRC_DIR, 'out', buildType);
  43. if (fs.existsSync(outPath)) {
  44. if (shouldLog) console.log(`OUT_DIR is: ${buildType}`);
  45. return buildType;
  46. }
  47. }
  48. }
  49. // If we got here, it means process.env.ELECTRON_OUT_DIR was not
  50. // set and none of the preset options could be found in /out, so throw
  51. throw new Error(`No valid out directory found; use one of ${presetDirs.join(',')} or set process.env.ELECTRON_OUT_DIR`);
  52. }
  53. function getAbsoluteElectronExec () {
  54. return path.resolve(SRC_DIR, getElectronExec());
  55. }
  56. async function handleGitCall (args, gitDir) {
  57. const details = await GitProcess.exec(args, gitDir);
  58. if (details.exitCode === 0) {
  59. return details.stdout.replace(/^\*|\s+|\s+$/, '');
  60. } else {
  61. const error = GitProcess.parseError(details.stderr);
  62. console.log(`${fail} couldn't parse git process call: `, error);
  63. process.exit(1);
  64. }
  65. }
  66. async function getCurrentBranch (gitDir) {
  67. let branch = await handleGitCall(['rev-parse', '--abbrev-ref', 'HEAD'], gitDir);
  68. if (!MAIN_BRANCH_PATTERN.test(branch) && !RELEASE_BRANCH_PATTERN.test(branch)) {
  69. const lastCommit = await handleGitCall(['rev-parse', 'HEAD'], gitDir);
  70. const branches = (await handleGitCall([
  71. 'branch',
  72. '--contains',
  73. lastCommit,
  74. '--remote'
  75. ], gitDir)).split('\n');
  76. branch = branches.find(b => MAIN_BRANCH_PATTERN.test(b.trim()) || ORIGIN_MAIN_BRANCH_PATTERN.test(b.trim()) || RELEASE_BRANCH_PATTERN.test(b.trim()));
  77. if (!branch) {
  78. console.log(`${fail} no release branch exists for this ref`);
  79. process.exit(1);
  80. }
  81. if (branch.startsWith('origin/')) branch = branch.substr('origin/'.length);
  82. }
  83. return branch.trim();
  84. }
  85. function chunkFilenames (filenames, offset = 0) {
  86. // Windows has a max command line length of 2047 characters, so we can't
  87. // provide too many filenames without going over that. To work around that,
  88. // chunk up a list of filenames such that it won't go over that limit when
  89. // used as args. Other platforms may have higher limits, but 4095 might be
  90. // the limit on Linux systems according to `termios(3)`, so cap it there.
  91. const MAX_FILENAME_ARGS_LENGTH =
  92. (os.platform() === 'win32' ? 2047 : 4095) - offset;
  93. return filenames.reduce(
  94. (chunkedFilenames, filename) => {
  95. const currChunk = chunkedFilenames[chunkedFilenames.length - 1];
  96. const currChunkLength = currChunk.reduce(
  97. (totalLength, _filename) => totalLength + _filename.length + 1,
  98. 0
  99. );
  100. if (currChunkLength + filename.length + 1 > MAX_FILENAME_ARGS_LENGTH) {
  101. chunkedFilenames.push([filename]);
  102. } else {
  103. currChunk.push(filename);
  104. }
  105. return chunkedFilenames;
  106. },
  107. [[]]
  108. );
  109. }
  110. module.exports = {
  111. chunkFilenames,
  112. getCurrentBranch,
  113. getElectronExec,
  114. getOutDir,
  115. getAbsoluteElectronExec,
  116. ELECTRON_DIR,
  117. SRC_DIR
  118. };