Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit cb0135c

Browse files
committed
feat: copy directories
License: MIT Signed-off-by: achingbrain <[email protected]>
1 parent 60baf97 commit cb0135c

File tree

3 files changed

+88
-23
lines changed

3 files changed

+88
-23
lines changed

src/cli/cp.js

-8
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ module.exports = {
66
describe: 'Copy files between locations in the mfs.',
77

88
builder: {
9-
recursive: {
10-
alias: 'r',
11-
type: 'boolean',
12-
default: false,
13-
describe: 'Copy directories recursively'
14-
},
159
parents: {
1610
alias: 'p',
1711
type: 'boolean',
@@ -25,12 +19,10 @@ module.exports = {
2519
source,
2620
dest,
2721
ipfs,
28-
recursive,
2922
parents
3023
} = argv
3124

3225
ipfs.mfs.cp(source, dest, {
33-
recursive,
3426
parents
3527
}, (error) => {
3628
if (error) {

src/core/cp.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const waterfall = require('async/waterfall')
55
const parallel = require('async/parallel')
66
const series = require('async/series')
77
const path = require('path')
8+
const UnixFs = require('ipfs-unixfs')
89
const {
910
traverseTo,
1011
addLink,
@@ -14,7 +15,6 @@ const {
1415
const stat = require('./stat')
1516

1617
const defaultOptions = {
17-
recursive: false,
1818
parents: false,
1919
flush: true,
2020
format: 'dag-pb',
@@ -56,11 +56,23 @@ module.exports = function mfsCp (ipfs) {
5656
return callback(new Error('Please specify a path to copy'))
5757
}
5858

59-
if (sources.length === 1) {
60-
return copyToFile(ipfs, sources.pop(), destination, options, callback)
61-
}
59+
traverseTo(ipfs, destination.path, {}, (error, result) => {
60+
if (error) {
61+
if (sources.length === 1) {
62+
return copyToFile(ipfs, sources.pop(), destination, options, callback)
63+
} else {
64+
return copyToDirectory(ipfs, sources, destination, options, callback)
65+
}
66+
}
67+
68+
const meta = UnixFs.unmarshal(result.node.data)
69+
70+
if (meta.type === 'directory') {
71+
return copyToDirectory(ipfs, sources, destination, options, callback)
72+
}
6273

63-
copyToDirectory(ipfs, sources, destination, options, callback)
74+
callback(new Error('Directory already has entry by that name'))
75+
})
6476
})
6577
}
6678

@@ -71,7 +83,7 @@ const copyToFile = (ipfs, source, destination, options, callback) => {
7183
(next) => stat(ipfs)(source.path, options, next),
7284
(next) => stat(ipfs)(destination.path, options, (error) => {
7385
if (!error) {
74-
return next(new Error('Destination exists'))
86+
return next(new Error('Directory already has entry by that name'))
7587
}
7688

7789
next()

test/cp.spec.js

+70-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const chai = require('chai')
55
chai.use(require('dirty-chai'))
66
const expect = chai.expect
77
const bufferStream = require('./fixtures/buffer-stream')
8+
const bs58 = require('bs58')
89

910
const {
1011
createMfs
@@ -66,8 +67,23 @@ describe('cp', function () {
6667
})
6768
})
6869

69-
it.skip('refuses to copy multiple files to one file', () => {
70+
it('refuses to copy files to an exsting file', () => {
71+
const source = `/source-file-${Math.random()}.txt`
72+
const destination = `/dest-file-${Math.random()}.txt`
7073

74+
return mfs.write(source, bufferStream(100), {
75+
create: true
76+
})
77+
.then(() => mfs.write(destination, bufferStream(100), {
78+
create: true
79+
}))
80+
.then(() => mfs.cp(source, destination))
81+
.then(() => {
82+
throw new Error('No error was thrown for a non-existent file')
83+
})
84+
.catch(error => {
85+
expect(error.message).to.contain('Directory already has entry by that name')
86+
})
7187
})
7288

7389
it('copies a file to new location', () => {
@@ -89,20 +105,50 @@ describe('cp', function () {
89105
})
90106
})
91107

92-
it.skip('copies a file to a directory', () => {
93-
94-
})
95-
96-
it.skip('copies directories', () => {
108+
it('copies a file to a pre-existing directory', () => {
109+
const source = `/source-file-${Math.random()}.txt`
110+
const directory = `/dest-directory-${Math.random()}`
111+
const destination = `${directory}${source}`
97112

113+
return mfs.write(source, bufferStream(500), {
114+
create: true
115+
})
116+
.then(() => mfs.mkdir(directory))
117+
.then(() => mfs.cp(source, directory))
118+
.then(() => mfs.stat(destination))
119+
.then((stats) => {
120+
expect(stats.size).to.equal(500)
121+
})
98122
})
99123

100-
it.skip('refuses to copy directories recursively without the recursive flag', () => {
124+
it('copies directories', () => {
125+
const source = `/source-directory-${Math.random()}`
126+
const destination = `/dest-directory-${Math.random()}`
101127

128+
return mfs.mkdir(source)
129+
.then(() => mfs.cp(source, destination))
130+
.then(() => mfs.stat(destination))
131+
.then((stats) => {
132+
expect(stats.type).to.equal('directory')
133+
})
102134
})
103135

104-
it.skip('copies directories recursively', () => {
105-
136+
it('copies directories recursively', () => {
137+
const directory = `/source-directory-${Math.random()}`
138+
const subDirectory = `/source-directory-${Math.random()}`
139+
const source = `${directory}/${subDirectory}`
140+
const destination = `/dest-directory-${Math.random()}`
141+
142+
return mfs.mkdir(source)
143+
.then(() => mfs.cp(directory, destination))
144+
.then(() => mfs.stat(destination))
145+
.then((stats) => {
146+
expect(stats.type).to.equal('directory')
147+
})
148+
.then(() => mfs.stat(`${destination}/${subDirectory}`))
149+
.then((stats) => {
150+
expect(stats.type).to.equal('directory')
151+
})
106152
})
107153

108154
it('copies multiple files to new location', () => {
@@ -141,4 +187,19 @@ describe('cp', function () {
141187
)
142188
))
143189
})
190+
191+
it.skip('copies files from ipfs paths', () => {
192+
const source = `/source-file-${Math.random()}.txt`
193+
const destination = `/dest-file-${Math.random()}.txt`
194+
195+
return mfs.write(source, bufferStream(100), {
196+
create: true
197+
})
198+
.then(() => mfs.stat(source))
199+
.then((stats) => mfs.cp(`/ipfs/${bs58.encode(stats.hash)}`, destination))
200+
.then(() => mfs.stat(destination))
201+
.then((stats) => {
202+
expect(stats.size).to.equal(100)
203+
})
204+
})
144205
})

0 commit comments

Comments
 (0)