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

files add, cat, get core + cli #197

Closed
wants to merge 2 commits into from
Closed
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
29 changes: 16 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"test:browser": "aegir-test browser",
"build": "aegir-build",
"release": "aegir-release",
"release:minor": "aegir-release minor",
"release:major": "aegir-release major",
"release:minor": "aegir-release --type minor",
"release:major": "aegir-release --type major",
"coverage-publish": "aegir-coverage publish"
},
"pre-commit": [
Expand All @@ -37,46 +37,49 @@
},
"homepage": "https://github.com/ipfs/js-ipfs#readme",
"devDependencies": {
"aegir": "^3.0.0",
"async": "^2.0.0-rc.3",
"aegir": "^3.0.1",
"async": "^1.5.2",
"buffer-loader": "0.0.1",
"chai": "^3.5.0",
"expose-loader": "^0.7.1",
"form-data": "^1.0.0-rc3",
"idb-plus-blob-store": "^1.1.2",
"lodash": "^4.11.1",
"mocha": "^2.3.4",
"lodash": "^4.11.2",
"mocha": "^2.4.5",
"ncp": "^2.0.0",
"nexpect": "^0.5.0",
"pre-commit": "^1.1.2",
"rimraf": "^2.4.4",
"rimraf": "^2.5.2",
"stream-to-promise": "^1.1.0",
"transform-loader": "^0.2.3"
},
"dependencies": {
"babel-runtime": "^6.6.1",
"bl": "^1.1.2",
"boom": "^3.1.1",
"boom": "^3.1.2",
"bs58": "^3.0.0",
"debug": "^2.2.0",
"fs-blob-store": "^5.2.1",
"glob": "^7.0.3",
"hapi": "^13.3.0",
"ipfs-api": "^3.0.1",
"ipfs-api": "^3.0.2",
"ipfs-block": "^0.3.0",
"ipfs-block-service": "^0.3.0",
"ipfs-data-importing": "^0.3.3",
"ipfs-merkle-dag": "^0.5.0",
"ipfs-multipart": "^0.1.0",
"ipfs-repo": "^0.8.0",
"joi": "^8.0.2",
"ipfs-unixfs-engine": "^0.6.1",
"joi": "^8.0.5",
"libp2p-ipfs": "^0.3.3",
"libp2p-swarm": "^0.12.5",
"lodash.get": "^4.2.1",
"lodash.set": "^4.0.0",
"multiaddr": "^1.3.0",
"lodash.set": "^4.1.0",
"multiaddr": "^1.4.1",
"path-exists": "^3.0.0",
"peer-book": "0.1.0",
"peer-id": "^0.6.6",
"peer-info": "^0.6.2",
"readable-stream": "^1.1.13",
"ronin": "^0.3.11",
"temp": "^0.8.3"
},
Expand Down
89 changes: 80 additions & 9 deletions src/cli/commands/files/add.js
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
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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

} 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',
Expand All @@ -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()
}
Copy link
Member

Choose a reason for hiding this comment

The 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()
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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

Copy link
Member

Choose a reason for hiding this comment

The 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 cwd?

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.

> var path = '/a/b/c/d'
undefined
> path.substring(path.lastIndexOf('/') + 1, path.length)
'd'

}
})
})
}
})
37 changes: 37 additions & 0 deletions src/cli/commands/files/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'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)
})
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the if (res), in what situation do we do not get an err and no res?

})
})
}
})
107 changes: 107 additions & 0 deletions src/cli/commands/files/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
'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 path = require('path')
const pathExists = require('path-exists')
const async = require('async')

function checkArgs (hash, outPath) {
if (!hash) {
throw new Error("Argument 'path' is required")
}
// format the output directory
if (!outPath) {
var cwd = process.cwd()
return cwd
} else {
if (!outPath.endsWith('/')) {
outPath += '/'
}
if (!outPath.startsWith('/')) {
outPath = path.join('/', outPath)
}
var directory = outPath
return directory
}
}

function getFiles (result, dir) {
var filePath
result.on('file', (file) => {
// Check to see if the result is in a directory
if (file.path.lastIndexOf('/') === -1) {
filePath = file.path
// Check to see if the result is a directory
if (file.dir === false) {
const ws = fs.createWriteStream(path.join(dir, file.path))
file.stream.pipe(ws)
} else {
// Check to see if the directory has already been created
pathExists(path.join(dir, file.path)).then(exists => {
if (!exists) {
fs.mkdir(path.join(dir, file.path), (err) => {
Copy link
Member

@dignifiedquire dignifiedquire May 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about putting this into a function

function ensureDir (dir) {
  pathExists(dir).then((exists) => {
    if (exists) {
      return
    }
    fs.mkdir(dir, (err) => {
      if (err) throw err
    })
  })
  .catch((err) => {
    throw err
  })
}

ensureDir(path.join(dir, file.path))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that way you can reuse it below

if (err) {
throw err
}
})
}
})
}
} else {
// Check to see if the directory has already been created
filePath = file.path.substring(0, file.path.lastIndexOf('/') + 1)
pathExists(path.join(dir, filePath)).then(exists => {
// Create a directory for the incoming files
if (!exists) {
async.waterfall([
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as you are not actually passing values from one function to the next you use async.series

(cb) => {
fs.mkdir(path.join(dir, filePath), (err) => {
if (err) {
cb(err)
}
cb(null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for null, just cb() is enough

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or even simpler:

(cb) => fs.mkdir(path.join(dir, filePath), cb)

})
},
(cb) => {
const ws = fs.createWriteStream(path.join(dir, file.path))
file.stream.pipe(ws)
cb(null)
}
], (err) => {
if (err) {
throw err
}
})
}
// Just write the file
const ws = fs.createWriteStream(path.join(dir, file.path))
file.stream.pipe(ws)
})
}
})
}

module.exports = Command.extend({
desc: 'Download IPFS objects',

run: (hash, outPath) => {
const dir = checkArgs(hash, outPath)

utils.getIPFS((err, ipfs) => {
if (err) {
throw err
}
ipfs.files.get(hash, (err, result) => {
if (err) {
throw err
}
getFiles(result, dir)
})
})
}
})
4 changes: 2 additions & 2 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const BlockService = require('ipfs-block-service')
const mDAG = require('ipfs-merkle-dag')
const DAGService = mDAG.DAGService
const IPFSRepo = require('ipfs-repo')
const PeerBook = require('peer-book')

const defaultRepo = require('./default-repo')
Expand All @@ -27,7 +26,8 @@ function IPFS (repoInstance) {
throw new Error('Must be instantiated with new')
}

if (!(repoInstance instanceof IPFSRepo)) {
if (typeof repoInstance === 'string' ||
repoInstance === undefined) {
repoInstance = defaultRepo(repoInstance)
}

Expand Down
Loading