Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/30467-ledger-adoption-staging-dir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@objectstack/cloud-connection': patch
---

Clause-②: no
Metadata-protocol: none

The one-time copy of the working-directory install ledger into its `OS_HOME` location (#30217) now creates its staging directory with an exclusive `mkdirSync` of a randomly named sibling instead of `mkdtempSync`. Behaviour is unchanged: the copy still lands in a unique sibling of the ledger directory, is renamed into place, and is removed if the copy fails. This repairs the red `main` build (#30467), where the repository's in-tree scratch scan could not read the `mkdtempSync` base.
13 changes: 10 additions & 3 deletions packages/cloud-connection/src/local-manifest-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
* the same ledger without going through HTTP.
*/

import { randomBytes } from 'node:crypto';
import {
copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync,
writeFileSync,
copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync,
} from 'node:fs';
import { homedir } from 'node:os';
import { basename, dirname, join, resolve } from 'node:path';
Expand Down Expand Up @@ -330,7 +330,14 @@ export class LocalManifestSource {
const files = readdirSync(from).filter((name) => name.endsWith('.json'));
if (files.length === 0) return null;
mkdirSync(dirname(this.dir), { recursive: true });
const staging = mkdtempSync(join(dirname(this.dir), `.${basename(this.dir)}.adopting-`));
// A unique sibling, created exclusively: a non-recursive mkdirSync
// throws EEXIST rather than reuse a directory that is already there,
// which is the guarantee mkdtempSync gave. mkdtempSync is not used
// because the repo's in-tree scratch scan holds every mkdtempSync to a
// base it can read from source, and this base is the ledger location
// resolved at run time.
const staging = join(dirname(this.dir), `.${basename(this.dir)}.adopting-${randomBytes(6).toString('hex')}`);
mkdirSync(staging);
try {
for (const name of files) copyFileSync(join(from, name), join(staging, name));
renameSync(staging, this.dir);
Expand Down
Loading