unzip.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. 'use strict';
  2. var la = require('lazy-ass');
  3. var is = require('check-more-types');
  4. var cp = require('child_process');
  5. var os = require('os');
  6. var yauzl = require('yauzl');
  7. var debug = require('debug')('cypress:cli');
  8. var extract = require('extract-zip');
  9. var Promise = require('bluebird');
  10. var readline = require('readline');
  11. var _require = require('../errors'),
  12. throwFormErrorText = _require.throwFormErrorText,
  13. errors = _require.errors;
  14. var fs = require('../fs');
  15. var util = require('../util');
  16. // expose this function for simple testing
  17. var unzip = function unzip(_ref) {
  18. var zipFilePath = _ref.zipFilePath,
  19. installDir = _ref.installDir,
  20. progress = _ref.progress;
  21. debug('unzipping from %s', zipFilePath);
  22. debug('into', installDir);
  23. if (!zipFilePath) {
  24. throw new Error('Missing zip filename');
  25. }
  26. return fs.ensureDirAsync(installDir).then(function () {
  27. return new Promise(function (resolve, reject) {
  28. return yauzl.open(zipFilePath, function (err, zipFile) {
  29. if (err) return reject(err);
  30. // debug('zipfile.paths:', zipFile)
  31. // zipFile.on('entry', debug)
  32. // debug(zipFile.readEntry())
  33. var total = zipFile.entryCount;
  34. debug('zipFile entries count', total);
  35. var started = new Date();
  36. var percent = 0;
  37. var count = 0;
  38. var notify = function notify(percent) {
  39. var elapsed = +new Date() - +started;
  40. var eta = util.calculateEta(percent, elapsed);
  41. progress.onProgress(percent, util.secsRemaining(eta));
  42. };
  43. var tick = function tick() {
  44. count += 1;
  45. percent = count / total * 100;
  46. var displayPercent = percent.toFixed(0);
  47. return notify(displayPercent);
  48. };
  49. var unzipWithNode = function unzipWithNode() {
  50. var endFn = function endFn(err) {
  51. if (err) {
  52. return reject(err);
  53. }
  54. return resolve();
  55. };
  56. var opts = {
  57. dir: installDir,
  58. onEntry: tick
  59. };
  60. return extract(zipFilePath, opts, endFn);
  61. };
  62. //# we attempt to first unzip with the native osx
  63. //# ditto because its less likely to have problems
  64. //# with corruption, symlinks, or icons causing failures
  65. //# and can handle resource forks
  66. //# http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
  67. var unzipWithOsx = function unzipWithOsx() {
  68. var copyingFileRe = /^copying file/;
  69. var sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
  70. // f-it just unzip with node
  71. sp.on('error', unzipWithNode);
  72. sp.on('close', function (code) {
  73. if (code === 0) {
  74. // make sure we get to 100% on the progress bar
  75. // because reading in lines is not really accurate
  76. percent = 100;
  77. notify(percent);
  78. return resolve();
  79. }
  80. return unzipWithNode();
  81. });
  82. return readline.createInterface({
  83. input: sp.stderr
  84. }).on('line', function (line) {
  85. if (copyingFileRe.test(line)) {
  86. return tick();
  87. }
  88. });
  89. };
  90. switch (os.platform()) {
  91. case 'darwin':
  92. return unzipWithOsx();
  93. case 'linux':
  94. case 'win32':
  95. return unzipWithNode();
  96. default:
  97. return;
  98. }
  99. });
  100. });
  101. });
  102. };
  103. var start = function start(_ref2) {
  104. var zipFilePath = _ref2.zipFilePath,
  105. installDir = _ref2.installDir,
  106. progress = _ref2.progress;
  107. la(is.unemptyString(installDir), 'missing installDir');
  108. if (!progress) {
  109. progress = { onProgress: function onProgress() {
  110. return {};
  111. } };
  112. }
  113. return fs.pathExists(installDir).then(function (exists) {
  114. if (exists) {
  115. debug('removing existing unzipped binary', installDir);
  116. return fs.removeAsync(installDir);
  117. }
  118. }).then(function () {
  119. return unzip({ zipFilePath: zipFilePath, installDir: installDir, progress: progress });
  120. }).catch(throwFormErrorText(errors.failedUnzip));
  121. };
  122. module.exports = {
  123. start: start
  124. };