From ea1f385d1cd8f5d8b0ed7cde4134193ea7abb97d Mon Sep 17 00:00:00 2001 From: lohit Date: Sat, 14 Dec 2024 18:55:28 +0530 Subject: [PATCH] fix: rename folder case insensitive (#3635) * fix: rename folder case insensitive * fix: add hasSubFolders utility and update folder moving logic for Windows OS * fix: validations * fix: updates * fix: updates --------- Co-authored-by: Pragadesh-45 --- packages/bruno-electron/src/app/watcher.js | 31 +++++++++++++++++++ packages/bruno-electron/src/ipc/collection.js | 27 +++++++++++++--- .../bruno-electron/src/utils/filesystem.js | 9 +++++- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index a26ff5d53..1b2e19d4a 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -44,6 +44,13 @@ const isCollectionRootBruFile = (pathname, collectionPath) => { return dirname === collectionPath && basename === 'collection.bru'; }; +const isPathInside = (childPath, parentPath) => { + const absoluteChildPath = path.resolve(childPath); + const absoluteParentPath = path.resolve(parentPath); + return absoluteChildPath.startsWith(absoluteParentPath); +} + + const hydrateRequestWithUuid = (request, pathname) => { request.uid = getRequestUid(pathname); @@ -506,6 +513,30 @@ class Watcher { this.watchers[watchPath] = null; } } + + getWatcherForPath(_path) { + const paths = Object.keys(this.watchers); + return paths.find(parentFolder => isPathInside(_path, parentFolder)); + } + + unlink(_path) { + const watcherPath = this.getWatcherForPath(_path); + if (watcherPath) { + const _watcher = this.watchers[watcherPath]; + _watcher.unwatch(_path); + } + } + + add(_path) { + const watcherPath = this.getWatcherForPath(_path); + if (watcherPath) { + const _watcher = this.watchers[watcherPath]; + if (!_watcher?.has?.(_path)) { + _watcher?.add?.(_path); + } + } + } + } module.exports = Watcher; diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index 130228797..2c4ff3a84 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -21,7 +21,8 @@ const { normalizeAndResolvePath, safeToRename, isWindowsOS, - isValidFilename + isValidFilename, + hasSubFolders, } = require('../utils/filesystem'); const { openCollectionDialog } = require('../app/collections'); const { generateUidBasedOnHash, stringifyJson, safeParseJSON, safeStringifyJSON } = require('../utils/common'); @@ -343,6 +344,7 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection // rename item ipcMain.handle('renderer:rename-item', async (event, oldPath, newPath, newName) => { + const tempDir = path.join(os.tmpdir(), `temp-folder-${Date.now()}`); try { // Normalize paths if they are WSL paths oldPath = isWSLPath(oldPath) ? normalizeWslPath(oldPath) : normalizeAndResolvePath(oldPath); @@ -365,15 +367,18 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection moveRequestUid(bruFile, newBruFilePath); } - if (isWindowsOS() && !isWSLPath(oldPath)) { - const tempDir = path.join(os.tmpdir(), `temp-folder-${Date.now()}`); + watcher.unlink(path.dirname(oldPath)); + if (isWindowsOS() && !isWSLPath(oldPath) && hasSubFolders(oldPath)) { + console.log('Windows OS: Moving folder with subfolders'); await fsExtra.copy(oldPath, tempDir); - await fsExtra.move(tempDir, newPath, { overwrite: true }); await fsExtra.remove(oldPath); + await fsExtra.move(tempDir, newPath, { overwrite: true }); + await fsExtra.remove(tempDir); } else { await fs.renameSync(oldPath, newPath); } + watcher.add(path.dirname(newPath)); return newPath; } @@ -397,6 +402,20 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection return newPath; } catch (error) { + // add path back to watcher in case an error during the rename file operations + // adds unlinked path back to watcher if doesn't exist + watcher.add(path.dirname(oldPath)); + + if (isWindowsOS() && !isWSLPath(oldPath)) { + if (fsExtra.pathExistsSync(tempDir) && !fsExtra.pathExistsSync(oldPath)) { + try { + await fsExtra.copy(tempDir, oldPath); + await fsExtra.remove(tempDir); + } catch (err) { + console.error("Failed to restore data to the old path:", err); + } + } + } return Promise.reject(error); } }); diff --git a/packages/bruno-electron/src/utils/filesystem.js b/packages/bruno-electron/src/utils/filesystem.js index aeb0bdd96..bd4e0aec0 100644 --- a/packages/bruno-electron/src/utils/filesystem.js +++ b/packages/bruno-electron/src/utils/filesystem.js @@ -38,6 +38,12 @@ const isDirectory = (dirPath) => { } }; +const hasSubFolders = (dir) => { + console.log('Checking for subfolders in:', dir); + const files = fs.readdirSync(dir); + return files.some(file => fs.statSync(path.join(dir, file)).isDirectory()); +}; + const normalizeAndResolvePath = (pathname) => { if (isSymbolicLink(pathname)) { const absPath = path.dirname(pathname); @@ -224,5 +230,6 @@ module.exports = { sanitizeDirectoryName, isWindowsOS, safeToRename, - isValidFilename + isValidFilename, + hasSubFolders };