Skip to content

Commit e9ec39a

Browse files
vikaspotluri123acburdine
authored andcommitted
feat(flags): add global dir option
Add ability to specify which directory Ghost should run in refs + closes #538
1 parent 975049c commit e9ec39a

File tree

5 files changed

+82
-39
lines changed

5 files changed

+82
-39
lines changed

lib/bootstrap.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ const bootstrap = {
145145
// TODO: evaluate if `wrap` is actually needed?
146146
yargs.wrap(Math.min(100, yargs.terminalWidth()))
147147
.epilogue('For more information, see our docs at https://docs.ghost.org/v1/docs/ghost-cli')
148-
.option('D', {
148+
.option('d', {
149+
alias: 'dir',
150+
describe: 'Folder to run command in'
151+
}).option('D', {
149152
alias: 'development',
150153
describe: 'Run in development mode',
151154
type: 'boolean'

lib/command.js

+36-10
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,42 @@ class Command {
107107
* @method run
108108
* @private
109109
*/
110-
static _run(commandName, argv, extensions) {
110+
static _run(commandName, argv = {}, extensions) {
111+
debug('running command prep');
112+
// Set process title
113+
process.title = `ghost ${commandName}`;
114+
115+
// Create CLI-wide UI & System instances
116+
const ui = new UI({
117+
verbose: argv.verbose,
118+
allowPrompt: argv.prompt
119+
});
120+
121+
// This needs to run before the installation check
122+
if (argv.dir) {
123+
debug('Directory specified, attempting to update');
124+
const path = require('path');
125+
const dir = path.resolve(argv.dir);
126+
try {
127+
if (this.ensureDir) {
128+
const {ensureDirSync} = require('fs-extra');
129+
ensureDirSync(dir);
130+
}
131+
132+
process.chdir(dir);
133+
} catch (error) {
134+
/* istanbul ignore next */
135+
const err = error.message || error.code || error;
136+
ui.log(`Unable to use "${dir}" (error ${err}). Please fix the issue and try again.`, 'red', true);
137+
process.exit(1);
138+
}
139+
/* istanbul ignore next */
140+
// In order to keep the rest of the function from running, chdir / exit is stubbed to
141+
// throw an error in the tests so this line is technically unreachable. Since it's only
142+
// a debug statement, we're not going to worry about it
143+
debug('Finished updating directory');
144+
}
145+
111146
if (!this.global) {
112147
const checkValidInstall = require('./utils/check-valid-install');
113148

@@ -120,15 +155,6 @@ class Command {
120155
checkRootUser(commandName);
121156
}
122157

123-
// Set process title
124-
process.title = `ghost ${commandName}`;
125-
const verbose = argv.verbose;
126-
127-
// Create CLI-wide UI & System instances
128-
const ui = new UI({
129-
verbose: verbose,
130-
allowPrompt: argv.prompt
131-
});
132158
const system = new System(ui, extensions);
133159

134160
// Set the initial environment based on args or NODE_ENV

lib/commands/install.js

+1-8
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ class InstallCommand extends Command {
1919
const yarnInstall = require('../tasks/yarn-install');
2020
const ensureStructure = require('../tasks/ensure-structure');
2121

22-
// Dir was specified, so we make sure it exists and chdir into it.
23-
if (argv.dir) {
24-
const dir = path.resolve(argv.dir);
25-
26-
fs.ensureDirSync(dir);
27-
process.chdir(dir);
28-
}
29-
3022
let version = argv.version;
3123
const filesInDir = fs.readdirSync(process.cwd());
3224

@@ -144,5 +136,6 @@ InstallCommand.options = {
144136
}
145137
};
146138
InstallCommand.checkVersion = true;
139+
InstallCommand.ensureDir = true;
147140

148141
module.exports = InstallCommand;

test/unit/command-spec.js

+41
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,47 @@ describe('Unit: Command', function () {
234234
}
235235
});
236236

237+
it('Changes directory if needed', function () {
238+
sinon.stub(process, 'exit').throws(new Error('exit_stub'));
239+
const outStub = sinon.stub(process.stderr, 'write');
240+
const chdirStub = sinon.stub(process, 'chdir').throws(new Error('chdir_stub'));
241+
const Command = require(modulePath);
242+
class TestCommand extends Command {}
243+
244+
try {
245+
TestCommand._run('test', {dir: '/path/to/ghost', verbose: true});
246+
throw new Error('Should have errored');
247+
} catch (error) {
248+
expect(error).to.be.ok;
249+
expect(error.message).to.equal('exit_stub');
250+
expect(chdirStub.calledOnce).to.be.true;
251+
expect(chdirStub.args[0][0]).to.equal('/path/to/ghost');
252+
expect(outStub.calledOnce).to.be.true;
253+
expect(outStub.args[0][0]).to.match(/chdir_stub/);
254+
}
255+
});
256+
257+
it('Creates & changes into directory if needed', function () {
258+
sinon.stub(process.stderr, 'write');
259+
sinon.stub(process, 'exit').throws(new Error('exit_stub'));
260+
sinon.stub(process, 'chdir').throws(new Error('chdir_stub'));
261+
const fs = require('fs-extra');
262+
const fsStub = sinon.stub(fs, 'ensureDirSync');
263+
const Command = require(modulePath);
264+
class TestCommand extends Command {}
265+
TestCommand.ensureDir = true;
266+
267+
try {
268+
TestCommand._run('test', {dir: '/path/to/ghost', verbose: true});
269+
throw new Error('Should have errored');
270+
} catch (error) {
271+
expect(error).to.be.ok;
272+
expect(error.message).to.equal('exit_stub');
273+
expect(fsStub.calledOnce).to.be.true;
274+
expect(fsStub.args[0][0]).to.equal('/path/to/ghost');
275+
}
276+
});
277+
237278
it('loads system and ui dependencies, calls run method', function () {
238279
const uiStub = sinon.stub().returns({ui: true});
239280
const setEnvironmentStub = sinon.stub();

test/unit/commands/install-spec.js

-20
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,6 @@ describe('Unit: Commands > Install', function () {
3939
sinon.restore();
4040
})
4141

42-
it('creates dir and changes into it if --dir option is passed', function () {
43-
const chdirStub = sinon.stub(process, 'chdir').throws();
44-
const ensureDirStub = sinon.stub();
45-
46-
const InstallCommand = proxyquire(modulePath, {
47-
'fs-extra': {ensureDirSync: ensureDirStub}
48-
});
49-
const testInstance = new InstallCommand({}, {});
50-
51-
try {
52-
testInstance.run({dir: '/some/dir'});
53-
} catch (e) {
54-
// ignore error, chdir is supposed to throw the error
55-
expect(ensureDirStub.calledOnce).to.be.true;
56-
expect(ensureDirStub.calledWithExactly('/some/dir')).to.be.true;
57-
expect(chdirStub.calledOnce).to.be.true;
58-
expect(chdirStub.calledWithExactly('/some/dir')).to.be.true;
59-
}
60-
});
61-
6242
it('rejects if directory is not empty', function () {
6343
const readdirStub = sinon.stub().returns([
6444
'.ghost-cli',

0 commit comments

Comments
 (0)