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

Commit

Permalink
feat: added mv command
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: achingbrain <[email protected]>
  • Loading branch information
achingbrain committed May 8, 2018
1 parent cb0135c commit 1577094
Show file tree
Hide file tree
Showing 13 changed files with 371 additions and 75 deletions.
12 changes: 10 additions & 2 deletions src/cli/cp.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ module.exports = {
type: 'boolean',
default: false,
describe: 'Create any non-existent intermediate directories'
},
recursive: {
alias: 'r',
type: 'boolean',
default: false,
describe: 'Remove directories recursively'
}
},

Expand All @@ -19,11 +25,13 @@ module.exports = {
source,
dest,
ipfs,
parents
parents,
recursive
} = argv

ipfs.mfs.cp(source, dest, {
parents
parents,
recursive
}, (error) => {
if (error) {
throw error
Expand Down
41 changes: 41 additions & 0 deletions src/cli/mv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict'

module.exports = {
command: 'mv <source> <dest>',

describe: 'Move files around. Just like traditional unix mv',

builder: {
parents: {
alias: 'p',
type: 'boolean',
default: false,
describe: 'Create any non-existent intermediate directories'
},
recursive: {
alias: 'r',
type: 'boolean',
default: false,
describe: 'Remove directories recursively'
}
},

handler (argv) {
let {
source,
dest,
ipfs,
parents,
recursive
} = argv

ipfs.mfs.mv(source, dest, {
parents,
recursive
}, (error) => {
if (error) {
throw error
}
})
}
}
44 changes: 14 additions & 30 deletions src/core/cp.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ const promisify = require('promisify-es6')
const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const series = require('async/series')
const path = require('path')
const UnixFs = require('ipfs-unixfs')
const {
traverseTo,
addLink,
updateTree,
updateMfsRoot
updateMfsRoot,
toSourcesAndDestination
} = require('./utils')
const stat = require('./stat')

const defaultOptions = {
parents: false,
recursive: false,
flush: true,
format: 'dag-pb',
hashAlg: 'sha2-256'
Expand All @@ -24,36 +25,19 @@ const defaultOptions = {
module.exports = function mfsCp (ipfs) {
return promisify(function () {
const args = Array.prototype.slice.call(arguments)
const callback = args.pop()

if (args.length < 2) {
return callback(new Error('Please specify a source(s) and a destination'))
}

let destination = args.pop()
let options = {}

if (typeof destination !== 'string') {
options = destination
destination = args.pop()
}

options = Object.assign({}, defaultOptions, options)

const sources = args.map(source => ({
path: source,
name: path.basename(source),
dir: path.dirname(source)
}))

destination = {
path: destination,
name: path.basename(destination),
dir: path.dirname(destination)
const {
sources,
destination,
options,
callback
} = toSourcesAndDestination(args, defaultOptions)

if (!sources.length) {
return callback(new Error('Please supply at least one source'))
}

if (sources.length < 1) {
return callback(new Error('Please specify a path to copy'))
if (!destination) {
return callback(new Error('Please supply a destination'))
}

traverseTo(ipfs, destination.path, {}, (error, result) => {
Expand Down
1 change: 1 addition & 0 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
cp: require('./cp'),
ls: require('./ls'),
mkdir: require('./mkdir'),
mv: require('./mv'),
read: require('./read'),
rm: require('./rm'),
stat: require('./stat'),
Expand Down
46 changes: 46 additions & 0 deletions src/core/mv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict'

const promisify = require('promisify-es6')
const series = require('async/series')
const {
toSources
} = require('./utils')
const cp = require('./cp')
const rm = require('./rm')

const defaultOptions = {
parents: false,
recursive: false,
flush: true,
format: 'dag-pb',
hashAlg: 'sha2-256'
}

module.exports = function mfsCp (ipfs) {
return promisify(function () {
const {
callback
} = toSources(Array.prototype.slice.call(arguments), defaultOptions)

// remove the callback
const cpArgs = Array.prototype.slice.call(arguments)
.filter(arg => typeof arg !== 'function')

// remove the last string in the args as it'll be the destination
const lastStringIndex = cpArgs.reduce((acc, curr, index) => {
if (typeof curr === 'string') {
return index
}

return acc
}, -1)
const rmArgs = cpArgs
.filter((arg, index) => index !== lastStringIndex)
.slice(0, cpArgs.length - 1)

series([
(cb) => cp(ipfs).apply(null, cpArgs.concat(cb)),
(cb) => rm(ipfs).apply(null, rmArgs.concat(cb))
], callback)
})
}
85 changes: 47 additions & 38 deletions src/core/rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const promisify = require('promisify-es6')
const UnixFs = require('ipfs-unixfs')
const waterfall = require('async/waterfall')
const series = require('async/series')
const {
DAGNode
} = require('ipld-dag-pb')
Expand All @@ -11,6 +12,7 @@ const {
traverseTo,
updateTree,
updateMfsRoot,
toSources,
FILE_SEPARATOR
} = require('./utils')

Expand All @@ -19,50 +21,57 @@ const defaultOptions = {
}

module.exports = function mfsRm (ipfs) {
return promisify(function (path, options, callback) {
if (typeof path === 'function') {
return path(new Error('Please specify a path to remove'))
}
return promisify(function () {
const args = Array.prototype.slice.call(arguments)
const {
sources,
options,
callback
} = toSources(args, defaultOptions)

if (!callback) {
callback = options
options = {}
if (!sources.length) {
return callback(new Error('Please supply at least one path to remove'))
}

options = Object.assign({}, defaultOptions, options)

path = path.trim()
series(
sources.map(source => {
return (done) => removePath(ipfs, source.path, options, done)
}),
callback
)
})
}

if (path === FILE_SEPARATOR) {
return callback(new Error('Cannot delete root'))
}
const removePath = (ipfs, path, options, callback) => {
if (path === FILE_SEPARATOR) {
return callback(new Error('Cannot delete root'))
}

waterfall([
(cb) => traverseTo(ipfs, path, {
withCreateHint: false
}, cb),
(result, cb) => {
const meta = UnixFs.unmarshal(result.node.data)
waterfall([
(cb) => traverseTo(ipfs, path, {
withCreateHint: false
}, cb),
(result, cb) => {
const meta = UnixFs.unmarshal(result.node.data)

if (meta.type === 'directory' && !options.recursive) {
return cb(new Error(`${path} is a directory, use -r to remove directories`))
}
if (meta.type === 'directory' && !options.recursive) {
return cb(new Error(`${path} is a directory, use -r to remove directories`))
}

waterfall([
(next) => DAGNode.rmLink(result.parent.node, result.name, next),
(newParentNode, next) => {
ipfs.dag.put(newParentNode, {
cid: new CID(newParentNode.hash || newParentNode.multihash)
}, (error) => next(error, newParentNode))
},
(newParentNode, next) => {
result.parent.node = newParentNode
waterfall([
(next) => DAGNode.rmLink(result.parent.node, result.name, next),
(newParentNode, next) => {
ipfs.dag.put(newParentNode, {
cid: new CID(newParentNode.hash || newParentNode.multihash)
}, (error) => next(error, newParentNode))
},
(newParentNode, next) => {
result.parent.node = newParentNode

updateTree(ipfs, result.parent, next)
},
(newRoot, next) => updateMfsRoot(ipfs, newRoot.node.multihash, next)
], cb)
}
], callback)
})
updateTree(ipfs, result.parent, next)
},
(newRoot, next) => updateMfsRoot(ipfs, newRoot.node.multihash, next)
], cb)
}
], callback)
}
2 changes: 2 additions & 0 deletions src/core/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const constants = require('./constants')

module.exports = {
endPullStream: require('./end-pull-stream'),
toSources: require('./to-sources'),
toSourcesAndDestination: require('./to-sources-and-destination'),
validatePath: require('./validate-path'),
withMfsRoot: require('./with-mfs-root'),
updateMfsRoot: require('./update-mfs-root'),
Expand Down
22 changes: 22 additions & 0 deletions src/core/utils/to-sources-and-destination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const toSources = require('./to-sources')

function toSourcesAndDestination (args, defaultOptions) {
const {
sources,
options,
callback
} = toSources(args, defaultOptions)

const destination = sources.pop()

return {
sources,
destination,
options,
callback
}
}

module.exports = toSourcesAndDestination
29 changes: 29 additions & 0 deletions src/core/utils/to-sources.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict'

const path = require('path')

function toSources (args, defaultOptions) {
args = args.slice()
const callback = args.filter(arg => typeof arg === 'function').pop()
const options = Object.assign({}, defaultOptions, args.filter(arg => typeof arg === 'object').pop() || {})

const sources = args
.filter(arg => typeof arg === 'string')
.map(source => {
source = source.trim()

return {
path: source,
name: path.basename(source),
dir: path.dirname(source)
}
})

return {
sources,
options,
callback
}
}

module.exports = toSources
1 change: 1 addition & 0 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require('./cp.spec.js')
require('./ls.spec.js')
require('./mkdir.spec.js')
require('./mv.spec.js')
require('./read.spec.js')
require('./write.spec.js')
require('./rm.spec.js')
Expand Down
Loading

0 comments on commit 1577094

Please sign in to comment.