First working end-to-end unzip test passing
This commit is contained in:
parent
5a13dbfa4d
commit
3411ba2dd3
|
@ -44,15 +44,8 @@ define(function(require) {
|
|||
var Deflater = require("zip.js/deflate");
|
||||
|
||||
var TEXT_PLAIN = "text/plain";
|
||||
|
||||
var MESSAGE_EVENT = "message";
|
||||
|
||||
var appendABViewSupported;
|
||||
try {
|
||||
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
function Crc32() {
|
||||
var crc = -1, that = this;
|
||||
that.append = function(data) {
|
||||
|
@ -78,17 +71,6 @@ define(function(require) {
|
|||
return table;
|
||||
})();
|
||||
|
||||
function blobSlice(blob, index, length) {
|
||||
if (blob.slice)
|
||||
return blob.slice(index, index + length);
|
||||
else if (blob.webkitSlice)
|
||||
return blob.webkitSlice(index, index + length);
|
||||
else if (blob.mozSlice)
|
||||
return blob.mozSlice(index, index + length);
|
||||
else if (blob.msSlice)
|
||||
return blob.msSlice(index, index + length);
|
||||
}
|
||||
|
||||
function getDataHelper(byteLength, bytes) {
|
||||
var dataBuffer, dataArray;
|
||||
dataBuffer = new ArrayBuffer(byteLength);
|
||||
|
@ -103,171 +85,73 @@ define(function(require) {
|
|||
}
|
||||
|
||||
// Readers
|
||||
function Reader() {
|
||||
}
|
||||
|
||||
function TextReader(text) {
|
||||
var that = this, blobReader;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var blob = new Blob([ text ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
blobReader = new BlobReader(blob);
|
||||
blobReader.init(function() {
|
||||
that.size = blobReader.size;
|
||||
callback();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
blobReader.readUint8Array(index, length, callback, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
TextReader.prototype = new Reader();
|
||||
TextReader.prototype.constructor = TextReader;
|
||||
|
||||
function Uint8Reader(u8) {
|
||||
// Filer fs-based File Reader, given a path and a fs instance
|
||||
function FileReader(path, fs) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
that.size = u8.length;
|
||||
callback();
|
||||
fs.stat(path, function(err, stats) {
|
||||
if(err) return onerror(err);
|
||||
|
||||
that.size = stats.size;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function getData(callback, onerror) {
|
||||
if(that.data) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
fs.readFile(path, function(err, data) {
|
||||
if(err) return onerror(err);
|
||||
that.data = data;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
callback(new Uint8Array(u8.subarray(index, index + length)));
|
||||
getData(function() {
|
||||
callback(that.data.subarray(index, index + length));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
Uint8Reader.prototype = new Reader();
|
||||
Uint8Reader.prototype.constructor = Uint8Reader;
|
||||
FileReader.prototype.checkCrc32 = false;
|
||||
|
||||
function BlobReader(blob) {
|
||||
var that = this;
|
||||
|
||||
function init(callback) {
|
||||
this.size = blob.size;
|
||||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
callback(new Uint8Array(e.target.result));
|
||||
};
|
||||
reader.onerror = onerror;
|
||||
reader.readAsArrayBuffer(blobSlice(blob, index, length));
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
BlobReader.prototype = new Reader();
|
||||
BlobReader.prototype.constructor = BlobReader;
|
||||
|
||||
// Writers
|
||||
|
||||
function Writer() {
|
||||
}
|
||||
Writer.prototype.getData = function(callback) {
|
||||
callback(this.data);
|
||||
};
|
||||
|
||||
function TextWriter(encoding) {
|
||||
var that = this, blob;
|
||||
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback, onerror) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
callback(e.target.result);
|
||||
};
|
||||
reader.onerror = onerror;
|
||||
reader.readAsText(blob, encoding);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
TextWriter.prototype = new Writer();
|
||||
TextWriter.prototype.constructor = TextWriter;
|
||||
|
||||
function Uint8Writer() {
|
||||
var that = this, u8;
|
||||
// Filer fs-based File Writer
|
||||
function FileWriter(path, fs, size) {
|
||||
var that = this;
|
||||
|
||||
function init(callback) {
|
||||
u8 = new Uint8Array();
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
var both = new Uint8Array(u8.length + array.length);
|
||||
both.set(u8);
|
||||
both.set(array, u8.length);
|
||||
u8 = both;
|
||||
// TODO: Overwrite the file. Should we also have a way to fail if exists?
|
||||
fs.unlink(path, function() {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(u8);
|
||||
callback(that.data);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
fs.appendFile(path, array, function(err) {
|
||||
if(err) return onerror(err);
|
||||
that.data = array;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
that.size = size;
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
Uint8Writer.prototype = new Writer();
|
||||
Uint8Writer.prototype.constructor = Uint8Writer;
|
||||
|
||||
function BlobWriter(contentType) {
|
||||
var blob, that = this;
|
||||
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(blob);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
BlobWriter.prototype = new Writer();
|
||||
BlobWriter.prototype.constructor = BlobWriter;
|
||||
|
||||
// inflate/deflate core functions
|
||||
function launchProcess(process, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {
|
||||
|
@ -309,7 +193,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
function inflate(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
|
||||
var worker, crc32 = new Crc32();
|
||||
var crc32 = new Crc32();
|
||||
|
||||
function oninflateappend(sending, array) {
|
||||
if (computeCrc32 && !sending)
|
||||
|
@ -321,11 +205,11 @@ define(function(require) {
|
|||
}
|
||||
|
||||
launchProcess(new Inflater(), reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);
|
||||
return worker;
|
||||
return;
|
||||
}
|
||||
|
||||
function deflate(reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {
|
||||
var worker, crc32 = new Crc32();
|
||||
var crc32 = new Crc32();
|
||||
|
||||
function ondeflateappend(sending, array) {
|
||||
if (sending)
|
||||
|
@ -337,7 +221,7 @@ define(function(require) {
|
|||
}
|
||||
|
||||
launchProcess(new Deflater(), reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);
|
||||
return worker;
|
||||
return;
|
||||
}
|
||||
|
||||
function copy(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
|
||||
|
@ -472,7 +356,10 @@ define(function(require) {
|
|||
readCommonHeader(that, data, 4, false, onerror);
|
||||
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
|
||||
writer.init(function() {
|
||||
copy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
|
||||
if (that.compressionMethod === 0)
|
||||
copy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
|
||||
else
|
||||
inflate(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
|
||||
}, onwriteerror);
|
||||
}, onreaderror);
|
||||
};
|
||||
|
@ -676,14 +563,8 @@ define(function(require) {
|
|||
}
|
||||
|
||||
return {
|
||||
Reader : Reader,
|
||||
Writer : Writer,
|
||||
BlobReader : BlobReader,
|
||||
Uint8Reader : Uint8Reader,
|
||||
TextReader : TextReader,
|
||||
BlobWriter : BlobWriter,
|
||||
Uint8Writer : Uint8Writer,
|
||||
TextWriter : TextWriter,
|
||||
FileReader : FileReader,
|
||||
FileWriter : FileWriter,
|
||||
createReader : function(reader, callback, onerror) {
|
||||
reader.init(function() {
|
||||
callback(createZipReader(reader, onerror));
|
||||
|
|
|
@ -476,6 +476,44 @@ define(function(require) {
|
|||
request.send();
|
||||
};
|
||||
|
||||
Shell.prototype.unzip = function(path, options, callback) {
|
||||
var fs = this.fs;
|
||||
if(typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
callback = callback || function(){};
|
||||
|
||||
if(!path) {
|
||||
callback(new Errors.EINVAL('missing path argument'));
|
||||
return;
|
||||
}
|
||||
|
||||
path = Path.resolve(this.cwd, path);
|
||||
var destination = Path.resolve(options.destination || this.cwd);
|
||||
|
||||
var Zip = require('zip.js/zip');
|
||||
Zip.createReader(new Zip.FileReader(path, fs), function(reader) {
|
||||
reader.getEntries(function(entries) {
|
||||
|
||||
function inflate(entry, callback) {
|
||||
var path = Path.join(destination, entry.filename);
|
||||
if(entry.directory) {
|
||||
this.mkdirp(path, callback);
|
||||
} else {
|
||||
entry.getData(new Zip.FileWriter(path, fs, entry.uncompressedSize), function() { callback(); });
|
||||
}
|
||||
}
|
||||
|
||||
async.eachSeries(entries, inflate, function(error) {
|
||||
if(error) return callback(error);
|
||||
reader.close(callback);
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
return Shell;
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
define(["Filer", "util"], function(Filer, util) {
|
||||
|
||||
describe('FileSystemShell.unzip', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var shell = util.shell();
|
||||
expect(shell.unzip).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should fail when path argument is absent', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = fs.Shell();
|
||||
|
||||
shell.unzip(null, function(err) {
|
||||
expect(err).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should download and unzip the contents of a zip file', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = fs.Shell();
|
||||
var url = "test-file.txt.zip";
|
||||
var contents = "This is a test file used in some of the tests.\n";
|
||||
|
||||
fs.writeFile('/original', contents, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
shell.wget(url, {filename: url}, function(err, path) {
|
||||
if(err) throw err;
|
||||
|
||||
shell.unzip(path, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.readFile('/original', function(err, originalData) {
|
||||
if(err) throw err;
|
||||
|
||||
|
||||
fs.readFile('/test-file.txt', function(err, data) {
|
||||
if(err) throw err;
|
||||
expect(util.typedArrayEqual(data, originalData)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Binary file not shown.
|
@ -58,6 +58,7 @@ define([
|
|||
"spec/shell/env.spec",
|
||||
"spec/shell/mkdirp.spec",
|
||||
"spec/shell/wget.spec",
|
||||
"spec/shell/unzip.spec",
|
||||
|
||||
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
|
||||
"spec/node-js/simple/test-fs-mkdir",
|
||||
|
|
Loading…
Reference in New Issue