1 // pipe in an fstream, and it'll make a tarball.
2 // key-value pair argument is global extended header props.
6 var EntryWriter = require("./entry-writer.js")
7 , Stream = require("stream").Stream
8 , path = require("path")
9 , inherits = require("inherits")
10 , GlobalHeaderWriter = require("./global-header-writer.js")
11 , collect = require("fstream").collect
12 , eof = new Buffer(512)
14 for (var i = 0; i < 512; i ++) eof[i] = 0
16 inherits(Pack, Stream)
18 function Pack (props) {
19 // console.error("-- p ctor")
21 if (!(me instanceof Pack)) return new Pack(props)
23 if (props) me._noProprietary = props.noProprietary
24 else me._noProprietary = false
31 // console.error("-- -- set current to null in ctor")
32 me._currentEntry = null
33 me._processing = false
36 me.on("pipe", function (src) {
37 if (src.root === me._pipeRoot) return
39 src.on("end", function () {
46 Pack.prototype.addGlobal = function (props) {
47 // console.error("-- p addGlobal")
48 if (this._didGlobal) return
49 this._didGlobal = true
52 GlobalHeaderWriter(props)
53 .on("data", function (c) {
59 Pack.prototype.add = function (stream) {
60 if (this._global && !this._didGlobal) this.addGlobal(this._global)
62 if (this._ended) return this.emit("error", new Error("add after end"))
65 this._buffer.push(stream)
67 this._needDrain = this._buffer.length > 0
68 return !this._needDrain
71 Pack.prototype.pause = function () {
73 if (this._currentEntry) this._currentEntry.pause()
77 Pack.prototype.resume = function () {
79 if (this._currentEntry) this._currentEntry.resume()
84 Pack.prototype.end = function () {
86 this._buffer.push(eof)
90 Pack.prototype._process = function () {
92 if (me._paused || me._processing) {
96 var entry = me._buffer.shift()
105 if (entry.ready === false) {
106 // console.error("-- entry is not ready", entry)
107 me._buffer.unshift(entry)
108 entry.on("ready", function () {
109 // console.error("-- -- ready!", entry)
115 me._processing = true
118 // need 2 ending null blocks.
126 // Change the path to be relative to the root dir that was
127 // added to the tarball.
129 // XXX This should be more like how -C works, so you can
130 // explicitly set a root dir, and also explicitly set a pathname
131 // in the tarball to use. That way we can skip a lot of extra
132 // work when resolving symlinks for bundled dependencies in npm.
134 var root = path.dirname((entry.root || entry).path);
135 if (me._global && me._global.fromBase && entry.root && entry.root.path) {
136 // user set 'fromBase: true' indicating tar root should be directory itself
137 root = entry.root.path;
142 Object.keys(entry.props || {}).forEach(function (k) {
143 wprops[k] = entry.props[k]
146 if (me._noProprietary) wprops.noProprietary = true
148 wprops.path = path.relative(root, entry.path || '')
150 // actually not a matter of opinion or taste.
151 if (process.platform === "win32") {
152 wprops.path = wprops.path.replace(/\\/g, "/")
156 wprops.type = 'Directory'
158 switch (wprops.type) {
159 // sockets not supported
169 var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
170 wprops.linkpath = path.relative(root, lp) || "."
175 var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
176 wprops.linkpath = path.relative(path.dirname(entry.path), lp) || "."
181 // console.error("-- new writer", wprops)
182 // if (!wprops.type) {
183 // // console.error("-- no type?", entry.constructor.name, entry)
186 // console.error("-- -- set current to new writer", wprops.path)
187 var writer = me._currentEntry = EntryWriter(wprops)
191 // writer.on("end", function () {
192 // // console.error("-- -- writer end", writer.path)
195 writer.on("data", function (c) {
199 writer.on("header", function () {
200 Buffer.prototype.toJSON = function () {
201 return this.toString().split(/\0/).join(".")
203 // console.error("-- -- writer header %j", writer.props)
204 if (writer.props.size === 0) nextEntry()
206 writer.on("close", nextEntry)
209 function nextEntry () {
213 // console.error("-- -- writer close", writer.path)
214 // console.error("-- -- set current to null", wprops.path)
215 me._currentEntry = null
216 me._processing = false
220 writer.on("error", function (er) {
221 // console.error("-- -- writer error", writer.path)
225 // if it's the root, then there's no need to add its entries,
226 // or data, since they'll be added directly.
227 if (entry === me._pipeRoot) {
228 // console.error("-- is the root, don't auto-add")
235 Pack.prototype.destroy = function () {}
236 Pack.prototype.write = function () {}