Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit 1577094

Browse files
committed
feat: added mv command
License: MIT Signed-off-by: achingbrain <[email protected]>
1 parent cb0135c commit 1577094

File tree

13 files changed

+371
-75
lines changed

13 files changed

+371
-75
lines changed

src/cli/cp.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ module.exports = {
1111
type: 'boolean',
1212
default: false,
1313
describe: 'Create any non-existent intermediate directories'
14+
},
15+
recursive: {
16+
alias: 'r',
17+
type: 'boolean',
18+
default: false,
19+
describe: 'Remove directories recursively'
1420
}
1521
},
1622

@@ -19,11 +25,13 @@ module.exports = {
1925
source,
2026
dest,
2127
ipfs,
22-
parents
28+
parents,
29+
recursive
2330
} = argv
2431

2532
ipfs.mfs.cp(source, dest, {
26-
parents
33+
parents,
34+
recursive
2735
}, (error) => {
2836
if (error) {
2937
throw error

src/cli/mv.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict'
2+
3+
module.exports = {
4+
command: 'mv <source> <dest>',
5+
6+
describe: 'Move files around. Just like traditional unix mv',
7+
8+
builder: {
9+
parents: {
10+
alias: 'p',
11+
type: 'boolean',
12+
default: false,
13+
describe: 'Create any non-existent intermediate directories'
14+
},
15+
recursive: {
16+
alias: 'r',
17+
type: 'boolean',
18+
default: false,
19+
describe: 'Remove directories recursively'
20+
}
21+
},
22+
23+
handler (argv) {
24+
let {
25+
source,
26+
dest,
27+
ipfs,
28+
parents,
29+
recursive
30+
} = argv
31+
32+
ipfs.mfs.mv(source, dest, {
33+
parents,
34+
recursive
35+
}, (error) => {
36+
if (error) {
37+
throw error
38+
}
39+
})
40+
}
41+
}

src/core/cp.js

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ const promisify = require('promisify-es6')
44
const waterfall = require('async/waterfall')
55
const parallel = require('async/parallel')
66
const series = require('async/series')
7-
const path = require('path')
87
const UnixFs = require('ipfs-unixfs')
98
const {
109
traverseTo,
1110
addLink,
1211
updateTree,
13-
updateMfsRoot
12+
updateMfsRoot,
13+
toSourcesAndDestination
1414
} = require('./utils')
1515
const stat = require('./stat')
1616

1717
const defaultOptions = {
1818
parents: false,
19+
recursive: false,
1920
flush: true,
2021
format: 'dag-pb',
2122
hashAlg: 'sha2-256'
@@ -24,36 +25,19 @@ const defaultOptions = {
2425
module.exports = function mfsCp (ipfs) {
2526
return promisify(function () {
2627
const args = Array.prototype.slice.call(arguments)
27-
const callback = args.pop()
28-
29-
if (args.length < 2) {
30-
return callback(new Error('Please specify a source(s) and a destination'))
31-
}
32-
33-
let destination = args.pop()
34-
let options = {}
35-
36-
if (typeof destination !== 'string') {
37-
options = destination
38-
destination = args.pop()
39-
}
40-
41-
options = Object.assign({}, defaultOptions, options)
42-
43-
const sources = args.map(source => ({
44-
path: source,
45-
name: path.basename(source),
46-
dir: path.dirname(source)
47-
}))
48-
49-
destination = {
50-
path: destination,
51-
name: path.basename(destination),
52-
dir: path.dirname(destination)
28+
const {
29+
sources,
30+
destination,
31+
options,
32+
callback
33+
} = toSourcesAndDestination(args, defaultOptions)
34+
35+
if (!sources.length) {
36+
return callback(new Error('Please supply at least one source'))
5337
}
5438

55-
if (sources.length < 1) {
56-
return callback(new Error('Please specify a path to copy'))
39+
if (!destination) {
40+
return callback(new Error('Please supply a destination'))
5741
}
5842

5943
traverseTo(ipfs, destination.path, {}, (error, result) => {

src/core/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module.exports = {
44
cp: require('./cp'),
55
ls: require('./ls'),
66
mkdir: require('./mkdir'),
7+
mv: require('./mv'),
78
read: require('./read'),
89
rm: require('./rm'),
910
stat: require('./stat'),

src/core/mv.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict'
2+
3+
const promisify = require('promisify-es6')
4+
const series = require('async/series')
5+
const {
6+
toSources
7+
} = require('./utils')
8+
const cp = require('./cp')
9+
const rm = require('./rm')
10+
11+
const defaultOptions = {
12+
parents: false,
13+
recursive: false,
14+
flush: true,
15+
format: 'dag-pb',
16+
hashAlg: 'sha2-256'
17+
}
18+
19+
module.exports = function mfsCp (ipfs) {
20+
return promisify(function () {
21+
const {
22+
callback
23+
} = toSources(Array.prototype.slice.call(arguments), defaultOptions)
24+
25+
// remove the callback
26+
const cpArgs = Array.prototype.slice.call(arguments)
27+
.filter(arg => typeof arg !== 'function')
28+
29+
// remove the last string in the args as it'll be the destination
30+
const lastStringIndex = cpArgs.reduce((acc, curr, index) => {
31+
if (typeof curr === 'string') {
32+
return index
33+
}
34+
35+
return acc
36+
}, -1)
37+
const rmArgs = cpArgs
38+
.filter((arg, index) => index !== lastStringIndex)
39+
.slice(0, cpArgs.length - 1)
40+
41+
series([
42+
(cb) => cp(ipfs).apply(null, cpArgs.concat(cb)),
43+
(cb) => rm(ipfs).apply(null, rmArgs.concat(cb))
44+
], callback)
45+
})
46+
}

src/core/rm.js

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const promisify = require('promisify-es6')
44
const UnixFs = require('ipfs-unixfs')
55
const waterfall = require('async/waterfall')
6+
const series = require('async/series')
67
const {
78
DAGNode
89
} = require('ipld-dag-pb')
@@ -11,6 +12,7 @@ const {
1112
traverseTo,
1213
updateTree,
1314
updateMfsRoot,
15+
toSources,
1416
FILE_SEPARATOR
1517
} = require('./utils')
1618

@@ -19,50 +21,57 @@ const defaultOptions = {
1921
}
2022

2123
module.exports = function mfsRm (ipfs) {
22-
return promisify(function (path, options, callback) {
23-
if (typeof path === 'function') {
24-
return path(new Error('Please specify a path to remove'))
25-
}
24+
return promisify(function () {
25+
const args = Array.prototype.slice.call(arguments)
26+
const {
27+
sources,
28+
options,
29+
callback
30+
} = toSources(args, defaultOptions)
2631

27-
if (!callback) {
28-
callback = options
29-
options = {}
32+
if (!sources.length) {
33+
return callback(new Error('Please supply at least one path to remove'))
3034
}
3135

32-
options = Object.assign({}, defaultOptions, options)
33-
34-
path = path.trim()
36+
series(
37+
sources.map(source => {
38+
return (done) => removePath(ipfs, source.path, options, done)
39+
}),
40+
callback
41+
)
42+
})
43+
}
3544

36-
if (path === FILE_SEPARATOR) {
37-
return callback(new Error('Cannot delete root'))
38-
}
45+
const removePath = (ipfs, path, options, callback) => {
46+
if (path === FILE_SEPARATOR) {
47+
return callback(new Error('Cannot delete root'))
48+
}
3949

40-
waterfall([
41-
(cb) => traverseTo(ipfs, path, {
42-
withCreateHint: false
43-
}, cb),
44-
(result, cb) => {
45-
const meta = UnixFs.unmarshal(result.node.data)
50+
waterfall([
51+
(cb) => traverseTo(ipfs, path, {
52+
withCreateHint: false
53+
}, cb),
54+
(result, cb) => {
55+
const meta = UnixFs.unmarshal(result.node.data)
4656

47-
if (meta.type === 'directory' && !options.recursive) {
48-
return cb(new Error(`${path} is a directory, use -r to remove directories`))
49-
}
57+
if (meta.type === 'directory' && !options.recursive) {
58+
return cb(new Error(`${path} is a directory, use -r to remove directories`))
59+
}
5060

51-
waterfall([
52-
(next) => DAGNode.rmLink(result.parent.node, result.name, next),
53-
(newParentNode, next) => {
54-
ipfs.dag.put(newParentNode, {
55-
cid: new CID(newParentNode.hash || newParentNode.multihash)
56-
}, (error) => next(error, newParentNode))
57-
},
58-
(newParentNode, next) => {
59-
result.parent.node = newParentNode
61+
waterfall([
62+
(next) => DAGNode.rmLink(result.parent.node, result.name, next),
63+
(newParentNode, next) => {
64+
ipfs.dag.put(newParentNode, {
65+
cid: new CID(newParentNode.hash || newParentNode.multihash)
66+
}, (error) => next(error, newParentNode))
67+
},
68+
(newParentNode, next) => {
69+
result.parent.node = newParentNode
6070

61-
updateTree(ipfs, result.parent, next)
62-
},
63-
(newRoot, next) => updateMfsRoot(ipfs, newRoot.node.multihash, next)
64-
], cb)
65-
}
66-
], callback)
67-
})
71+
updateTree(ipfs, result.parent, next)
72+
},
73+
(newRoot, next) => updateMfsRoot(ipfs, newRoot.node.multihash, next)
74+
], cb)
75+
}
76+
], callback)
6877
}

src/core/utils/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const constants = require('./constants')
44

55
module.exports = {
66
endPullStream: require('./end-pull-stream'),
7+
toSources: require('./to-sources'),
8+
toSourcesAndDestination: require('./to-sources-and-destination'),
79
validatePath: require('./validate-path'),
810
withMfsRoot: require('./with-mfs-root'),
911
updateMfsRoot: require('./update-mfs-root'),
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict'
2+
3+
const toSources = require('./to-sources')
4+
5+
function toSourcesAndDestination (args, defaultOptions) {
6+
const {
7+
sources,
8+
options,
9+
callback
10+
} = toSources(args, defaultOptions)
11+
12+
const destination = sources.pop()
13+
14+
return {
15+
sources,
16+
destination,
17+
options,
18+
callback
19+
}
20+
}
21+
22+
module.exports = toSourcesAndDestination

src/core/utils/to-sources.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict'
2+
3+
const path = require('path')
4+
5+
function toSources (args, defaultOptions) {
6+
args = args.slice()
7+
const callback = args.filter(arg => typeof arg === 'function').pop()
8+
const options = Object.assign({}, defaultOptions, args.filter(arg => typeof arg === 'object').pop() || {})
9+
10+
const sources = args
11+
.filter(arg => typeof arg === 'string')
12+
.map(source => {
13+
source = source.trim()
14+
15+
return {
16+
path: source,
17+
name: path.basename(source),
18+
dir: path.dirname(source)
19+
}
20+
})
21+
22+
return {
23+
sources,
24+
options,
25+
callback
26+
}
27+
}
28+
29+
module.exports = toSources

test/browser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require('./cp.spec.js')
44
require('./ls.spec.js')
55
require('./mkdir.spec.js')
6+
require('./mv.spec.js')
67
require('./read.spec.js')
78
require('./write.spec.js')
89
require('./rm.spec.js')

0 commit comments

Comments
 (0)