monorepo-next 11.1.0 → 11.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/package.json +4 -1
  2. package/src/fs.js +36 -0
  3. package/src/git.js +66 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monorepo-next",
3
- "version": "11.1.0",
3
+ "version": "11.3.0",
4
4
  "description": "Detach monorepo packages from normal linking",
5
5
  "bin": {
6
6
  "next": "bin/next.js"
@@ -66,9 +66,11 @@
66
66
  "glob": "^8.0.0",
67
67
  "inquirer": "^9.0.0",
68
68
  "js-yaml": "^4.0.0",
69
+ "lockfile": "^1.0.4",
69
70
  "minimatch": "^9.0.0",
70
71
  "npm-packlist": "^8.0.0",
71
72
  "rfc6902": "^5.0.0",
73
+ "sanitize-filename": "^1.6.3",
72
74
  "semver": "^7.5.3",
73
75
  "standard-version": "9.5.0",
74
76
  "superset": "^2.0.1",
@@ -79,6 +81,7 @@
79
81
  "@crowdstrike/commitlint": "^7.0.0",
80
82
  "chai": "^4.2.0",
81
83
  "chai-as-promised": "^7.1.1",
84
+ "chai-fs": "^2.0.0",
82
85
  "common-tags": "^1.8.2",
83
86
  "eslint": "^8.0.0",
84
87
  "eslint-config-crowdstrike": "10.1.0",
package/src/fs.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = { ...require('fs'), ...require('fs').promises };
4
4
  const { EOL } = require('os');
5
+ const { dirname } = require('path');
5
6
 
6
7
  async function replaceFile(path, callback) {
7
8
  let oldContents = await fs.readFile(path, 'utf8');
@@ -30,7 +31,42 @@ async function replaceJsonFile(path, callback) {
30
31
  });
31
32
  }
32
33
 
34
+ /**
35
+ * @param {string} path
36
+ */
37
+ async function safeReadFile(path) {
38
+ try {
39
+ return await fs.readFile(path, 'utf8');
40
+ } catch (err) {
41
+ if (err.code !== 'ENOENT') {
42
+ throw err;
43
+ }
44
+
45
+ return null;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * @param {string} path
51
+ */
52
+ async function ensureDir(path) {
53
+ await fs.mkdir(path, { recursive: true });
54
+ }
55
+
56
+ /**
57
+ * @param {string} path
58
+ * @param {string} data
59
+ */
60
+ async function ensureWriteFile(path, data) {
61
+ await ensureDir(dirname(path));
62
+
63
+ await fs.writeFile(path, data);
64
+ }
65
+
33
66
  module.exports = {
34
67
  replaceFile,
35
68
  replaceJsonFile,
69
+ safeReadFile,
70
+ ensureDir,
71
+ ensureWriteFile,
36
72
  };
package/src/git.js CHANGED
@@ -2,11 +2,18 @@
2
2
 
3
3
  const execa = require('execa');
4
4
  const debug = require('./debug').extend('git');
5
+ const sanitize = require('sanitize-filename');
6
+ const path = require('path');
7
+ const { safeReadFile, ensureDir, ensureWriteFile } = require('./fs');
8
+ const { promisify } = require('util');
9
+ const lockfile = require('lockfile');
10
+ const lock = promisify(lockfile.lock);
11
+ const unlock = promisify(lockfile.unlock);
5
12
 
6
13
  let cache = {};
7
14
 
8
15
  function getCacheKey(args, cwd) {
9
- return [cwd, ...args].join();
16
+ return sanitize([cwd, ...args].join());
10
17
  }
11
18
 
12
19
  async function git(args, options) {
@@ -15,27 +22,76 @@ async function git(args, options) {
15
22
  cached,
16
23
  } = options;
17
24
 
18
- let stdout;
25
+ let cacheKey;
26
+ let lockFilePath;
19
27
 
20
- let cacheKey = getCacheKey(args, cwd);
28
+ if (cached) {
29
+ cacheKey = getCacheKey(args, cwd);
30
+
31
+ if (cacheKey in cache) {
32
+ debug('Git cache hit.');
33
+
34
+ return cache[cacheKey];
35
+ }
36
+
37
+ if (cached !== true) {
38
+ lockFilePath = path.join(cached, `${cacheKey}.lock`);
39
+
40
+ await ensureDir(cached);
41
+
42
+ debug(`Waiting for git lock at ${lockFilePath}.`);
43
+
44
+ await lock(lockFilePath, { wait: 10 * 60e3 });
45
+
46
+ debug(`Acquired git lock at ${lockFilePath}.`);
47
+ }
48
+ }
49
+
50
+ try {
51
+ let cachedFilePath;
52
+
53
+ if (cached) {
54
+ if (cached !== true) {
55
+ cachedFilePath = path.join(cached, cacheKey);
56
+
57
+ let _cache = await safeReadFile(cachedFilePath);
58
+
59
+ if (_cache !== null) {
60
+ debug('Git cache hit.');
61
+
62
+ cache[cacheKey] = _cache;
63
+
64
+ return _cache;
65
+ }
66
+ }
67
+
68
+ debug('Git cache miss.');
69
+ }
21
70
 
22
- if (cached && cacheKey in cache) {
23
- stdout = cache[cacheKey];
24
- } else {
25
71
  debug(args, options);
26
72
 
27
- stdout = (await execa('git', args, {
73
+ let { stdout } = await execa('git', args, {
28
74
  cwd,
29
- })).stdout;
75
+ });
30
76
 
31
77
  if (cached) {
32
78
  cache[cacheKey] = stdout;
79
+
80
+ if (cached !== true) {
81
+ await ensureWriteFile(cachedFilePath, stdout);
82
+ }
33
83
  }
34
84
 
35
85
  debug(stdout);
36
- }
37
86
 
38
- return stdout;
87
+ return stdout;
88
+ } finally {
89
+ if (lockFilePath) {
90
+ await unlock(lockFilePath);
91
+
92
+ debug(`Released git lock at ${lockFilePath}.`);
93
+ }
94
+ }
39
95
  }
40
96
 
41
97
  async function getCurrentBranch(cwd) {