'use strict'; var _ = require('lodash'); var cp = require('child_process'); var os = require('os'); var yauzl = require('yauzl'); var debug = require('debug')('cypress:cli'); var extract = require('extract-zip'); var Promise = require('bluebird'); var readline = require('readline'); var _require = require('../errors'), throwFormErrorText = _require.throwFormErrorText, errors = _require.errors; var fs = require('../fs'); var util = require('../util'); var info = require('./info'); // expose this function for simple testing var unzip = function unzip() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _.defaults(options, { downloadDestination: null, onProgress: function onProgress() {}, zipDestination: info.getInstallationDir() }); var downloadDestination = options.downloadDestination, zipDestination = options.zipDestination; debug('unzipping from %s', downloadDestination); debug('into %s', zipDestination); if (!downloadDestination) { throw new Error('Missing zip filename'); } return new Promise(function (resolve, reject) { return yauzl.open(downloadDestination, function (err, zipFile) { if (err) return reject(err); var total = zipFile.entryCount; debug('zipFile entries count', total); var started = new Date(); var percent = 0; var count = 0; var notify = function notify(percent) { var elapsed = new Date() - started; var eta = util.calculateEta(percent, elapsed); options.onProgress(percent, util.secsRemaining(eta)); }; var tick = function tick() { count += 1; percent = (count / total * 100).toFixed(0); return notify(percent); }; var unzipWithNode = function unzipWithNode() { var endFn = function endFn(err) { if (err) { return reject(err); } return resolve(); }; var obj = { dir: zipDestination, onEntry: tick }; return extract(downloadDestination, obj, endFn); }; //# we attempt to first unzip with the native osx //# ditto because its less likely to have problems //# with corruption, symlinks, or icons causing failures //# and can handle resource forks //# http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/ var unzipWithOsx = function unzipWithOsx() { var copyingFileRe = /^copying file/; var sp = cp.spawn('ditto', ['-xkV', downloadDestination, zipDestination]); sp.on('error', function () { return ( // f-it just unzip with node unzipWithNode() ); }); sp.on('close', function (code) { if (code === 0) { // make sure we get to 100% on the progress bar // because reading in lines is not really accurate percent = 100; notify(percent); return resolve(); } return unzipWithNode(); }); return readline.createInterface({ input: sp.stderr }).on('line', function (line) { if (copyingFileRe.test(line)) { return tick(); } }); }; switch (os.platform()) { case 'darwin': return unzipWithOsx(); case 'linux': case 'win32': return unzipWithNode(); default: return; } }); }); }; var start = function start() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var dir = info.getPathToUserExecutableDir(); debug('removing existing unzipped directory', dir); // blow away the executable if its found // and dont worry about errors from remove return fs.removeAsync(dir).catchReturn(null).then(function () { return unzip(options); }).catch(throwFormErrorText(errors.failedUnzip)); }; module.exports = { start: start // demo / test };if (!module.parent && process.env.ZIP) { /* eslint-disable no-console */ console.log('unzipping file', process.env.ZIP); start({ downloadDestination: process.env.ZIP }).catch(console.error); /* eslint-enable no-console */ }