Robust app folder rename (#200)

Fixes #89
This commit is contained in:
Will Chen
2025-05-19 14:59:55 -07:00
committed by GitHub
parent cbfe26bac1
commit 68cb6b3d7d
2 changed files with 35 additions and 29 deletions

View File

@@ -12,10 +12,7 @@ import { promises as fsPromises } from "node:fs";
// Import our utility modules // Import our utility modules
import { withLock } from "../utils/lock_utils"; import { withLock } from "../utils/lock_utils";
import { import { getFilesRecursively } from "../utils/file_utils";
copyDirectoryRecursive,
getFilesRecursively,
} from "../utils/file_utils";
import { import {
runningApps, runningApps,
processCounter, processCounter,
@@ -192,10 +189,15 @@ export function registerAppHandlers() {
// Start async operations in background // Start async operations in background
try { try {
// Copy scaffold asynchronously await fsPromises.cp(
await copyDirectoryRecursive(
path.join(__dirname, "..", "..", "scaffold"), path.join(__dirname, "..", "..", "scaffold"),
fullAppPath, fullAppPath,
{
recursive: true,
// Scaffold should *not* have node_modules anyways, but
// just in case, we filter it out.
filter: (source) => !source.includes("node_modules"),
},
); );
// Initialize git repo and create first commit // Initialize git repo and create first commit
await git.init({ await git.init({
@@ -666,8 +668,11 @@ export function registerAppHandlers() {
recursive: true, recursive: true,
}); });
// Move the files // Copy the directory without node_modules
await fsPromises.rename(oldAppPath, newAppPath); await fsPromises.cp(oldAppPath, newAppPath, {
recursive: true,
filter: (source) => !source.includes("node_modules"),
});
} catch (error: any) { } catch (error: any) {
logger.error( logger.error(
`Error moving app files from ${oldAppPath} to ${newAppPath}:`, `Error moving app files from ${oldAppPath} to ${newAppPath}:`,
@@ -675,6 +680,21 @@ export function registerAppHandlers() {
); );
throw new Error(`Failed to move app files: ${error.message}`); throw new Error(`Failed to move app files: ${error.message}`);
} }
try {
// Delete the old directory
await fsPromises.rm(oldAppPath, { recursive: true, force: true });
} catch (error: any) {
// Why is this just a warning? This happens quite often on Windows
// because it has an aggressive file lock.
//
// Not deleting the old directory is annoying, but not a big deal
// since the user can do it themselves if they need to.
logger.warn(
`Error deleting old app directory ${oldAppPath}:`,
error,
);
}
} }
// Update app in database // Update app in database
@@ -693,7 +713,13 @@ export function registerAppHandlers() {
// Attempt to rollback the file move // Attempt to rollback the file move
if (newAppPath !== oldAppPath) { if (newAppPath !== oldAppPath) {
try { try {
await fsPromises.rename(newAppPath, oldAppPath); // Copy back from new to old
await fsPromises.cp(newAppPath, oldAppPath, {
recursive: true,
filter: (source) => !source.includes("node_modules"),
});
// Delete the new directory
await fsPromises.rm(newAppPath, { recursive: true, force: true });
} catch (rollbackError) { } catch (rollbackError) {
logger.error( logger.error(
`Failed to rollback file move during rename error:`, `Failed to rollback file move during rename error:`,

View File

@@ -1,6 +1,5 @@
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { promises as fsPromises } from "node:fs";
/** /**
* Recursively gets all files in a directory, excluding node_modules and .git * Recursively gets all files in a directory, excluding node_modules and .git
@@ -32,22 +31,3 @@ export function getFilesRecursively(dir: string, baseDir: string): string[] {
return files; return files;
} }
export async function copyDirectoryRecursive(
source: string,
destination: string,
) {
await fsPromises.mkdir(destination, { recursive: true });
const entries = await fsPromises.readdir(source, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(source, entry.name);
const destPath = path.join(destination, entry.name);
if (entry.isDirectory()) {
await copyDirectoryRecursive(srcPath, destPath);
} else {
await fsPromises.copyFile(srcPath, destPath);
}
}
}