UNPKG

@jimpick/dat-next

Version:

Dat is the package manager for data. Easily share and version control data.

155 lines (137 loc) 4.71 kB
module.exports = { name: 'clone', command: clone, help: [ 'Clone a remote Dat archive', '', 'Usage: dat clone <link> [download-folder]' ].join('\n'), options: [ { name: 'empty', boolean: false, default: false, help: 'Do not download files by default. Files must be synced manually.' }, { name: 'upload', boolean: true, default: true, help: 'announce your address on link (improves connection capability) and upload data to other downloaders.' }, { name: 'show-key', boolean: true, default: false, abbr: 'k', help: 'print out the dat key' }, { name: 'staging-new-format', alias: ['new'], boolean: true, default: false, help: 'experimental multiwriter support' } ] } function clone (opts) { var fs = require('fs') var path = require('path') var rimraf = require('rimraf') var Dat = require('@jimpick/dat-node') var linkResolve = require('dat-link-resolve') var neatLog = require('neat-log') var archiveUI = require('../ui/archive') var trackArchive = require('../lib/archive') var discoveryExit = require('../lib/discovery-exit') var onExit = require('../lib/exit') var parseArgs = require('../parse-args') var debug = require('debug')('dat') var parsed = parseArgs(opts) opts.key = parsed.key || opts._[0] // pass other links to resolver opts.dir = parsed.dir opts.showKey = opts['show-key'] // using abbr in option makes printed help confusing opts.sparse = opts.empty opts.stagingNewFormat = opts['staging-new-format'] opts.cloning = true debug('clone()') // cmd: dat /path/to/dat.json (opts.key is path to dat.json) if (fs.existsSync(opts.key)) { try { opts.key = getDatJsonKey() } catch (e) { debug('error reading dat.json key', e) } } debug(Object.assign({}, opts, {key: '<private>', _: null})) // don't show key var neat = neatLog(archiveUI, { logspeed: opts.logspeed, quiet: opts.quiet, debug: opts.debug }) neat.use(trackArchive) neat.use(discoveryExit) neat.use(onExit) neat.use(function (state, bus) { if (!opts.key) return bus.emit('exit:warn', 'key required to clone') state.opts = opts var createdDirectory = null // so we can delete directory if we get error // Force these options for clone command opts.exit = (opts.exit !== false) // opts.errorIfExists = true // TODO: do we want to force this? linkResolve(opts.key, function (err, key) { if (err && err.message.indexOf('Invalid key') === -1) return bus.emit('exit:error', 'Could not resolve link') else if (err) return bus.emit('exit:warn', 'Link is not a valid Dat link.') opts.key = key createDir(opts.key, function () { bus.emit('key', key) runDat() }) }) function createDir (key, cb) { debug('Checking directory for clone') // Create the directory if it doesn't exist // If no dir is specified, we put dat in a dir with name = key if (!opts.dir) opts.dir = key if (!Buffer.isBuffer(opts.dir) && typeof opts.dir !== 'string') { return bus.emit('exit:error', 'Directory path must be a string or Buffer') } fs.access(opts.dir, fs.F_OK, function (err) { if (!err) { createdDirectory = false return cb() } debug('No existing directory, creating it.') createdDirectory = true fs.mkdir(opts.dir, cb) }) } function runDat () { Dat(opts.dir, opts, function (err, dat) { if (err && err.name === 'ExistsError') return bus.emit('exit:warn', 'Existing archive in this directory. Use pull or sync to update.') if (err) { if (createdDirectory) rimraf.sync(dat.path) return bus.emit('exit:error', err) } if (!opts.stagingNewFormat && dat.writable) { return bus.emit( 'exit:warn', 'Archive is writable. Cannot clone your own archive =).' ) } state.dat = dat state.title = 'Cloning' bus.emit('dat') bus.emit('render') }) } }) function getDatJsonKey () { var datPath = opts.key var stat = fs.lstatSync(datPath) if (stat.isDirectory()) datPath = path.join(datPath, 'dat.json') if (!fs.existsSync(datPath) || path.basename(datPath) !== 'dat.json') { if (stat.isFile()) throw new Error('must specify existing dat.json file to read key') throw new Error('directory must contain a dat.json') } debug('reading key from dat.json:', datPath) return JSON.parse(fs.readFileSync(datPath, 'utf8')).url } }