Revert "workspace renaming with path update (#7437)" (#7455)

This reverts commit e7c2c7c872.
This commit is contained in:
naman-bruno
2026-03-12 18:40:52 +05:30
committed by GitHub
parent 6f6a9100e9
commit ddb1c69fc9
4 changed files with 14 additions and 216 deletions

View File

@@ -524,38 +524,21 @@ const handleWorkspaceAction = async (action, workspaceUid, ...args) => {
export const renameWorkspaceAction = (workspaceUid, newName) => {
return async (dispatch, getState) => {
try {
const { workspaces, activeWorkspaceUid } = getState().workspaces;
const { workspaces } = getState().workspaces;
const workspace = workspaces.find((w) => w.uid === workspaceUid);
if (!workspace) {
throw new Error('Workspace not found');
}
const result = await ipcRenderer.invoke('renderer:rename-workspace', workspace.pathname, newName);
await handleWorkspaceAction((...args) => ipcRenderer.invoke('renderer:rename-workspace', ...args),
workspace.pathname,
newName);
if (result.newWorkspacePath) {
const { generateUidBasedOnHash } = await import('utils/common');
const newWorkspaceUid = generateUidBasedOnHash(result.newWorkspacePath);
const wasActive = activeWorkspaceUid === workspaceUid;
dispatch(removeWorkspace(workspaceUid));
dispatch(createWorkspace({
...workspace,
uid: newWorkspaceUid,
name: newName,
pathname: result.newWorkspacePath
}));
if (wasActive) {
dispatch(setActiveWorkspace(newWorkspaceUid));
}
} else {
dispatch(updateWorkspace({
uid: workspaceUid,
name: newName
}));
}
dispatch(updateWorkspace({
uid: workspaceUid,
name: newName
}));
} catch (error) {
throw error;
}

View File

@@ -16,6 +16,7 @@ const {
readWorkspaceConfig,
writeWorkspaceConfig,
validateWorkspaceConfig,
updateWorkspaceName,
updateWorkspaceDocs,
addCollectionToWorkspace,
removeCollectionFromWorkspace,
@@ -24,8 +25,7 @@ const {
normalizeCollectionEntry,
validateWorkspacePath,
validateWorkspaceDirectory,
getWorkspaceUid,
renameWorkspace
getWorkspaceUid
} = require('../utils/workspace-config');
const { isValidCollectionDirectory } = require('../utils/filesystem');
@@ -270,20 +270,7 @@ const registerWorkspaceIpc = (mainWindow, workspaceWatcher) => {
ipcMain.handle('renderer:rename-workspace', async (event, workspacePath, newName) => {
try {
const result = await renameWorkspace(workspacePath, newName);
if (result.newWorkspacePath) {
if (workspaceWatcher) {
workspaceWatcher.removeWatcher(workspacePath);
workspaceWatcher.addWatcher(mainWindow, result.newWorkspacePath);
}
lastOpenedWorkspaces.remove(workspacePath);
lastOpenedWorkspaces.add(result.newWorkspacePath);
return { success: true, newWorkspacePath: result.newWorkspacePath };
}
await updateWorkspaceName(workspacePath, newName);
return { success: true };
} catch (error) {
throw error;

View File

@@ -1,7 +1,7 @@
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const { writeFile, validateName, isValidCollectionDirectory, sanitizeName } = require('./filesystem');
const { writeFile, validateName, isValidCollectionDirectory } = require('./filesystem');
const { generateUidBasedOnHash } = require('./common');
const { withLock, getWorkspaceLockKey } = require('./workspace-lock');
@@ -563,44 +563,6 @@ const getWorkspaceUid = (workspacePath) => {
return generateUidBasedOnHash(workspacePath);
};
/**
* Renames a workspace folder and updates the workspace.yml config.
* @param {string} workspacePath - Current absolute path to the workspace folder
* @param {string} newName - New name for the workspace
* @returns {Promise<{newWorkspacePath: string|null}>} - New path if folder was renamed, null otherwise
*/
const renameWorkspace = async (workspacePath, newName) => {
const parentDir = path.dirname(workspacePath);
const newFolderName = sanitizeName(newName);
const newWorkspacePath = path.join(parentDir, newFolderName);
const pathsAreSame = path.normalize(workspacePath).toLowerCase() === path.normalize(newWorkspacePath).toLowerCase();
if (!pathsAreSame) {
if (fs.existsSync(newWorkspacePath)) {
throw new Error(`A folder named "${newFolderName}" already exists at this location`);
}
fs.renameSync(workspacePath, newWorkspacePath);
try {
await updateWorkspaceName(newWorkspacePath, newName);
} catch (error) {
try {
fs.renameSync(newWorkspacePath, workspacePath);
} catch (rollbackError) {
console.error('Failed to rollback workspace folder rename:', rollbackError);
}
throw error;
}
return { newWorkspacePath };
}
await updateWorkspaceName(workspacePath, newName);
return { newWorkspacePath: null };
};
module.exports = {
makeRelativePath,
normalizeCollectionEntry,
@@ -623,6 +585,5 @@ module.exports = {
getWorkspaceUid,
writeWorkspaceFileAtomic,
isValidCollectionEntry,
isValidSpecEntry,
renameWorkspace
isValidSpecEntry
};

View File

@@ -2,7 +2,7 @@ const path = require('path');
const fs = require('fs');
const os = require('os');
const yaml = require('js-yaml');
const { reorderWorkspaceCollections, renameWorkspace } = require('../../src/utils/workspace-config');
const { reorderWorkspaceCollections } = require('../../src/utils/workspace-config');
const collection = (name, pathSegment) => ({ name, path: pathSegment });
@@ -74,136 +74,3 @@ describe('reorderWorkspaceCollections', () => {
expect(getCollectionPathsFromYml()).toEqual(['collections/api', 'collections/backend']);
});
});
describe('renameWorkspace', () => {
let parentDir;
let workspacePath;
/** Creates a workspace directory with workspace.yml */
const createWorkspace = (folderName, workspaceName) => {
const wsPath = path.join(parentDir, folderName);
fs.mkdirSync(wsPath, { recursive: true });
const content = [
'opencollection: 1.0.0',
'info:',
` name: "${workspaceName}"`,
' type: workspace',
'collections:',
'specs:',
'docs: \'\''
].join('\n');
fs.writeFileSync(path.join(wsPath, 'workspace.yml'), content);
return wsPath;
};
/** Gets the workspace name from workspace.yml */
const getWorkspaceName = (wsPath) => {
const raw = fs.readFileSync(path.join(wsPath, 'workspace.yml'), 'utf8');
const config = yaml.load(raw);
return config.info?.name;
};
beforeEach(() => {
parentDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bruno-ws-parent-'));
workspacePath = createWorkspace('Untitled Workspace', 'Untitled Workspace');
});
afterEach(() => {
fs.rmSync(parentDir, { recursive: true, force: true });
});
test('renames workspace folder and updates config', async () => {
const result = await renameWorkspace(workspacePath, 'My API Project');
expect(result.newWorkspacePath).toBe(path.join(parentDir, 'My API Project'));
expect(fs.existsSync(path.join(parentDir, 'Untitled Workspace'))).toBe(false);
expect(fs.existsSync(path.join(parentDir, 'My API Project'))).toBe(true);
expect(getWorkspaceName(result.newWorkspacePath)).toBe('My API Project');
});
test('only updates config when folder name stays the same', async () => {
// Create workspace where folder name matches sanitized target but display name differs
const sameFolderPath = createWorkspace('My-Project', 'Old Name');
// Rename to name that sanitizes to same folder name
const result = await renameWorkspace(sameFolderPath, 'My:Project');
expect(result.newWorkspacePath).toBeNull();
expect(fs.existsSync(sameFolderPath)).toBe(true);
// Verify config was actually updated
expect(getWorkspaceName(sameFolderPath)).toBe('My:Project');
});
test('sanitizes special characters in folder name', async () => {
const result = await renameWorkspace(workspacePath, 'My:API/Project<Test>');
expect(result.newWorkspacePath).toBe(path.join(parentDir, 'My-API-Project-Test-'));
expect(fs.existsSync(result.newWorkspacePath)).toBe(true);
expect(getWorkspaceName(result.newWorkspacePath)).toBe('My:API/Project<Test>');
});
test('throws error when target folder already exists', async () => {
// Create another workspace with the target name
createWorkspace('Existing Project', 'Existing Project');
await expect(renameWorkspace(workspacePath, 'Existing Project'))
.rejects.toThrow('A folder named "Existing Project" already exists at this location');
// Original workspace should still exist
expect(fs.existsSync(workspacePath)).toBe(true);
});
test('handles case-only rename by updating config without renaming folder', async () => {
// Create workspace with lowercase name
const lowerPath = createWorkspace('myworkspace', 'myworkspace');
// Rename to different case - code uses case-insensitive comparison
// so this only updates config, doesn't rename folder (cross-platform safety)
const result = await renameWorkspace(lowerPath, 'MyWorkspace');
expect(result.newWorkspacePath).toBeNull();
expect(fs.existsSync(lowerPath)).toBe(true);
expect(getWorkspaceName(lowerPath)).toBe('MyWorkspace');
});
test('preserves workspace.yml content after rename', async () => {
// Add collections, specs, and other fields to the workspace
const configPath = path.join(workspacePath, 'workspace.yml');
const content = [
'opencollection: 1.0.0',
'info:',
' name: "Untitled Workspace"',
' type: workspace',
'collections:',
' - name: "API"',
' path: "collections/api"',
' remote: "https://github.com/example/api"',
'specs:',
' - name: "OpenAPI"',
' path: "specs/openapi.yaml"',
'docs: \'Some documentation\'',
'',
'activeEnvironmentUid: env_123'
].join('\n');
fs.writeFileSync(configPath, content);
const result = await renameWorkspace(workspacePath, 'My Project');
const newConfigPath = path.join(result.newWorkspacePath, 'workspace.yml');
const newContent = fs.readFileSync(newConfigPath, 'utf8');
const config = yaml.load(newContent);
// Verify all fields are preserved
expect(config.opencollection).toBe('1.0.0');
expect(config.info.name).toBe('My Project');
expect(config.info.type).toBe('workspace');
expect(config.collections).toHaveLength(1);
expect(config.collections[0].name).toBe('API');
expect(config.collections[0].path).toBe('collections/api');
expect(config.collections[0].remote).toBe('https://github.com/example/api');
expect(config.specs).toHaveLength(1);
expect(config.specs[0]).toEqual({ name: 'OpenAPI', path: 'specs/openapi.yaml' });
expect(config.docs).toBe('Some documentation');
expect(config.activeEnvironmentUid).toBe('env_123');
});
});