blob: 8e09042d016314f99a8a3c38882eacdc42257715 [file] [log] [blame]
module.exports = EntryWriter
var tar = require("../tar.js")
, TarHeader = require("./header.js")
, Entry = require("./entry.js")
, inherits = require("inherits")
, BlockStream = require("block-stream")
, ExtendedHeaderWriter
, Stream = require("stream").Stream
, EOF = {}
inherits(EntryWriter, Stream)
function EntryWriter (props) {
var me = this
if (!(me instanceof EntryWriter)) {
return new EntryWriter(props)
}
Stream.apply(this)
me.writable = true
me.readable = true
me._stream = new BlockStream(512)
me._stream.on("data", function (c) {
me.emit("data", c)
})
me._stream.on("drain", function () {
me.emit("drain")
})
me._stream.on("end", function () {
me.emit("end")
me.emit("close")
})
me.props = props
if (props.type === "Directory") {
props.size = 0
}
props.ustar = "ustar\0"
props.ustarver = "00"
me.path = props.path
me._buffer = []
me._didHeader = false
me._meta = false
me.on("pipe", function () {
me._process()
})
}
EntryWriter.prototype.write = function (c) {
// console.error(".. ew write")
if (this._ended) return this.emit("error", new Error("write after end"))
this._buffer.push(c)
this._process()
this._needDrain = this._buffer.length > 0
return !this._needDrain
}
EntryWriter.prototype.end = function (c) {
// console.error(".. ew end")
if (c) this._buffer.push(c)
this._buffer.push(EOF)
this._ended = true
this._process()
this._needDrain = this._buffer.length > 0
}
EntryWriter.prototype.pause = function () {
// console.error(".. ew pause")
this._paused = true
this.emit("pause")
}
EntryWriter.prototype.resume = function () {
// console.error(".. ew resume")
this._paused = false
this.emit("resume")
this._process()
}
EntryWriter.prototype.add = function (entry) {
// console.error(".. ew add")
if (!this.parent) return this.emit("error", new Error("no parent"))
// make sure that the _header and such is emitted, and clear out
// the _currentEntry link on the parent.
if (!this._ended) this.end()
return this.parent.add(entry)
}
EntryWriter.prototype._header = function () {
// console.error(".. ew header")
if (this._didHeader) return
this._didHeader = true
var headerBlock = TarHeader.encode(this.props)
if (this.props.needExtended && !this._meta) {
var me = this
ExtendedHeaderWriter = ExtendedHeaderWriter ||
require("./extended-header-writer.js")
ExtendedHeaderWriter(this.props)
.on("data", function (c) {
me.emit("data", c)
})
.on("error", function (er) {
me.emit("error", er)
})
.end()
}
// console.error(".. .. ew headerBlock emitting")
this.emit("data", headerBlock)
this.emit("header")
}
EntryWriter.prototype._process = function () {
// console.error(".. .. ew process")
if (!this._didHeader && !this._meta) {
this._header()
}
if (this._paused || this._processing) {
// console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing)
return
}
this._processing = true
var buf = this._buffer
for (var i = 0; i < buf.length; i ++) {
// console.error(".. .. .. i=%d", i)
var c = buf[i]
if (c === EOF) this._stream.end()
else this._stream.write(c)
if (this._paused) {
// console.error(".. .. .. paused mid-emission")
this._processing = false
if (i < buf.length) {
this._needDrain = true
this._buffer = buf.slice(i + 1)
}
return
}
}
// console.error(".. .. .. emitted")
this._buffer.length = 0
this._processing = false
// console.error(".. .. .. emitting drain")
this.emit("drain")
}
EntryWriter.prototype.destroy = function () {}