@coderook/cli 0.8.0 → 0.9.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.
- package/dist/cli/src/config.js +32 -3
- package/package.json +4 -3
package/dist/cli/src/config.js
CHANGED
|
@@ -42,15 +42,44 @@ function configDirectory() {
|
|
|
42
42
|
}
|
|
43
43
|
const tokenFile = () => node_path_1.default.join(configDirectory(), "token");
|
|
44
44
|
const linksFile = () => node_path_1.default.join(configDirectory(), "links.json");
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Write a file only its owner can read, and atomically.
|
|
47
|
+
*
|
|
48
|
+
* The temporary name carries this process's own identity. Sharing one — as
|
|
49
|
+
* `${target}.tmp` did — means two runs at once write the same scratch file
|
|
50
|
+
* and then race to move it, which on Windows fails outright and elsewhere
|
|
51
|
+
* quietly hands one run the other's bytes.
|
|
52
|
+
*
|
|
53
|
+
* The move is retried briefly because Windows refuses a rename while another
|
|
54
|
+
* process still has the destination open, which during a race is ordinary
|
|
55
|
+
* rather than exceptional.
|
|
56
|
+
*/
|
|
46
57
|
async function writePrivate(target, body) {
|
|
47
58
|
await (0, promises_1.mkdir)(node_path_1.default.dirname(target), { recursive: true });
|
|
48
|
-
const temporary = `${target}.tmp`;
|
|
59
|
+
const temporary = `${target}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
49
60
|
await (0, promises_1.writeFile)(temporary, body, "utf8");
|
|
50
61
|
// Windows ignores the mode; on everything else this is what keeps the
|
|
51
62
|
// token out of other accounts' reach.
|
|
52
63
|
await (0, promises_1.chmod)(temporary, 0o600).catch(() => undefined);
|
|
53
|
-
|
|
64
|
+
try {
|
|
65
|
+
for (let attempt = 0;; attempt += 1) {
|
|
66
|
+
try {
|
|
67
|
+
await (0, promises_1.rename)(temporary, target);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const code = error.code;
|
|
72
|
+
if (attempt >= 20 || (code !== "EPERM" && code !== "EACCES" && code !== "EBUSY")) {
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
await new Promise((wake) => setTimeout(wake, 10 + attempt * 5));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
// A failed move must not leave scratch files accumulating beside it.
|
|
81
|
+
await (0, promises_1.rm)(temporary, { force: true }).catch(() => undefined);
|
|
82
|
+
}
|
|
54
83
|
}
|
|
55
84
|
async function storeToken(token) {
|
|
56
85
|
await writePrivate(tokenFile(), `${token.trim()}\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderook/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "CodeRook from the command line, on any operating system",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"homepage": "https://coderook.com",
|
|
@@ -32,12 +32,13 @@
|
|
|
32
32
|
"test:matrix": "node test/state-matrix.mjs",
|
|
33
33
|
"test:attempt": "node test/attempt-identity.mjs",
|
|
34
34
|
"test:get": "node test/get-safety.mjs",
|
|
35
|
-
"test:live": "node test/e2e.mjs --allow-production && node test/state-matrix.mjs --allow-production && node test/get-safety.mjs --allow-production && node test/get-protects-edits.mjs --allow-production && node test/upgrade-migration.mjs --allow-production && node test/fault-get.mjs --allow-production && node test/version-floor.mjs --allow-production && node test/fault-submit.mjs --allow-production && node test/attempt-identity.mjs --allow-production",
|
|
35
|
+
"test:live": "node test/e2e.mjs --allow-production && node test/state-matrix.mjs --allow-production && node test/get-safety.mjs --allow-production && node test/get-protects-edits.mjs --allow-production && node test/upgrade-migration.mjs --allow-production && node test/fault-get.mjs --allow-production && node test/version-floor.mjs --allow-production && node test/fault-submit.mjs --allow-production && node test/race-attempts.mjs --allow-production && node test/attempt-identity.mjs --allow-production",
|
|
36
36
|
"test:getedits": "node test/get-protects-edits.mjs",
|
|
37
37
|
"test:upgrade": "node test/upgrade-migration.mjs",
|
|
38
38
|
"test:faultget": "node test/fault-get.mjs",
|
|
39
39
|
"test:floor": "node test/version-floor.mjs",
|
|
40
|
-
"test:faultsubmit": "node test/fault-submit.mjs"
|
|
40
|
+
"test:faultsubmit": "node test/fault-submit.mjs",
|
|
41
|
+
"test:race": "node test/race-attempts.mjs"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "24.10.1",
|