Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added 'files mv' command to rename files #86

Merged
merged 5 commits into from
May 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions lib/cmds/files_cmds/mv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use strict';

const chalk = require('chalk');
const querystring = require('querystring');
const { patch, list } = require('../../api');

exports.command = 'mv <source> <dest>';
exports.desc = 'Move/rename files from <source> to <dest> within a project';
exports.builder = yargs => {
yargs.positional('source', {
describe: 'Either the ID of the file to move or a project ID and prefix of the form <project ID>/<prefix> to move a set of files in a project.',
type: 'string'
}).positional('dest', {
describe: 'The new destination for the file within the project.',
type: 'string'
}).option('recursive', {
describe:
'If <source> is a project Id with an optional prefix, move all files under that prefix to the destination.',
alias: 'r',
type: 'boolean',
default: false
}).option('limit', {
describe: 'The maximum number of files to move when used with the --recursive option',
alias: 'l',
type: 'number',
default: 1000
});
};

exports.handler = async argv => {
if (argv.recursive) {
const [datasetId, prefix] = argv.source.split('/');

const opts = {
datasetId,
pageSize: argv.limit
};

if (prefix) {
opts.name = prefix;
}

const response = await list(argv, `/v1/files?${querystring.stringify(opts)}`);
for (const item of response.data.items) {
const newName = [argv.dest, item.name.replace(prefix, '')].join('/').replace(/\/{1,}/g, '/');
await patch(argv, `/v1/files/${item.id}`, {
name: newName
});
console.log(chalk.green(`Moved: `) + item.name + chalk.green(` to `) + newName);
}
} else {
await patch(argv, `/v1/files/${argv.source}`, {
name: argv.dest
});
console.log(chalk.green(`Moved: `) + argv.source + chalk.green(` to `) + argv.dest);
}
};
58 changes: 58 additions & 0 deletions test/unit/commands/file.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const querystring = require('querystring');

const getStub = sinon.stub();
const postStub = sinon.stub();
const patchStub = sinon.stub();
const delStub = sinon.stub();
const printSpy = sinon.spy();
const downloadSpy = sinon.spy();
Expand Down Expand Up @@ -37,6 +38,10 @@ const mocks = {
list: function (options, url) {
return listStub(options, url);
},
patch: (options, url, opts) => {
patchStub(options, url, opts);
callback();
},
post: postStub,
del: delStub,
download: function (options, url, file, name) {
Expand Down Expand Up @@ -69,6 +74,7 @@ const list = proxyquire('../../../lib/cmds/files_cmds/list', mocks);
const download = proxyquire('../../../lib/cmds/files_cmds/download', mocks);
const upload = proxyquire('../../../lib/cmds/files_cmds/upload', mocks);
const ls = proxyquire('../../../lib/cmds/files_cmds/ls', mocks);
const mv = proxyquire('../../../lib/cmds/files_cmds/mv', mocks);

test.beforeEach(t => {
t.context.sandbox = sinon.createSandbox();
Expand All @@ -78,6 +84,7 @@ test.afterEach.always(t => {
listStub.reset();
getStub.reset();
postStub.reset();
patchStub.reset();
delStub.reset();
printSpy.resetHistory();
uploadSpy.resetHistory();
Expand Down Expand Up @@ -236,6 +243,57 @@ test.serial.cb('The "files-download" command should download a set of files from
.parse('download projectId/prefix /dir -r');
});

test.serial.cb('The "files-mv" command should move a set of files from a project', t => {
patchStub.returns({});
listStub.onFirstCall().returns({
data: {
items: [
{
id: '1',
name: 'foo.txt'
}
]
}
});

callback = () => {
t.is(listStub.callCount, 1);
t.is(listStub.getCall(0).args[1], '/v1/files?datasetId=projectId&pageSize=1000&name=prefix');

t.is(patchStub.callCount, 1);
t.is(patchStub.getCall(0).args[1], '/v1/files/1');
t.deepEqual(patchStub.getCall(0).args[2], {
name: '/dir/foo.txt'
});
t.end();
};

t.context.deleteFileStub = t.context.sandbox.stub(fs, 'unlinkSync').callsFake(callback);
t.context.copyFileStub = t.context.sandbox.stub(fs, 'copyFileSync').callsFake(callback);

yargs.command(mv)
.parse('mv projectId/prefix /dir/ -r');
});

test.serial.cb('The "files-mv" command should move a file in a project', t => {
patchStub.returns({});

callback = () => {
t.is(patchStub.callCount, 1);
t.is(patchStub.getCall(0).args[1], '/v1/files/1234');
t.deepEqual(patchStub.getCall(0).args[2], {
name: '/dir/bar.txt'
});
t.end();
};

t.context.deleteFileStub = t.context.sandbox.stub(fs, 'unlinkSync').callsFake(callback);
t.context.copyFileStub = t.context.sandbox.stub(fs, 'copyFileSync').callsFake(callback);

yargs.command(mv)
.parse('mv 1234 /dir/bar.txt');
});

test.serial.cb('The "files-upload" command should upload a file', t => {
const res = { data: { uploadUrl: 'https://host/upload' } };
postStub.onFirstCall().returns(res);
Expand Down