Skip to content

Commit

Permalink
feat: add 3 new folders to content directory (TryGhost#1581)
Browse files Browse the repository at this point in the history
- Recently we've added 3 new folders to content in Ghost: media, files and public
- This updates Ghost-CLI to create the folders for both new and existing installs
  • Loading branch information
ErisDS authored and acburdine committed Nov 24, 2021
1 parent e4a8468 commit 3c31da2
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 3 deletions.
20 changes: 17 additions & 3 deletions lib/migrations.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
const path = require('path');

async function ensureSettingsFolder(context) {
async function ensureFolder(context, folderName) {
const ghostUser = require('./utils/use-ghost-user');

const contentDir = context.instance.config.get('paths.contentPath');

if (ghostUser.shouldUseGhostUser(contentDir)) {
await context.ui.sudo(`mkdir -p ${path.resolve(contentDir, 'settings')}`, {sudoArgs: '-E -u ghost'});
await context.ui.sudo(`mkdir -p ${path.resolve(contentDir, folderName)}`, {sudoArgs: '-E -u ghost'});
} else {
const fs = require('fs-extra');
fs.ensureDirSync(path.resolve(contentDir, 'settings'));
fs.ensureDirSync(path.resolve(contentDir, folderName));
}
}

async function ensureSettingsFolder(context) {
await ensureFolder(context, 'settings');
}

async function makeSqliteAbsolute({instance}) {
const configs = await instance.getAvailableConfigs();

Expand All @@ -26,6 +30,12 @@ async function makeSqliteAbsolute({instance}) {
});
}

async function ensureMediaFileAndPublicFolders(context) {
await ensureFolder(context, 'media');
await ensureFolder(context, 'files');
await ensureFolder(context, 'public');
}

module.exports = [{
before: '1.7.0',
title: 'Create content/settings directory',
Expand All @@ -34,4 +44,8 @@ module.exports = [{
before: '1.14.1',
title: 'Fix Sqlite DB path',
task: makeSqliteAbsolute
}, {
before: '1.18.1',
title: 'Create content/media, content/files and content/public directories',
task: ensureMediaFileAndPublicFolders
}];
3 changes: 3 additions & 0 deletions lib/tasks/ensure-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ module.exports = function ensureStructure() {
fs.ensureDirSync(path.resolve(cwd, 'content', 'images'));
fs.ensureDirSync(path.resolve(cwd, 'content', 'logs'));
fs.ensureDirSync(path.resolve(cwd, 'content', 'settings'));
fs.ensureDirSync(path.resolve(cwd, 'content', 'media'));
fs.ensureDirSync(path.resolve(cwd, 'content', 'files'));
fs.ensureDirSync(path.resolve(cwd, 'content', 'public'));
};
50 changes: 50 additions & 0 deletions test/unit/migrations-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,54 @@ describe('Unit: Migrations', function () {
expect(configs.production.set.called).to.be.false;
expect(configs.production.save.called).to.be.false;
});

it('ensureMediaFileAndPublicFolders', async () => {
it('if ghost user owns directory, runs `sudo mkdir` as ghost user', function () {
const ghostUserStub = sinon.stub(ghostUser, 'shouldUseGhostUser').returns(true);
const sudoStub = sinon.stub().resolves();
const config = createConfig();
config.get.withArgs('paths.contentPath').returns('/var/www/ghost/content');

const context = {
instance: {config: config},
ui: {sudo: sudoStub}
};

return migrations[0].task(context).then(() => {
expect(ghostUserStub.calledThrice).to.be.true;
expect(ghostUserStub.calledWithExactly('/var/www/ghost/content')).to.be.true;
expect(sudoStub.calledThrice).to.be.true;
expect(sudoStub.firstCall.calledWithExactly(
'mkdir -p /var/www/ghost/content/media',
{sudoArgs: '-E -u ghost'}
)).to.be.true;
expect(sudoStub.secondCall.calledWithExactly(
'mkdir -p /var/www/ghost/content/files',
{sudoArgs: '-E -u ghost'}
)).to.be.true;
expect(sudoStub.thirdCall.calledWithExactly(
'mkdir -p /var/www/ghost/content/public',
{sudoArgs: '-E -u ghost'}
)).to.be.true;
});
});

it('if ghost user doesn\'t own directory, runs basic mkdir', function () {
const ghostUserStub = sinon.stub(ghostUser, 'shouldUseGhostUser').returns(false);
const fsStub = sinon.stub(fs, 'ensureDirSync');
const config = createConfig();
config.get.withArgs('paths.contentPath').returns('/var/www/ghost/content');

const context = {instance: {config: config}};

return migrations[0].task(context).then(() => {
expect(ghostUserStub.calledThrice).to.be.true;
expect(ghostUserStub.calledWithExactly('/var/www/ghost/content')).to.be.true;
expect(fsStub.calledThrice).to.be.true;
expect(fsStub.firstCall.calledWithExactly('/var/www/ghost/content/media')).to.be.true;
expect(fsStub.secondCall.calledWithExactly('/var/www/ghost/content/files')).to.be.true;
expect(fsStub.thirdCall.calledWithExactly('/var/www/ghost/content/public')).to.be.true;
});
});
});
});

0 comments on commit 3c31da2

Please sign in to comment.