From d49886d0854059ecd47f45943bea34131aa929fc Mon Sep 17 00:00:00 2001 From: Qvazar Date: Tue, 25 Aug 2015 16:17:45 +0200 Subject: [PATCH] compiles, now for testing --- .gitignore | 27 +--- gulpfile.js | 46 ++++++ package.json | 39 +++++ {test => spec/data}/test.tar | Bin spec/empty.js | 0 spec/untar.js | 9 ++ test/1.txt | 1 - test/2.txt | 1 - test/3.txt | 1 - test/directory/1.txt | 1 - test/directory/2.txt | 1 - test/directory/3.txt | 1 - untar-worker.js | 277 ++++++++++++++++++----------------- untar.js | 30 ++-- 14 files changed, 250 insertions(+), 184 deletions(-) create mode 100644 gulpfile.js create mode 100644 package.json rename {test => spec/data}/test.tar (100%) create mode 100644 spec/empty.js create mode 100644 spec/untar.js delete mode 100644 test/1.txt delete mode 100644 test/2.txt delete mode 100644 test/3.txt delete mode 100644 test/directory/1.txt delete mode 100644 test/directory/2.txt delete mode 100644 test/directory/3.txt diff --git a/.gitignore b/.gitignore index 123ae94..e3fbd98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,2 @@ -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +build node_modules diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..59b4779 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,46 @@ +var gulp = require("gulp"), + umd = require("gulp-umd"), + sourcemaps = require("gulp-sourcemaps"), + uglify = require("gulp-uglify"), + insert = require("gulp-insert"), + addSrc = require("gulp-add-src"), + concat = require("gulp-concat"), + jshint = require("gulp-jshint"), + jasmine = require("gulp-jasmine"); + +gulp.task("default", function() { + return gulp.src("untar-worker.js") + .pipe(sourcemaps.init()) + .pipe(jshint()) + .pipe(jshint.reporter("default")) + .pipe(jshint.reporter("fail")) + .pipe(uglify()) + .pipe(insert.transform(function(contents, file) { + var str = ["\nworkerScriptUri = URL.createObjectURL(new Blob([\""]; + str.push(contents.replace(/"/g, '\\"')); + str.push("\"]));"); + + return str.join(""); + })) + .pipe(addSrc("untar.js")) + .pipe(jshint()) + .pipe(jshint.reporter("default")) + .pipe(jshint.reporter("fail")) + .pipe(concat("untar.js")) + .pipe(umd({ + exports: function() { return "untar"; }, + namespace: function() { return "untar"; } + })) + .pipe(sourcemaps.write()) + .pipe(gulp.dest("build/dev")) + .pipe(uglify()) + .pipe(gulp.dest("build/dist")); +}); + +gulp.task("test", ["default"], function() { + return gulp.src("spec/*.js") + .pipe(jasmine({ + includeStackTrace: true, + verbose: true + })); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..629aa7c --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "untar", + "version": "0.0.1", + "description": "untar files in the browser", + "main": "", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/Qvazar/js-untar.git" + }, + "keywords": [ + "js", + "untar", + "browser", + "extract" + ], + "author": "Sebastian Joergensen ", + "license": "MIT", + "bugs": { + "url": "https://github.com/Qvazar/js-untar/issues" + }, + "homepage": "https://github.com/Qvazar/js-untar", + "devDependencies": { + "gulp": "^3.9.0", + "gulp-add-src": "^0.2.0", + "gulp-concat": "^2.6.0", + "gulp-insert": "^0.5.0", + "gulp-jasmine": "^2.0.1", + "gulp-jshint": "^1.11.2", + "gulp-sourcemaps": "^1.5.2", + "gulp-uglify": "^1.3.0", + "gulp-umd": "^0.2.0" + } +} diff --git a/test/test.tar b/spec/data/test.tar similarity index 100% rename from test/test.tar rename to spec/data/test.tar diff --git a/spec/empty.js b/spec/empty.js new file mode 100644 index 0000000..e69de29 diff --git a/spec/untar.js b/spec/untar.js new file mode 100644 index 0000000..1ac8bf8 --- /dev/null +++ b/spec/untar.js @@ -0,0 +1,9 @@ +var untar = require("../build/dev/untar.js"); + +describe("untar", function() { + it("should unpack 3 files and a directory with 3 files", function() { + untar("data/test.tar").then(function(files) { + expect(files.length).toBe(6); + }); + }); +}) \ No newline at end of file diff --git a/test/1.txt b/test/1.txt deleted file mode 100644 index 43dd47e..0000000 --- a/test/1.txt +++ /dev/null @@ -1 +0,0 @@ -one \ No newline at end of file diff --git a/test/2.txt b/test/2.txt deleted file mode 100644 index 64c5e58..0000000 --- a/test/2.txt +++ /dev/null @@ -1 +0,0 @@ -two \ No newline at end of file diff --git a/test/3.txt b/test/3.txt deleted file mode 100644 index 1d19714..0000000 --- a/test/3.txt +++ /dev/null @@ -1 +0,0 @@ -three \ No newline at end of file diff --git a/test/directory/1.txt b/test/directory/1.txt deleted file mode 100644 index 43dd47e..0000000 --- a/test/directory/1.txt +++ /dev/null @@ -1 +0,0 @@ -one \ No newline at end of file diff --git a/test/directory/2.txt b/test/directory/2.txt deleted file mode 100644 index 64c5e58..0000000 --- a/test/directory/2.txt +++ /dev/null @@ -1 +0,0 @@ -two \ No newline at end of file diff --git a/test/directory/3.txt b/test/directory/3.txt deleted file mode 100644 index 1d19714..0000000 --- a/test/directory/3.txt +++ /dev/null @@ -1 +0,0 @@ -three \ No newline at end of file diff --git a/untar-worker.js b/untar-worker.js index b386677..195229c 100644 --- a/untar-worker.js +++ b/untar-worker.js @@ -1,168 +1,169 @@ -"use strict"; +(function() { + "use strict"; -onmessage = function(source) { - if (typeof source === "string") { - loadArrayBuffer(source).then( - untarBuffer, - function(err) { postMessage({ type: "error", data: err }); } - ); - } else { - untarBuffer(source); + onmessage = function(source) { + if (typeof source === "string") { + loadArrayBuffer(source).then( + untarBuffer, + function(err) { postMessage({ type: "error", data: err }); } + ); + } else { + untarBuffer(source); + } + }; + + function loadArrayBuffer(uri) { + return new Promise(function(resolve, reject) { + try { + var request = new XMLHttpRequest(); + + request.addEventListener("progress", function(e) { + postMessage({ type: "loading", data: e }); + }); + + request.addEventListener("load", function(e) { + resolve(request.response); + }); + + request.addEventListener("error", reject); + request.addEventListener("abort", reject); + + request.open("GET", uri); + request.responseType = "arraybuffer"; + request.send(); + } catch (err) { + reject(err); + } + }); } -}; -function loadArrayBuffer(uri) { - return new Promise(function(resolve, reject) { + function untarBuffer(arrayBuffer) { try { - var request = new XMLHttpRequest(); + var tarFileStream = new TarFileStream(arrayBuffer); + while (tarFileStream.hasNext()) { + var file = tarFileStream.next(); - request.addEventListener("progress", function(e) { - postMessage({ type: "loading", data: e }); - }); + postMessage({ type: "extract", data: file }, [file.buffer]); + } - request.addEventListener("load", function(e) { - resolve(request.response); - }); - - request.addEventListener("error", reject); - request.addEventListener("abort", reject); - - request.open("GET", uri); - request.responseType = "arraybuffer"; - request.send(); + postMessage({ type: "complete" }); } catch (err) { - reject(err); + postMessage({ type: "error", data: err }); } - }); -} - -function untarBuffer(arrayBuffer) { - try { - var tarFileStream = new TarFileStream(arrayBuffer); - while (tarFileStream.hasNext()) { - var file = tarFileStream.next(); - - postMessage({ type: "extract", data: file }, [file.buffer]); - } - - postMessage({ type: "complete" }); - ); - } catch (err) { - postMessage({ type: "error", data: err }); } -} -function TarFile() { + function TarFile() { -} + } -TarFile.prototype = { + TarFile.prototype = { -}; + }; -function Stream(arrayBuffer) { - this._bufferView = new DataView(arrayBuffer); - this._position = 0; -} + function Stream(arrayBuffer) { + this._bufferView = new DataView(arrayBuffer); + this._position = 0; + } -Stream.prototype = { - readString: function(charCount) { - var charSize = 1; - var byteCount = charCount * charSize; + Stream.prototype = { + readString: function(charCount) { + var charSize = 1; + var byteCount = charCount * charSize; - var charCodes = []; + var charCodes = []; - for (var i = 0; i < charCount; ++i) { - var charCode = this._bufferView.getUint8(this.position() + (i * charSize)); - if (charCode !== 0) { - charCodes.push(charCode); + for (var i = 0; i < charCount; ++i) { + var charCode = this._bufferView.getUint8(this.position() + (i * charSize)); + if (charCode !== 0) { + charCodes.push(charCode); + } else { + break; + } + } + + this.seek(byteCount); + + return String.fromCharCode.apply(null, charCodes); + }, + + readBuffer: function(byteCount) { + return this._bufferView.buffer.slice(this._position, byteCount); + }, + + seek: function(byteCount) { + this._position += byteCount; + }, + + peekUint32: function() { + return this._bufferView.getUint32(this.position()); + }, + + position: function(newpos) { + if (newpos === undefined) { + return this._position; } else { - break; + this._position = newpos; } } + }; - this.seek(byteCount); - - return String.fromCharCode.apply(null, charCodes); - }, - - readBuffer: function(byteCount) { - return this._bufferView.buffer.slice(this._position, byteCount); + function TarFileStream(arrayBuffer) { + this._stream = new Stream(arrayBuffer); } - seek: function(byteCount) { - this._position += byteCount; - }, + TarFileStream.prototype = { + hasNext: function() { + return this._stream.peekUint32() !== 0; + }, - peekUint32: function() { - return this._bufferView.getUint32(this.position()); - } + next: function() { + var stream = this._stream; + var file = new TarFile(); - position: function(newpos) { - if (newpos === undefined) { - return this._position; - } else { - this._position = newpos; - } - } -}; + var headerBeginPos = stream.position; + var dataBeginPos = headerBeginPos + 512; -function TarFileStream(arrayBuffer) { - this._stream = new Stream(arrayBuffer); -} + // Read header + file.name = stream.readString(100); + file.mode = stream.readString(8); + file.uid = stream.readString(8); + file.gid = stream.readString(8); + file.size = parseInt(stream.readString(12), 8); + file.modificationTime = parseInt(stream.readString(12), 8); + file.checksum = stream.readString(8); + file.type = stream.readString(1); + file.linkname = stream.readString(1); + file.ustarFormat = stream.readString(6); -TarFileStream.prototype = { - hasNext: function() { - return this._stream.peekUint32() != 0; - }, + if (file.ustarFormat === "ustar") { + file.version = stream.readString(2); + file.uname = stream.readString(32); + file.gname = stream.readString(32); + file.devmajor = stream.readString(8); + file.devminor = stream.readString(8); + file.namePrefix = stream.readString(155); - next: function() { - var stream = this._stream; - var file = new TarFile(); - - var headerBeginPos = stream.position; - var dataBeginPos = headerBeginPos + 512; - - // Read header - file.name = stream.readString(100); - file.mode = stream.readString(8); - file.uid = stream.readString(8); - file.gid = stream.readString(8); - file.size = parseInt(stream.readString(12), 8); - file.modificationTime = parseInt(stream.readString(12), 8); - file.checksum = stream.readString(8); - file.type = stream.readString(1); - file.linkname = stream.readString(1); - file.ustarFormat = stream.readString(6); - - if (file.ustarFormat === "ustar") { - file.version = stream.readString(2); - file.uname = stream.readString(32); - file.gname = stream.readString(32); - file.devmajor = stream.readString(8); - file.devminor = stream.readString(8); - file.namePrefix = stream.readString(155); - - if (file.namePrefix.length > 0) { - file.name = file.namePrefix + file.name; + if (file.namePrefix.length > 0) { + file.name = file.namePrefix + file.name; + } } + + stream.position(dataBeginPos); + + // Normal file is either "\0" or 0. + if (file.type === 0 || file.type === "\0") { + file.buffer = stream.readBuffer(file.size); + } else if (file.type == 5) { + // Directory - should we do anything with this? Nope! + } else { + // We only care about real files, not symlinks. + } + + // File data is padded to reach a 512 byte boundary; skip the padded bytes. + var bytesToSkipCount = 512 - file.size % 512; + stream.seek(bytesToSkipCount); + + return file; } - - stream.position(dataBeginPos); - - // Normal file is either "\0" or 0. - if (file.type == 0 || file.type === "\0") { - file.buffer = stream.readBuffer(file.size); - } else if (file.type == 5) { - // Directory - should we do anything with this? Nope! - } else { - // We only care about real files, not symlinks. - } - - // File data is padded to reach a 512 byte boundary; skip the padded bytes. - var bytesToSkipCount = 512 - file.size % 512; - stream.seek(bytesToSkipCount); - - return file; - } -}; \ No newline at end of file + }; +}()); diff --git a/untar.js b/untar.js index ee0b70a..023f598 100644 --- a/untar.js +++ b/untar.js @@ -1,4 +1,4 @@ -// var workerScriptUri is compiled in +var workerScriptUri; // Included at compile time /** source = ArrayBuffer or a url string. If an ArrayBuffer, it will be transfered to the web worker and will thus not be available in the window after. @@ -10,6 +10,7 @@ options = { } */ function untar(source, options) { + "use strict"; if (typeof Promise !== "function") { throw new Error("Promise implementation not available in this environment."); } @@ -20,8 +21,6 @@ function untar(source, options) { options = options || {}; - function makeTarFile - return new Promise(function(resolve, reject) { var noop = function() { }; var onComplete = options.onComplete || noop; @@ -31,6 +30,7 @@ function untar(source, options) { var worker = new Worker(workerScriptUri); var files = []; + var msgData; worker.onmessage = function(message) { switch (message.type) { @@ -38,23 +38,23 @@ function untar(source, options) { onLoading(message.data); break; case "extract": - var file = new TarFile(message.data); - files.push(file); - onExtract(file); + msgData = new TarFile(message.data); + files.push(msgData); + onExtract(msgData); break; case "complete": onComplete(files); resolve(files); break; case "error": - var error = message.data; - onError(error); - reject(error); + msgData = message.data; + onError(msgData); + reject(msgData); break; default: - var error = new Error("Unknown message from worker."); - onError(error); - reject(error); + msgData = new Error("Unknown message from worker."); + onError(msgData); + reject(msgData); break; } }; @@ -65,9 +65,10 @@ function untar(source, options) { } function TarFile(orig) { + "use strict"; this._blobUrl = null; - for (p in orig) { + for (var p in orig) { switch (p) { case "buffer": this.blob = new Blob([orig.buffer]); @@ -81,10 +82,11 @@ function TarFile(orig) { TarFile.prototype = { getObjectUrl: function() { + "use strict"; if (!this._blobUrl) { this._blobUrl = URL.createObjectURL(this.blob); } return this._blobUrl; } -}; \ No newline at end of file +};