Files
nexe/node_modules/tar-async/tar.js
T
2011-11-26 17:00:12 -06:00

157 lines
3.2 KiB
JavaScript

(function () {
"use strict";
var path = require('path'),
Stream = require('stream').Stream,
header = require("./header"),
utils = require("./utils"),
recordSize = 512,
blockSize,
queue = [];
function Tar(opt) {
var tape;
opt = opt || {};
blockSize = (opt.recordsPerBlock ? opt.recordsPerBlock : 20) * recordSize;
Stream.apply(this, arguments);
tape = this;
this.written = 0;
this.consolidate = 'consolidate' in opt ? opt.consolidate : false;
this.normalize = 'normalize' in opt ? opt.normalize : true;
this.on('end', function () {
tape.emit('data', utils.clean(blockSize - (tape.written % blockSize)));
});
if (opt && opt.output) {
this.pipe(opt.output);
}
}
Tar.prototype = Object.create(Stream.prototype, {
constructor: { value: Tar }
});
Tar.prototype.close = function () {
this.emit('end');
};
Tar.prototype.append = function (filepath, input, opts, callback) {
var data,
checksum,
mode,
mtime,
uid,
gid,
size,
tape = this,
extraBytes,
headerBuf;
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
if (this.processing || queue.length) {
queue.push({
filepath: filepath,
input: input,
opts: opts,
cb: callback
});
return;
}
opts = opts || {};
mode = opts.mode || parseInt('777', 8) & 0xfff;
mtime = opts.mtime || parseInt(+new Date() / 1000);
uid = opts.uid || 0;
gid = opts.gid || 0;
size = opts.size || input.length;
data = {
filename: this.consolidate ? path.basename(filepath) : filepath,
mode: utils.pad(mode, 7),
uid: utils.pad(uid, 7),
gid: utils.pad(gid, 7),
size: utils.pad(size, 11),
mtime: utils.pad(mtime, 11),
checksum: ' ',
type: '0', // just a file
ustar: 'ustar ',
owner: '',
group: ''
};
if (this.normalize && !this.consolidate) {
data.filename = path.normalize(data.filename);
}
// calculate the checksum
checksum = 0;
Object.keys(data).forEach(function (key) {
var i, value = data[key], length;
for (i = 0, length = value.length; i < length; i += 1) {
checksum += value.charCodeAt(i);
}
});
data.checksum = utils.pad(checksum, 6) + "\u0000 ";
headerBuf = header.format(data);
this.emit('data', header.format(data));
this.written += headerBuf.length;
if (typeof input === 'string') {
this.emit('data', input);
this.written += input.length;
extraBytes = recordSize - (size % recordSize || recordSize);
this.emit('data', utils.clean(recordSize - (size % recordSize)));
this.written += extraBytes;
if (typeof callback === 'function') {
callback();
}
} else {
this.processing = true;
input.on('data', function (chunk) {
tape.emit('data', chunk);
tape.written += chunk.length;
});
input.on('end', function () {
extraBytes = recordSize - (size % recordSize || recordSize);
tape.emit('data', utils.clean(extraBytes));
tape.written += extraBytes;
if (queue.length) {
setTimeout(function () {
var elem = queue.splice(0, 1)[0];
tape.append(elem.filepath, elem.input, elem.opts, elem.cb);
}, 0);
tape.processing = false;
}
if (typeof callback === 'function') {
callback();
}
});
}
};
module.exports = Tar;
}());