diff options
author | isaacs <i@izs.me> | 2013-12-16 16:23:13 -0800 |
---|---|---|
committer | isaacs <i@izs.me> | 2013-12-16 23:09:16 -0800 |
commit | 97738994e0bc2f3255659ca8f27e43a90aa0a24e (patch) | |
tree | 51bc3a3a928ddcba4944b8294656158d120d3d75 /deps/npm/node_modules/npm-registry-client/lib/publish.js | |
parent | 39e2426b209799d5deaa29d2401dd98f060babda (diff) | |
download | android-node-v8-97738994e0bc2f3255659ca8f27e43a90aa0a24e.tar.gz android-node-v8-97738994e0bc2f3255659ca8f27e43a90aa0a24e.tar.bz2 android-node-v8-97738994e0bc2f3255659ca8f27e43a90aa0a24e.zip |
npm: Upgrade to 1.3.19
Diffstat (limited to 'deps/npm/node_modules/npm-registry-client/lib/publish.js')
-rw-r--r-- | deps/npm/node_modules/npm-registry-client/lib/publish.js | 153 |
1 files changed, 94 insertions, 59 deletions
diff --git a/deps/npm/node_modules/npm-registry-client/lib/publish.js b/deps/npm/node_modules/npm-registry-client/lib/publish.js index d6a7496f1f..9404a129db 100644 --- a/deps/npm/node_modules/npm-registry-client/lib/publish.js +++ b/deps/npm/node_modules/npm-registry-client/lib/publish.js @@ -3,9 +3,11 @@ module.exports = publish var path = require("path") , url = require("url") + , semver = require("semver") + , crypto = require("crypto") + , fs = require("fs") function publish (data, tarball, cb) { - var email = this.conf.get('email') var auth = this.conf.get('_auth') var username = this.conf.get('username') @@ -16,14 +18,30 @@ function publish (data, tarball, cb) { return cb(er) } - // 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. - // then: - // PUT the data to {config.registry}/{data.name}/{data.version} - var registry = this.conf.get('registry') + if (data.name !== encodeURIComponent(data.name).toLowerCase()) + return cb(new Error('invalid name: must be lowercase and url-safe')) + + var ver = semver.clean(data.version) + if (!ver) + return cb(new Error('invalid semver: ' + data.version)) + data.version = ver + + var self = this + fs.stat(tarball, function(er, s) { + if (er) return cb(er) + fs.readFile(tarball, 'base64', function(er, tardata) { + if (er) return cb(er) + putFirst.call(self, data, tardata, s, username, email, cb) + }) + }) +} - var fullData = +function putFirst (data, tardata, stat, username, email, cb) { + // optimistically try to PUT all in one single atomic thing. + // If 409, then GET and merge, try again. + // If other error, then fail. + + var root = { _id : data.name , name : data.name , description : data.description @@ -37,76 +55,93 @@ function publish (data, tarball, cb) { ] } + root.versions[ data.version ] = data + var tag = data.tag || this.conf.get('tag') || "latest" + root["dist-tags"][tag] = data.version + + var registry = this.conf.get('registry') var tbName = data.name + "-" + data.version + ".tgz" , tbURI = data.name + "/-/" + tbName data._id = data.name+"@"+data.version data.dist = data.dist || {} + data.dist.shasum = crypto.createHash("sha1").update(tardata).digest("hex") data.dist.tarball = url.resolve(registry, tbURI) .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. - this.request("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" )) { - this.log.error("publish", "Failed PUT response " - +(response && response.statusCode)) + root._attachments = {} + root._attachments[ tbName ] = { + content_type: 'application/octet-stream', + data: tardata, + length: stat.size + }; + + this.request("PUT", data.name, root, function (er, parsed, json, res) { + var r409 = "must supply latest _rev to update existing package" + var r409b = "Document update conflict." + var conflict = res && res.statusCode === 409 + if (parsed && (parsed.reason === r409 || parsed.reason === r409b)) + conflict = true + + // a 409 is typical here. GET the data and merge in. + if (er && !conflict) { + this.log.error("publish", "Failed PUT " + +(res && res.statusCode)) return cb(er) } - var dataURI = encodeURIComponent(data.name) - + "/" + encodeURIComponent(data.version) - var tag = data.tag || this.conf.get('tag') || "latest" - dataURI += "/-tag/" + tag + if (!er && !conflict) + return cb(er, parsed, json, res) // let's see what versions are already published. - // could be that we just need to update the bin dist values. - this.request("GET", data.name, function (er, fullData) { - if (er) return cb(er) - - function handle(er) { - if (er.message.indexOf("conflict Document update conflict.") === 0) { - return cb(conflictError.call(this, data._id)); - } - this.log.error("publish", "Error uploading package"); + this.request("GET", data.name, function (er, current) { + if (er) return cb(er) - } - - var exists = fullData.versions && fullData.versions[data.version] - if (exists) return cb(conflictError.call(this, data._id)) - - var rev = fullData._rev; - attach.call(this, data.name, tarball, tbName, rev, function (er) { - if (er) return handle.call(this, er) - this.log.verbose("publish", "attached", [data.name, tarball, tbName]) - this.request("PUT", dataURI, data, function (er) { - if (er) return handle.call(this, er) - return cb(er) - }.bind(this)) - }.bind(this)) + putNext.call(this, data.version, root, current, cb) }.bind(this)) - }.bind(this)) // pining for fat arrows. + }.bind(this)) +} + +function putNext(newVersion, root, current, cb) { + // already have the tardata on the root object + // just merge in existing stuff + // if the version already exists, and not a --force, then raise error + var force = this.conf.get('force') + var curVers = Object.keys(current.versions || {}).map(function (v) { + return semver.clean(v, true) + }) + + if (!force && curVers.indexOf(newVersion) !== -1) { + return cb(conflictError(root.name)) + } + + current.versions[newVersion] = root.versions[newVersion] + for (var i in root) { + switch (i) { + // objects that copy over the new stuffs + case 'dist-tags': + case 'versions': + case '_attachments': + for (var j in root[i]) + current[i][j] = root[i][j] + break + + // ignore these + case 'maintainers': + break; + + // copy + default: + current[i] = root[i] + } + } + + this.request("PUT", root.name, current, cb) } function conflictError (pkgid) { - var e = new Error("publish fail") + var e = new Error("cannot modify existing version") e.code = "EPUBLISHCONFLICT" e.pkgid = pkgid return e } - -function attach (doc, file, filename, rev, cb) { - doc = encodeURIComponent(doc) - var revu = "-rev/"+rev - , attURI = doc + "/-/" + encodeURIComponent(filename) + "/" + revu - this.log.verbose("uploading", [attURI, file]) - this.upload(attURI, file, cb) -} |