diff options
author | isaacs <i@izs.me> | 2011-03-29 00:54:17 +0400 |
---|---|---|
committer | isaacs <i@izs.me> | 2011-03-30 09:04:59 +0400 |
commit | 93a2b221ae3d55892a5a87844da5390b92e9fb1c (patch) | |
tree | b50397c298a42cd3230abd416593f91637de9f84 /lib | |
parent | 4250a30198f469def627ad041e478789b56c61a4 (diff) |
Publish binary distribution as well as source
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cache.js | 3 | ||||
-rw-r--r-- | lib/publish.js | 81 | ||||
-rw-r--r-- | lib/utils/npm-registry-client/publish.js | 76 |
3 files changed, 123 insertions, 37 deletions
diff --git a/lib/cache.js b/lib/cache.js index 5eda1917a..7902efd76 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -286,7 +286,8 @@ function addNameVersion (name, ver, cb) { if (!dist) return cb(new Error("No dist in "+data._id+" package")) - var b = dist.bin && dist.bin[binTag()] + var bt = binTag() + , b = dist.bin && bt && dist.bin[bt] if (b && b.tarball && b.shasum) dist = b if (!dist.tarball) return cb(new Error( diff --git a/lib/publish.js b/lib/publish.js index e590bbb0c..3d78d8c25 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -4,6 +4,12 @@ module.exports = publish var npm = require("../npm") , registry = require("./utils/npm-registry-client") , log = require("./utils/log") + , binTag = require("./utils/bin-tag") + , tar = require("./utils/tar") + , sha = require("./utils/sha") + , path = require("path") + , readJson = require("./utils/read-json") + , fs = require("fs") publish.usage = "npm publish <tarball>" + "\nnpm publish <folder>" @@ -28,16 +34,73 @@ function publish (args, isRetry, cb) { if (data.private) return cb(new Error ("This package has been marked as private\n" +"Remove the 'private' field from the package.json to publish it.")) - registry.publish(data, function (er) { - if (er && er.errno === npm.EPUBLISHCONFLICT - && npm.config.get("force") && !isRetry) { - log.warn("Forced publish over "+data._id, "publish") - return npm.commands.unpublish([data._id], function (er) { - // ignore errors. Use the force. Reach out with your feelings. - publish(args, true, cb) - }) + + // pre-build + preBuild(data, binTag(), function (er, tb) { + if (er) return cb(er) + return regPublish(data, tb, cb) + }) + }) +} + +function preBuild (data, bt, cb) { + if (!bt) return cb(data, null, cb) + // unpack to cache/n/v/build + // build there + // pack to cache/package-<bt>.tgz + var cf = path.resolve(npm.cache, data.name, data.version) + var pb = path.resolve(cf, "build") + , tb = path.resolve(cf, "package-"+bt+".tgz") + + npm.commands.cache.unpack(data.name, data.version, pb, function (er) { + if (er) return cb(er) + npm.commands.build([pb], function (er) { + log.info(data._id, "prebuild done") + // build failure just means that we can't prebuild + if (er) { + log.warn(er.message, "prebuild failed "+bt) + return cb() } - cb(er) + // now strip the preinstall/install scripts + // they've already been run. + var pbj = path.resolve(pb, "package.json") + readJson(pbj, function (er, pbo) { + if (er) return cb(er) + if (pbo.scripts) { + delete pbo.scripts.preinstall + delete pbo.scripts.install + delete pbo.scripts.postinstall + } + fs.writeFile(pbj, JSON.stringify(pbj), "utf8", function (er) { + if (er) return cb(er) + tar.pack(tb, pb, pbo, false, function (er) { + if (er) return cb(er) + // try to validate the shasum, too + sha.get(tb, function (er, shasum) { + if (er) return cb(er) + // binary distribution requires shasum checking. + if (!shasum) return cb() + data.dist[bt] = data.dist[bt] || {} + data.dist[bt].shasum = shasum + return cb(null, tb) + }) + }) + }) + }) }) }) } + +function regPublish (data, prebuilt, cb) { + registry.publish(data, prebuilt, function (er) { + if (er && er.errno === npm.EPUBLISHCONFLICT + && npm.config.get("force") && !isRetry) { + log.warn("Forced publish over "+data._id, "publish") + return npm.commands.unpublish([data._id], function (er) { + // ignore errors. Use the force. Reach out with your feelings. + publish(args, true, cb) + }) + } + cb(er) + }) +} diff --git a/lib/utils/npm-registry-client/publish.js b/lib/utils/npm-registry-client/publish.js index 4f2249e9f..013629c15 100644 --- a/lib/utils/npm-registry-client/publish.js +++ b/lib/utils/npm-registry-client/publish.js @@ -1,5 +1,4 @@ - module.exports = publish var request = require("./request") @@ -12,8 +11,9 @@ var request = require("./request") , path = require("path") , npm = require("../../../npm") , url = require("url") + , binTag = require("../bin-tag") -function publish (data, cb) { +function publish (data, prebuilt, cb) { // add the dist-url to the data, pointing at the tarball. // if the {name} isn't there, then create it. // if the {version} is already there, then fail. @@ -34,31 +34,43 @@ function publish (data, cb) { } ] } + + var tbName = data.name + "-" + data.version + ".tgz" + , bt = binTag() + , pbName = data.name + "-" + data.version + "-" + bt + ".tgz" + , tbURI = data.name + "/-/" + tbName + , pbURI = data.name + "/-/" + pbName + data._id = data.name+"@"+data.version - var attURI = encodeURIComponent(data.name) - + "/-/" - + encodeURIComponent(data.name) - + "-" - + encodeURIComponent(data.version) - + ".tgz" data.dist = data.dist || {} - data.dist.tarball = url.resolve(registry, attURI) - .replace(/^https:\/\//, 'http://') + data.dist.tarball = url.resolve(registry, tbURI) + .replace(/^https:\/\//, "http://") + + if (prebuilt && bt) { + data.dist[bt] = data.dist[bt] || {} + data.dist[bt].tarball = url.resolve(registry, pbURI) + .replace(/^https:\/\//, "http://") + } + + + // first try to just PUT the whole fullData, and this will fail if it's // already there, because it'll be lacking a _rev, so couch'll bounce it. - PUT(encodeURIComponent(data.name), fullData, function (er, parsed, json, response) { + PUT(encodeURIComponent(data.name), fullData, + function (er, parsed, json, response) { // get the rev and then upload the attachment // a 409 is expected here, if this is a new version of an existing package. if (er && !(response && response.statusCode === 409) && !( parsed - && parsed.reason === "must supply latest _rev to update existing package" - ) - ) { - return log.er(cb, "Failed PUT response "+(response && response.statusCode))(er) + && parsed.reason === + "must supply latest _rev to update existing package" )) { + return log.er(cb, "Failed PUT response " + +(response && response.statusCode))(er) } - var dataURI = encodeURIComponent(data.name)+"/"+encodeURIComponent(data.version) + var dataURI = encodeURIComponent(data.name) + + "/" + encodeURIComponent(data.version) var tag = data.tag || npm.config.get("tag") if (npm.config.get("pre")) dataURI += "/-pre/true" @@ -75,22 +87,32 @@ function publish (data, cb) { } return log.er(cb, "Error sending version data")(er) } - GET(encodeURIComponent(data.name), function (er, d) { - if (er) return cb(er) - var rev = d && ("-rev/"+d._rev) - , tarball = path.join(npm.cache, data.name, data.version, "package.tgz") - log.verbose(tarball, "tarball") - attURI += "/" + rev - upload(attURI, tarball, function (er) { - log("uploaded", "publish") - if (er) log.error("Couldn't send tarball", "publish fail") - rollbackFailure(data, cb)(er) - }) + + var c = path.resolve(npm.cache, data.name, data.version) + , tb = path.resolve(c, "package.tgz") + + cb = rollbackFailure(data, cb) + + attach(data.name, tb, tbName, function (er) { + if (er || !prebuilt) return cb(er) + attach(data.name, prebuilt, pbName, cb) }) }) }) } +function attach (doc, file, filename, cb) { + doc = encodeURIComponent(doc) + GET(doc, function (er, d) { + if (er) return cb(er) + if (!d) return cb(new Error( + "Attempting to upload to invalid doc "+doc)) + var rev = "-rev/"+d._rev + , attURI = doc + "/-/" + encodeURIComponent(filename) + "/" + rev + upload(attURI, file, cb) + }) +} + function rollbackFailure (data, cb) { return function (er) { if (!er) return cb() npm.ROLLBACK = true |