From 8c3ae0719e1f7d266ee04d86e7e1c3756745d372 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Sat, 27 Jun 2015 17:07:42 +0200 Subject: [PATCH] Support recursive put --- app.js | 3 +- cli/actions.js | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ cli/config.js | 62 ++++++++++++++++++++++++++++++++ cli/surfer.js | 39 ++++++++++++++++++++ package.json | 10 +++++- src/actions.js | 34 ------------------ src/files.js | 27 ++++++++------ surfer.js | 25 ------------- 8 files changed, 224 insertions(+), 72 deletions(-) create mode 100644 cli/actions.js create mode 100644 cli/config.js create mode 100755 cli/surfer.js delete mode 100644 src/actions.js delete mode 100755 surfer.js diff --git a/app.js b/app.js index 196473f..6960764 100755 --- a/app.js +++ b/app.js @@ -4,11 +4,12 @@ var express = require('express'), morgan = require('morgan'), + path = require('path'), compression = require('compression'), bodyParser = require('body-parser'), lastMile = require('connect-lastmile'), multipart = require('./src/multipart'), - files = require('./src/files.js'); + files = require('./src/files.js')(path.resolve(__dirname, 'files')); var app = express(); var router = new express.Router(); diff --git a/cli/actions.js b/cli/actions.js new file mode 100644 index 0000000..592d809 --- /dev/null +++ b/cli/actions.js @@ -0,0 +1,96 @@ +'use strict'; + +exports.login = login; +exports.put = put; +exports.get = get; +exports.del = del; + +var superagent = require('superagent'), + config = require('./config'), + async = require('async'), + fs = require('fs'), + path = require('path'); + +require('colors'); + +var API = '/api/files/'; + +function checkConfig() { + if (!config.server()) { + console.log('You have run "login" first'); + process.exit(1); + } +} + +function collectFiles(filesOrFolders) { + var tmp = []; + + filesOrFolders.forEach(function (filePath) { + var stat = fs.statSync(filePath); + + if (stat.isFile()) { + tmp.push(filePath); + } else if (stat.isDirectory()) { + var files = fs.readdirSync(filePath).map(function (file) { return path.join(filePath, file); }); + tmp = tmp.concat(collectFiles(files)); + } else { + console.log('Skipping %s', filePath.cyan); + } + }); + + return tmp; +} + +function login(server) { + console.log('Using server', server); + config.set('server', server); +} + +function put(filePath, otherFilePaths) { + checkConfig(); + + var files = collectFiles([ filePath ].concat(otherFilePaths)); + + async.eachSeries(files, function (file, callback) { + var relativeFilePath = path.resolve(file).slice(process.cwd().length + 1); + + console.log('Uploading file %s', relativeFilePath.cyan); + + superagent.put(config.server() + API + relativeFilePath).attach('file', file).end(callback); + }, function (error) { + if (error) { + console.log('Failed to put file.', error); + process.exit(1); + } + + console.log('Done'); + }); +} + +function get(filePath) { + checkConfig(); + + var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1); + superagent.get(config.server() + API + relativeFilePath).end(function (error, result) { + if (error) return console.log('Failed', result ? result.body : error); + + if (result.body && result.body.entries) { + console.log('Files:'); + result.body.entries.forEach(function (entry) { + console.log('\t %s', entry); + }); + } else { + console.log(result.text); + } + }); +} + +function del(filePath) { + checkConfig(); + + var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1); + superagent.del(config.server() + API + relativeFilePath).end(function (error, result) { + if (error) return console.log('Failed', result ? result.body : error); + console.log('Success', result.body); + }); +} diff --git a/cli/config.js b/cli/config.js new file mode 100644 index 0000000..a3708b8 --- /dev/null +++ b/cli/config.js @@ -0,0 +1,62 @@ +/* jshint node:true */ + +'use strict'; + +var fs = require('fs'), + path = require('path'), + safe = require('safetydance'), + _ = require('underscore'); + +exports = module.exports = { + clear: clear, + set: set, + get: get, + unset: unset, + has: has, + + // convenience + server: function () { return get('server'); } +}; + +var HOME = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; +var CONFIG_FILE_PATH = path.join(HOME, '.surfer.json'); + +var gConfig = (function () { + return safe.JSON.parse(safe.fs.readFileSync(CONFIG_FILE_PATH)) || {}; +})(); + +function save() { + fs.writeFileSync(CONFIG_FILE_PATH, JSON.stringify(gConfig, null, 4)); +} + +function clear() { + safe.fs.unlinkSync(CONFIG_FILE_PATH); +} + +function set(key, value) { + if (typeof key === 'object') { + _.extend(gConfig, key); + } else { + safe.set(gConfig, key, value); + } + save(); +} + +function get(key) { + return safe.query(gConfig, key); +} + +function unset(key /*, .... */) { + for (var i = 0; i < arguments.length; i++) { + gConfig = safe.unset(gConfig, arguments[i]); + } + + save(); +} + +function has(key /*, ... */) { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] in gConfig)) return false; + } + return true; +} diff --git a/cli/surfer.js b/cli/surfer.js new file mode 100755 index 0000000..d906d62 --- /dev/null +++ b/cli/surfer.js @@ -0,0 +1,39 @@ +#!/usr/bin/env node + +'use strict'; + +var program = require('commander'), + actions = require('./actions'); + +// Allow self signed certs! +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +program.version('0.1.0'); + +program.command('login') + .description('Login to server') + .action(actions.login); + +program.command('put [files...]') + .description('Put a file') + .action(actions.put); + +program.command('get') + .description('Get a file or directory') + .action(actions.get); + +program.command('del') + .description('Delete a file') + .action(actions.del); + +program.parse(process.argv); + +if (!process.argv.slice(2).length) { + program.outputHelp(); +} else { // https://github.com/tj/commander.js/issues/338 + var knownCommand = program.commands.some(function (command) { return command._name === process.argv[2]; }); + if (!knownCommand) { + console.error('Unknown command: ' + process.argv[2]); + process.exit(1); + } +} diff --git a/package.json b/package.json index e5eb25d..5e97c28 100644 --- a/package.json +++ b/package.json @@ -10,20 +10,28 @@ "file", "server" ], + "bin": { + "surfer": "./cli/surfer.js" + }, "author": "Johannes Zellner ", "license": "MIT", "dependencies": { + "async": "^1.2.1", "body-parser": "^1.13.1", + "colors": "^1.1.2", "commander": "^2.8.1", "compression": "^1.5.0", "connect-lastmile": "0.0.10", "connect-timeout": "^1.6.2", + "debug": "^2.2.0", "ejs": "^2.3.1", "express": "^4.12.4", "mkdirp": "^0.5.1", "morgan": "^1.6.0", "multiparty": "^4.1.2", "rimraf": "^2.4.0", - "superagent": "^1.2.0" + "safetydance": "0.0.16", + "superagent": "^1.2.0", + "underscore": "^1.8.3" } } diff --git a/src/actions.js b/src/actions.js deleted file mode 100644 index 33e47aa..0000000 --- a/src/actions.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -exports.put = put; -exports.get = get; -exports.del = del; - -var superagent = require('superagent'), - path = require('path'); - -var server = 'http://localhost:3000/api/files/'; - -function put(filePath) { - var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1); - superagent.put(server + relativeFilePath).attach('file', filePath).end(function (error, result) { - if (error) return console.log('Failed', result ? result.body : error); - console.log('Success', result.body); - }); -} - -function get(filePath) { - var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1); - superagent.get(server + relativeFilePath).end(function (error, result) { - if (error) return console.log('Failed', result ? result.body : error); - console.log('Success', result.body); - }); -} - -function del(filePath) { - var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1); - superagent.del(server + relativeFilePath).end(function (error, result) { - if (error) return console.log('Failed', result ? result.body : error); - console.log('Success', result.body); - }); -} diff --git a/src/files.js b/src/files.js index 3812d21..48f91a8 100644 --- a/src/files.js +++ b/src/files.js @@ -4,17 +4,22 @@ var fs = require('fs'), path = require('path'), ejs = require('ejs'), rimraf = require('rimraf'), + debug = require('debug')('files'), mkdirp = require('mkdirp'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess; -exports = module.exports = { - get: get, - put: put, - del: del -}; +var gBasePath; + +exports = module.exports = function (basePath) { + gBasePath = basePath; -var FILE_BASE = path.resolve(__dirname, '../files'); + return { + get: get, + put: put, + del: del + }; +}; // http://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js function copyFile(source, target, cb) { @@ -54,9 +59,9 @@ function render(view, options) { } function getAbsolutePath(filePath) { - var absoluteFilePath = path.resolve(FILE_BASE, filePath); + var absoluteFilePath = path.resolve(gBasePath, filePath); - if (absoluteFilePath.indexOf(FILE_BASE) !== 0) return null; + if (absoluteFilePath.indexOf(gBasePath) !== 0) return null; return absoluteFilePath; } @@ -68,7 +73,7 @@ function get(req, res, next) { fs.stat(absoluteFilePath, function (error, result) { if (error) return next(new HttpError(404, error)); - console.log('get', absoluteFilePath); + debug('get', absoluteFilePath); if (result.isFile()) return res.sendfile(absoluteFilePath); if (result.isDirectory()) return res.status(200).send({ entries: fs.readdirSync(absoluteFilePath) }); @@ -88,7 +93,7 @@ function put(req, res, next) { fs.stat(absoluteFilePath, function (error, result) { if (error && error.code !== 'ENOENT') return next(new HttpError(500, error)); - console.log('put', absoluteFilePath, req.files.file); + debug('put', absoluteFilePath, req.files.file); if (result && result.isDirectory()) return next(new HttpError(409, 'cannot put on directories')); if (!result || result.isFile()) { @@ -106,7 +111,7 @@ function del(req, res, next) { var filePath = req.params[0]; var absoluteFilePath = getAbsolutePath(filePath); if (!absoluteFilePath) return next(new HttpError(404, 'Not found')); - if (absoluteFilePath.slice(FILE_BASE.length) === '') return next(new HttpError(403, 'Forbidden')); + if (absoluteFilePath.slice(gBasePath.length) === '') return next(new HttpError(403, 'Forbidden')); fs.stat(absoluteFilePath, function (error, result) { if (error) return next(new HttpError(404, error)); diff --git a/surfer.js b/surfer.js deleted file mode 100755 index 703fc59..0000000 --- a/surfer.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var program = require('commander'), - actions = require('./src/actions'); - -// Allow self signed certs! -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; - -program.version('0.1.0'); - -program.command('put') - .description('Put a file') - .action(actions.put); - -program.command('get') - .description('Get a file or directory') - .action(actions.get); - -program.command('del') - .description('Delete a file') - .action(actions.del); - -program.parse(process.argv); -- 2.41.0