-
Notifications
You must be signed in to change notification settings - Fork 1.2k
files add, cat, get core + cli #197
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,45 @@ | ||
'use strict' | ||
|
||
const Command = require('ronin').Command | ||
const IPFS = require('../../../core') | ||
const utils = require('../../utils') | ||
const debug = require('debug') | ||
const log = debug('cli:version') | ||
log.error = debug('cli:version:error') | ||
const bs58 = require('bs58') | ||
const fs = require('fs') | ||
const async = require('async') | ||
const path = require('path') | ||
const glob = require('glob') | ||
|
||
function checkPath (inPath, recursive) { | ||
// This function is to check for the following possible inputs | ||
// 1) "." add the cwd but throw error for no recursion flag | ||
// 2) "." -r return the cwd | ||
// 3) "/some/path" but throw error for no recursion | ||
// 4) "/some/path" -r | ||
// 5) No path, throw err | ||
// 6) filename.type return the cwd + filename | ||
|
||
if (!inPath) { | ||
throw new Error('Error: Argument \'path\' is required') | ||
} | ||
|
||
var s = fs.statSync(inPath) | ||
|
||
if (s.isDirectory() && recursive === false) { | ||
throw new Error('Error: ' + process.cwd() + ' is a directory, use the \'-r\' flag to specify directories') | ||
} | ||
if (inPath === '.' && recursive === true) { | ||
inPath = process.cwd() | ||
return inPath | ||
} else if (inPath === '.' && recursive === false) { | ||
s = fs.statSync(process.cwd()) | ||
if (s.isDirectory()) { | ||
throw new Error('Error: ' + process.cwd() + ' is a directory, use the \'-r\' flag to specify directories') | ||
} | ||
} | ||
return inPath | ||
} | ||
|
||
module.exports = Command.extend({ | ||
desc: 'Add a file to IPFS using the UnixFS data format', | ||
|
@@ -18,16 +52,53 @@ module.exports = Command.extend({ | |
} | ||
}, | ||
|
||
run: (recursive, path) => { | ||
var node = new IPFS() | ||
path = process.cwd() + '/' + path | ||
node.files.add(path, { | ||
recursive: recursive | ||
}, (err, stats) => { | ||
run: (recursive, inPath) => { | ||
let rs | ||
|
||
inPath = checkPath(inPath, recursive) | ||
|
||
glob(path.join(inPath, '/**/*'), (err, res) => { | ||
if (err) { | ||
return console.log(err) | ||
throw err | ||
} | ||
console.log('added', bs58.encode(stats.Hash).toString(), stats.Name) | ||
utils.getIPFS((err, ipfs) => { | ||
if (err) { | ||
throw err | ||
} | ||
const i = ipfs.files.add() | ||
var filePair | ||
i.on('data', (file) => { | ||
console.log('added', bs58.encode(file.multihash).toString(), file.path) | ||
}) | ||
i.once('end', () => { | ||
return | ||
}) | ||
if (res.length !== 0) { | ||
const index = inPath.lastIndexOf('/') | ||
async.eachLimit(res, 10, (element, callback) => { | ||
const addPath = element.substring(index + 1, element.length) | ||
if (fs.statSync(element).isDirectory()) { | ||
callback() | ||
} else { | ||
rs = fs.createReadStream(element) | ||
filePair = {path: addPath, stream: rs} | ||
i.write(filePair) | ||
callback() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be simplified: if (!fs.statSync(element).isDirectory()) {
i.write({path: addPath, stream: fs.createReadStrem(element})
}
callback() |
||
}, (err) => { | ||
if (err) { | ||
throw err | ||
} | ||
i.end() | ||
}) | ||
} else { | ||
rs = fs.createReadStream(inPath) | ||
inPath = inPath.substring(inPath.lastIndexOf('/') + 1, inPath.length) | ||
filePair = {path: inPath, stream: rs} | ||
i.write(filePair) | ||
i.end() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is all of this doing? Wouldn't glob do this for free? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. glob returns the full path, so I have to trim it to so we don't add unnecessary directories There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't inPath being converted to the filename? Instead of trimming the full path till the Ran an experiment and I can only get the filename, the path value should be the total path relative to where the process was executed.
|
||
} | ||
}) | ||
}) | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
'use strict' | ||
|
||
const Command = require('ronin').Command | ||
const debug = require('debug') | ||
const utils = require('../../utils') | ||
const log = debug('cli:files') | ||
log.error = debug('cli:files:error') | ||
|
||
module.exports = Command.extend({ | ||
desc: 'Download IPFS objects', | ||
|
||
options: {}, | ||
|
||
run: (path, options) => { | ||
if (!path) { | ||
throw new Error("Argument 'path' is required") | ||
} | ||
if (!options) { | ||
options = {} | ||
} | ||
utils.getIPFS((err, ipfs) => { | ||
if (err) { | ||
throw err | ||
} | ||
ipfs.files.cat(path, (err, res) => { | ||
if (err) { | ||
throw (err) | ||
} | ||
if (res) { | ||
res.on('file', (data) => { | ||
data.stream.pipe(process.stdout) | ||
}) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the |
||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are the chances of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was wondering the same logic when you asked on the other PR :D #193 (diff) I will revert to my original conclusion and remove the return |
||
}) | ||
}) | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
'use strict' | ||
|
||
const Command = require('ronin').Command | ||
const debug = require('debug') | ||
const utils = require('../../utils') | ||
const log = debug('cli:files') | ||
log.error = debug('cli:files:error') | ||
var fs = require('fs') | ||
const pathj = require('path') | ||
|
||
module.exports = Command.extend({ | ||
desc: 'Download IPFS objects', | ||
|
||
run: (path, outPath) => { | ||
let dir | ||
let filepath | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. filePath |
||
let ws | ||
|
||
if (!path) { | ||
throw new Error("Argument 'path' is required") | ||
} | ||
if (!outPath) { | ||
outPath = {} | ||
dir = process.cwd() | ||
} else { | ||
if (outPath.slice(-1) !== '/') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you do this often, maybe create a func called "isRootPath" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do this once as an attempt to be like go-ipfs. It is checking to see if you supply a path with either / on the end or without. If you don' t supply a / then one needs to appended to the supplied path. It's just so things don't break if for example you do this
instead of one with a / at the end like
please let me know if there is a better way to achieve this logic in JS There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I see that you can specify a start index for startsWith, but the outPath will be variable length so I don't see how this is useful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nvm I can't read code.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is also |
||
outPath += '/' | ||
} | ||
dir = outPath | ||
} | ||
|
||
utils.getIPFS((err, ipfs) => { | ||
if (err) { | ||
throw err | ||
} | ||
ipfs.files.get(path, (err, data) => { | ||
if (err) { | ||
throw err | ||
} | ||
data.on('file', (data) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is confusing, maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed |
||
if (data.path.lastIndexOf('/') === -1) { | ||
filepath = data.path | ||
if (data.dir === false) { | ||
ws = fs.createWriteStream(pathj.join(dir, data.path)) | ||
data.stream.pipe(ws) | ||
} else { | ||
try { | ||
fs.mkdirSync(pathj.join(dir, data.path)) | ||
} catch (err) { | ||
throw err | ||
} | ||
} | ||
} else { | ||
filepath = data.path.substring(0, data.path.lastIndexOf('/') + 1) | ||
try { | ||
fs.mkdirSync(pathj.join(dir, filepath)) | ||
} catch (err) { | ||
throw err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you catch to throw, better don't even catch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not familiar with another mechanism for ensuring that i don't receive file already exist errors that will break the command.
If there is a better way let me know There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand, you don't check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was not throwing the errors, this was only to make sure that an error did not break the command. I started throwing the error because of another comment or the linter saying that you shouldn't have a try catch without handling the error. I agree that I should switch async mkdir. Will try to check for existence of the path instead of try catching There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
ws = fs.createWriteStream(pathj.join(dir, data.path)) | ||
data.stream.pipe(ws) | ||
} | ||
}) | ||
}) | ||
}) | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,57 @@ | ||
'use strict' | ||
|
||
const importer = require('ipfs-data-importing').import | ||
const Importer = require('ipfs-unixfs-engine').importer | ||
const Exporter = require('ipfs-unixfs-engine').exporter | ||
const UnixFS = require('ipfs-unixfs') | ||
|
||
module.exports = function libp2p (self) { | ||
module.exports = function files (self) { | ||
return { | ||
add: (path, options, callback) => { | ||
options.path = path | ||
options.dagService = self._dagS | ||
importer(options, callback) | ||
add: (arr, callback) => { | ||
if (typeof arr === 'function') { | ||
callback = arr | ||
arr = undefined | ||
} | ||
if (callback === undefined) { | ||
callback = function noop () {} | ||
} | ||
if (arr === undefined) { | ||
return new Importer(self._dagS) | ||
} | ||
|
||
const i = new Importer(self._dagS) | ||
const res = [] | ||
|
||
i.on('data', (info) => { | ||
res.push(info) | ||
}) | ||
|
||
i.once('end', () => { | ||
callback(null, res) | ||
}) | ||
|
||
arr.forEach((tuple) => { | ||
i.write(tuple) | ||
}) | ||
|
||
i.end() | ||
}, | ||
cat: (hash, callback) => { | ||
self._dagS.get(hash, (err, fetchedNode) => { | ||
if (err) { | ||
return callback(err, null) | ||
} | ||
const data = UnixFS.unmarshal(fetchedNode.data) | ||
if (data.type === 'directory') { | ||
callback('This dag node is a directory', null) | ||
} else { | ||
const exportEvent = Exporter(hash, self._dagS) | ||
callback(null, exportEvent) | ||
} | ||
}) | ||
}, | ||
get: (hash, callback) => { | ||
var exportFile = Exporter(hash, self._dagS) | ||
callback(null, exportFile) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,10 @@ const peerId = require('peer-id') | |
const BlockService = require('ipfs-block-service') | ||
const DagService = require('ipfs-merkle-dag').DAGService | ||
const path = require('path') | ||
const glob = require('glob') | ||
const async = require('async') | ||
const Readable = require('stream').Readable | ||
const fs = require('fs') | ||
|
||
module.exports = function init (self) { | ||
return (opts, callback) => { | ||
|
@@ -67,15 +71,45 @@ module.exports = function init (self) { | |
return doneImport(null) | ||
} | ||
|
||
const importer = require('ipfs-data-importing') | ||
const Importer = require('ipfs-unixfs-engine').importer | ||
const blocks = new BlockService(self._repo) | ||
const dag = new DagService(blocks) | ||
|
||
const initDocsPath = path.join(__dirname, '../../init-files/init-docs') | ||
|
||
importer.import(initDocsPath, dag, { | ||
recursive: true | ||
}, doneImport) | ||
const i = new Importer(dag) | ||
i.resume() | ||
|
||
glob(path.join(initDocsPath, '/**/*'), (err, res) => { | ||
if (err) { | ||
throw err | ||
} | ||
const index = __dirname.lastIndexOf('/') | ||
async.eachLimit(res, 10, (element, callback) => { | ||
const addPath = element.substring(index + 1, element.length) | ||
if (fs.statSync(element).isDirectory()) { | ||
callback() | ||
} else { | ||
const buffered = fs.readFileSync(element) | ||
const rs = new Readable() | ||
rs.push(buffered) | ||
rs.push(null) | ||
const filePair = {path: addPath, stream: rs} | ||
i.write(filePair) | ||
callback() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be simplified if (!fs.statSync(element).isDirectory()) {
const rs = new Readable()
rs.push(fs.readFileSync(element))
rs.push(null)
i.write({path: addPath, stream: res})
}
callback() |
||
}, (err) => { | ||
if (err) { | ||
throw err | ||
} | ||
i.end() | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed |
||
}) | ||
}) | ||
|
||
i.once('end', () => { | ||
doneImport(null) | ||
}) | ||
|
||
function doneImport (err, stat) { | ||
if (err) { return callback(err) } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a need for this return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inPath is not declared in this scope and needs to be returned on line 58, unless I'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, since there is the return of inPath in the end of the func and this assignment of inPath is within a if/else clause, you just need the return once