diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index d50f9a34f88..b6f522e8e82 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -286,7 +286,7 @@ export { // Util export { findFileWithViewer, findFile, isSpecialDirectory } from './core/find-file' -export { expandHomeDir, cwd } from './util/home' +export { expandHomeDir, cwd, fallbackCWD } from './util/home' export { flatten } from './core/utility' export { promiseEach } from './util/async' export { isHTML, isPromise } from './util/types' diff --git a/packages/core/src/util/home.ts b/packages/core/src/util/home.ts index 9d564d2ad1c..b5994f52649 100644 --- a/packages/core/src/util/home.ts +++ b/packages/core/src/util/home.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { join } from 'path' +import { dirname, join } from 'path' import { homedir as home } from 'os' import { inBrowser } from '../core/capabilities' @@ -37,6 +37,15 @@ export const expandHomeDir = function(path: string): string { export default expandHomeDir +/** In case of error, e.g. removed CWD, this is our fallback plan */ +export function fallbackCWD(cwd?: string) { + if (cwd) { + return dirname(cwd) + } else { + return process.env.HOME || _homedir || '/' + } +} + export const cwd = () => { try { return ( @@ -45,9 +54,9 @@ export const cwd = () => { } catch (err) { // it could be that the underlying directory disappeared // see https://github.com/kubernetes-sigs/kui/issues/8160 - console.error(err) + console.error('Using fallback plan due to error', err) // fallback plan: - return process.env.PWD || process.env.HOME || _homedir || '/' + return fallbackCWD() } } diff --git a/plugins/plugin-bash-like/src/tab-state/index.ts b/plugins/plugin-bash-like/src/tab-state/index.ts index 1c8af7b1fe5..8a0b041812c 100644 --- a/plugins/plugin-bash-like/src/tab-state/index.ts +++ b/plugins/plugin-bash-like/src/tab-state/index.ts @@ -15,7 +15,7 @@ */ import Debug from 'debug' -import { TabState, cwd as kuiCwd, registerTabState, inBrowser } from '@kui-shell/core' +import { TabState, cwd as kuiCwd, fallbackCWD, registerTabState, inBrowser } from '@kui-shell/core' import getTabState from './get' import { apiVersion, name } from './key' @@ -43,8 +43,19 @@ const restore = (tab: TabState) => { debug('changing cwd', process.env.PWD, cwd) process.env.PWD = cwd } else { - debug('changing cwd', process.cwd(), cwd) - process.chdir(cwd) + try { + debug('changing cwd', cwd) + process.chdir(cwd) + } catch (err) { + console.error(`Error in chdir, using fallback plan: ${fallbackCWD(cwd)}`, err) + try { + process.chdir(fallbackCWD(cwd)) + } catch (err) { + // wow, things really are weird, then + console.error(err) + process.chdir(fallbackCWD()) + } + } } } } diff --git a/plugins/plugin-bash-like/src/test/bash-like/cd.ts b/plugins/plugin-bash-like/src/test/bash-like/cd.ts index 817f2afdf43..7c25701a81c 100644 --- a/plugins/plugin-bash-like/src/test/bash-like/cd.ts +++ b/plugins/plugin-bash-like/src/test/bash-like/cd.ts @@ -18,7 +18,7 @@ import { dirSync } from 'tmp' import { v4 as uuid } from 'uuid' import { dirname, join, normalize } from 'path' -import { Common, CLI, ReplExpect, Selectors } from '@kui-shell/test' +import { Common, CLI, ReplExpect, Selectors, Util } from '@kui-shell/test' import { expandHomeDir } from '@kui-shell/core' const ROOT = dirname(require.resolve('@kui-shell/core/tests/package.json')) @@ -178,3 +178,36 @@ describe(`remove current directory ${process.env.MOCHA_RUN_TARGET || ''}`, funct .catch(Common.oops(this, true)) ) }) + +// see https://github.com/kubernetes-sigs/kui/issues/8173 +describe(`remove current directory with tab switch ${process.env.MOCHA_RUN_TARGET || + ''}`, function(this: Common.ISuite) { + before(Common.before(this)) + after(Common.after(this)) + Util.closeAllExceptFirstTab.bind(this)() + + const { name: tmp } = dirSync() + + pit(`should cd to our tmp dir ${tmp}`, () => + CLI.command(`cd ${tmp}`, this.app) + .then(ReplExpect.okWithString(tmp)) + .catch(Common.oops(this, true)) + ) + + pit('should create new tab', () => Util.clickNewTabButton(this, 2)) + pit('should switch to that tab', () => Util.switchToTopLevelTabViaClick(this, 2)) + + pit(`should remove our tmp dir ${tmp}`, () => + CLI.command(`rmdir ${tmp}`, this.app) + .then(ReplExpect.ok) + .catch(Common.oops(this, true)) + ) + + pit('should switch back to the first tab', () => Util.switchToTopLevelTabViaClick(this, 1)) + + pit(`should show parent of pwd as ${tmp}`, () => + CLI.command(`pwd`, this.app) + .then(ReplExpect.okWithString(dirname(tmp))) + .catch(Common.oops(this, true)) + ) +})