Summary
installCmdTools in packages/core/src/cmdTools/install.ts does not roll back or clean up the install target (CMD_PATH, default ~/command-line-tools) when the install fails partway through. Its catch/finally only clean up the temporary scratch directory, never the actual install target:
https://github.com/eclipse-oniro4openharmony/oniro-app-builder/blob/main/packages/core/src/cmdTools/install.ts#L114-L150
try {
...
await extractZipWithProgress({ zipPath, dest: extractPath, ... });
fs.mkdirSync(CMD_PATH, { recursive: true });
const srcDir = findCmdToolsSourceDir(extractPath);
for (const entry of fs.readdirSync(srcDir)) {
const src = path.join(srcDir, entry);
const dest = path.join(CMD_PATH, entry);
if (fs.statSync(src).isDirectory()) {
if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true, force: true });
movePath(src, dest); // <- can throw partway through a large dir (e.g. ENOSPC)
} else {
fs.copyFileSync(src, dest);
}
}
...
} catch (err) {
throw toSpaceError(err, tmpRoot, what);
} finally {
removeTempWorkDir(tmpDir, tmpRoot); // only removes the scratch dir, never CMD_PATH
}
If an error (e.g. running out of disk space) interrupts the copy loop partway through, whatever had already been written into CMD_PATH — some entries fully copied, the one in progress possibly truncated/partial, later entries never reached at all — is left behind. movePath's cross-device fallback (fs.cpSync + fs.rmSync, in sdk/move.ts) is itself non-atomic per directory, so even a single top-level entry (e.g. sdk/) can be left half-copied.
On retry, the loop does replace CMD_PATH entries that share a name with something in the fresh archive (rmSync + movePath), so a full, uninterrupted second run can self-heal — but any inconsistency introduced by the first partial run is not guaranteed to be reconciled cleanly, and the resulting tree can end up different from what you'd get extracting the same archive fresh into an empty directory.
Steps to reproduce
Run oniro-app cmdtools install --from-zip with insufficient free disk space on the drive backing the install target / scratch directory. The install fails partway through with a disk-space error.
Free up space on the drive.
Run the same install command again. It completes without error.
Run oniro-app build on a project.
Expected behavior
A failed install should leave CMD_PATH clean (either untouched or fully rolled back), and a subsequent successful install should always produce a directory tree identical to a clean extraction of the archive, regardless of a prior failed attempt. oniro-app build should find all the directories it depends on under CMD_PATH.
Actual behavior
A subfolder under CMD_PATH is missing even though the second install reported success. oniro-app build fails with an error about a non-existent directory, because it can't find a path it expects to exist inside the command-line-tools install.
Suggested fix
On failure, also remove any partial content written to CMD_PATH during this run (or write into a temporary staging directory under the scratch dir and only move/rename the whole finished tree into CMD_PATH once the copy loop completes successfully, so a failure anywhere leaves CMD_PATH untouched instead of partially written).
Environment
OS: macOS
oniro-app-builder version: 0.10.0
Install method: --from-zip with a manually downloaded archive
Summary
installCmdToolsinpackages/core/src/cmdTools/install.tsdoes not roll back or clean up the install target (CMD_PATH, default~/command-line-tools) when the install fails partway through. Itscatch/finallyonly clean up the temporary scratch directory, never the actual install target:https://github.com/eclipse-oniro4openharmony/oniro-app-builder/blob/main/packages/core/src/cmdTools/install.ts#L114-L150
If an error (e.g. running out of disk space) interrupts the copy loop partway through, whatever had already been written into CMD_PATH — some entries fully copied, the one in progress possibly truncated/partial, later entries never reached at all — is left behind. movePath's cross-device fallback (fs.cpSync + fs.rmSync, in sdk/move.ts) is itself non-atomic per directory, so even a single top-level entry (e.g. sdk/) can be left half-copied.
On retry, the loop does replace CMD_PATH entries that share a name with something in the fresh archive (rmSync + movePath), so a full, uninterrupted second run can self-heal — but any inconsistency introduced by the first partial run is not guaranteed to be reconciled cleanly, and the resulting tree can end up different from what you'd get extracting the same archive fresh into an empty directory.
Steps to reproduce
Run oniro-app cmdtools install --from-zip with insufficient free disk space on the drive backing the install target / scratch directory. The install fails partway through with a disk-space error.
Free up space on the drive.
Run the same install command again. It completes without error.
Run oniro-app build on a project.
Expected behavior
A failed install should leave CMD_PATH clean (either untouched or fully rolled back), and a subsequent successful install should always produce a directory tree identical to a clean extraction of the archive, regardless of a prior failed attempt. oniro-app build should find all the directories it depends on under CMD_PATH.
Actual behavior
A subfolder under CMD_PATH is missing even though the second install reported success. oniro-app build fails with an error about a non-existent directory, because it can't find a path it expects to exist inside the command-line-tools install.
Suggested fix
On failure, also remove any partial content written to CMD_PATH during this run (or write into a temporary staging directory under the scratch dir and only move/rename the whole finished tree into CMD_PATH once the copy loop completes successfully, so a failure anywhere leaves CMD_PATH untouched instead of partially written).
Environment
OS: macOS
oniro-app-builder version: 0.10.0
Install method: --from-zip with a manually downloaded archive