patches pushed to nodejs-npm-registry-client (el6). "Merge branch 'master' into el6"
notifications at fedoraproject.org
notifications at fedoraproject.org
Sat May 16 21:24:17 UTC 2015
From 857c90e16f7f9b9089a5266625a130d67cd99c74 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis at ausil.us>
Date: Sat, 7 Jun 2014 09:11:03 -0500
Subject: - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
diff --git a/nodejs-npm-registry-client.spec b/nodejs-npm-registry-client.spec
index 6d3ba92..4c6230b 100644
--- a/nodejs-npm-registry-client.spec
+++ b/nodejs-npm-registry-client.spec
@@ -2,7 +2,7 @@
Name: nodejs-npm-registry-client
Version: 0.2.28
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: Client for the npm registry
Group: System Environment/Libraries
@@ -45,6 +45,9 @@ rm -rf %buildroot
%doc README.md LICENSE
%changelog
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.2.28-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
* Fri Sep 06 2013 Jamie Nguyen <jamielinux at fedoraproject.org> - 0.2.28-1
- update to upstream release 0.2.28
- add ExclusiveArch logic
--
cgit v0.10.2
From 7f827500bbdd347ce9dbab6ea30f42b4d07e7c62 Mon Sep 17 00:00:00 2001
From: "T.C. Hollingsworth" <tchollingsworth at gmail.com>
Date: Sat, 16 May 2015 14:23:01 -0700
Subject: backport fixes to publish and adduser functions (RHBZ#1220472)
diff --git a/nodejs-npm-registry-client-publish-fixes.patch b/nodejs-npm-registry-client-publish-fixes.patch
new file mode 100644
index 0000000..9c21f92
--- /dev/null
+++ b/nodejs-npm-registry-client-publish-fixes.patch
@@ -0,0 +1,989 @@
+diff --git a/README.md b/README.md
+index 534c407..4b3d4c3 100644
+--- a/README.md
++++ b/README.md
+@@ -34,6 +34,9 @@ also be accepted.
+ * `tag` {String} The default tag to use when publishing new packages.
+ Default = `"latest"`
+ * `ca` {String} Cerficate signing authority certificates to trust.
++* `cert` {String} Client certificate (PEM encoded). Enable access
++ to servers that require client certificates
++* `key` {String} Private key (PEM encoded) for client certificate 'cert'
+ * `strict-ssl` {Boolean} Whether or not to be strict with SSL
+ certificates. Default = `true`
+ * `user-agent` {String} User agent header to send. Default =
+@@ -82,6 +85,22 @@ around this. one.
+
+ Add a user account to the registry, or verify the credentials.
+
++# client.deprecate(name, version, message, cb)
++
++* `name` {String} The package name
++* `version` {String} Semver version range
++* `message` {String} The message to use as a deprecation warning
++* `cb` {Function}
++
++Deprecate a version of a package in the registry.
++
++# client.bugs(name, cb)
++
++* `name` {String} the name of the package
++* `cb` {Function}
++
++Get the url for bugs of a package
++
+ # client.get(url, [timeout], [nofollow], [staleOk], cb)
+
+ * `url` {String} The url path to fetch
+@@ -94,11 +113,10 @@ Add a user account to the registry, or verify the credentials.
+ Fetches data from the registry via a GET request, saving it in
+ the cache folder with the ETag.
+
+-# client.publish(data, tarball, [readme], cb)
++# client.publish(data, tarball, cb)
+
+ * `data` {Object} Package data
+ * `tarball` {String | Stream} Filename or stream of the package tarball
+-* `readme` {String} Contents of the README markdown file
+ * `cb` {Function}
+
+ Publish a package to the registry.
+diff --git a/index.js b/index.js
+index c2d50b6..24c33ae 100644
+--- a/index.js
++++ b/index.js
+@@ -1,4 +1,3 @@
+-
+ // utilities for working with the js-registry site.
+
+ module.exports = RegClient
+@@ -6,7 +5,6 @@ module.exports = RegClient
+ var fs = require('fs')
+ , url = require('url')
+ , path = require('path')
+-, CouchLogin = require('couch-login')
+ , npmlog
+
+ try {
+@@ -48,20 +46,6 @@ function RegClient (conf) {
+ }
+
+ if (!conf.get('cache')) throw new Error("Cache dir is required")
+-
+- var auth = this.conf.get('_auth')
+- var alwaysAuth = this.conf.get('always-auth')
+- if (auth && !alwaysAuth && registry) {
+- // if we're always authing, then we just send the
+- // user/pass on every thing. otherwise, create a
+- // session, and use that.
+- var token = this.conf.get('_token')
+- this.couchLogin = new CouchLogin(registry, token)
+- this.couchLogin.proxy = this.conf.get('proxy')
+- this.couchLogin.strictSSL = this.conf.get('strict-ssl')
+- this.couchLogin.ca = this.conf.get('ca')
+- }
+-
+ this.log = conf.log || conf.get('log') || npmlog
+ }
+
+diff --git a/lib/adduser.js b/lib/adduser.js
+index 7106e44..5a76b02 100644
+--- a/lib/adduser.js
++++ b/lib/adduser.js
+@@ -1,11 +1,5 @@
+ module.exports = adduser
+
+-var crypto = require('crypto')
+-
+-function sha (s) {
+- return crypto.createHash("sha1").update(s).digest("hex")
+-}
+-
+ function adduser (username, password, email, cb) {
+
+ password = ("" + (password || "")).trim()
+@@ -17,15 +11,9 @@ function adduser (username, password, email, cb) {
+ return cb(new Error("Please use a real email address."))
+ }
+
+- if (password.indexOf(":") !== -1) return cb(new Error(
+- "Sorry, ':' chars are not allowed in passwords.\n"+
+- "See <https://issues.apache.org/jira/browse/COUCHDB-969> for why."))
+-
+- var salt = crypto.randomBytes(30).toString('hex')
+- , userobj =
++ var userobj =
+ { name : username
+- , salt : salt
+- , password_sha : sha(password + salt)
++ , password : password
+ , email : email
+ , _id : 'org.couchdb.user:'+username
+ , type : "user"
+@@ -51,7 +39,7 @@ function adduser (username, password, email, cb) {
+ cb = done.call(this, cb, pre)
+
+ var logObj = Object.keys(userobj).map(function (k) {
+- if (k === 'salt' || k === 'password_sha') return [k, 'XXXXX']
++ if (k === 'password') return [k, 'XXXXX']
+ return [k, userobj[k]]
+ }).reduce(function (s, kv) {
+ s[kv[0]] = kv[1]
+@@ -81,13 +69,14 @@ function adduser (username, password, email, cb) {
+
+ this.log.verbose("adduser", "update existing user")
+ return this.request('GET'
+- , '/-/user/org.couchdb.user:'+encodeURIComponent(username)
++ , '/-/user/org.couchdb.user:'+encodeURIComponent(username) +
++ '?write=true'
+ , function (er, data, json, response) {
+ if (er || data.error) {
+ return cb(er, data, json, response)
+ }
+ Object.keys(data).forEach(function (k) {
+- if (!userobj[k]) {
++ if (!userobj[k] || k === 'roles') {
+ userobj[k] = data[k]
+ }
+ })
+@@ -129,7 +118,7 @@ function done (cb, pre) {
+ this.log.warn("adduser", "Incorrect username or password\n"
+ +"You can reset your account by visiting:\n"
+ +"\n"
+- +" http://admin.npmjs.org/reset\n")
++ +" https://npmjs.org/forgot\n")
+ }
+
+ return cb(error)
+diff --git a/lib/bugs.js b/lib/bugs.js
+new file mode 100644
+index 0000000..a047013
+--- /dev/null
++++ b/lib/bugs.js
+@@ -0,0 +1,9 @@
++
++module.exports = bugs
++
++function bugs (name, cb) {
++ this.get(name + "/latest", 3600, function (er, d) {
++ if (er) return cb(er)
++ cb(null, d.bugs)
++ })
++}
+diff --git a/lib/deprecate.js b/lib/deprecate.js
+new file mode 100644
+index 0000000..9cbc6d8
+--- /dev/null
++++ b/lib/deprecate.js
+@@ -0,0 +1,26 @@
++
++module.exports = deprecate
++
++var semver = require("semver")
++
++function deprecate (name, ver, message, cb) {
++ if (!this.conf.get('username')) {
++ return cb(new Error("Must be logged in to deprecate a package"))
++ }
++
++ if (semver.validRange(ver) === null) {
++ return cb(new Error("invalid version range: "+ver))
++ }
++
++ this.get(name + '?write=true', function (er, data) {
++ if (er) return cb(er)
++ // filter all the versions that match
++ Object.keys(data.versions).filter(function (v) {
++ return semver.satisfies(v, ver)
++ }).forEach(function (v) {
++ data.versions[v].deprecated = message
++ })
++ // now update the doc on the registry
++ this.request('PUT', data._id, data, cb)
++ }.bind(this))
++}
+diff --git a/lib/get.js b/lib/get.js
+index eeb716e..7722e91 100644
+--- a/lib/get.js
++++ b/lib/get.js
+@@ -10,7 +10,6 @@ function get (uri, timeout, nofollow, staleOk, cb) {
+ if (typeof cb !== "function") cb = staleOk, staleOk = false
+ if (typeof cb !== "function") cb = nofollow, nofollow = false
+ if (typeof cb !== "function") cb = timeout, timeout = -1
+- if (typeof cb !== "function") cb = version, version = null
+
+ timeout = Math.min(timeout, this.conf.get('cache-max') || 0)
+ timeout = Math.max(timeout, this.conf.get('cache-min') || -Infinity)
+@@ -31,9 +30,15 @@ function get (uri, timeout, nofollow, staleOk, cb) {
+
+ var cacheUri = uri
+ // on windows ":" is not an allowed character in a foldername
+- cacheUri = cacheUri.replace(/:/g, '_')
++ cacheUri = cacheUri.replace(/:/g, '_').replace(/\?write=true$/, '')
+ var cache = path.join(this.conf.get('cache'), cacheUri, ".cache.json")
+
++ // If the GET is part of a write operation (PUT or DELETE), then
++ // skip past the cache entirely, but still save the results.
++ if (uri.match(/\?write=true$/))
++ return get_.call(this, uri, timeout, cache, null, null, nofollow, staleOk, cb)
++
++
+ fs.stat(cache, function (er, stat) {
+ if (!er) fs.readFile(cache, function (er, data) {
+ try { data = JSON.parse(data) }
+@@ -48,6 +53,7 @@ function requestAll (cb) {
+ var cache = path.join(this.conf.get('cache'), "/-/all", ".cache.json")
+
+ mkdir(path.join(this.conf.get('cache'), "-", "all"), function (er) {
++ if (er) return cb(er)
+ fs.readFile(cache, function (er, data) {
+ if (er) return requestAll_.call(this, 0, {}, cb)
+ try {
+diff --git a/lib/publish.js b/lib/publish.js
+index d6a7496..2a50380 100644
+--- a/lib/publish.js
++++ b/lib/publish.js
+@@ -1,11 +1,12 @@
+
+ module.exports = publish
+
+-var path = require("path")
+- , url = require("url")
++var 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 +17,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))
++ return cb(new Error('invalid name: must be 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, function(er, tarbuffer) {
++ if (er) return cb(er)
++ putFirst.call(self, data, tarbuffer, s, username, email, cb)
++ })
++ })
++}
+
+- var fullData =
++function putFirst (data, tarbuffer, 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 +54,102 @@ function publish (data, tarball, cb) {
+ ]
+ }
+
++ root.versions[ data.version ] = data
++ data.maintainers = JSON.parse(JSON.stringify(root.maintainers))
++ 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(tarbuffer).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: tarbuffer.toString('base64'),
++ 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");
++ var getUrl = data.name + "?write=true"
++ this.request("GET", getUrl, 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 conflictError (pkgid) {
+- var e = new Error("publish fail")
++function putNext(newVersion, root, current, cb) {
++ // already have the tardata on the root object
++ // just merge in existing stuff
++ var curVers = Object.keys(current.versions || {}).map(function (v) {
++ return semver.clean(v, true)
++ }).concat(Object.keys(current.time || {}).map(function(v) {
++ if (semver.valid(v, true))
++ return semver.clean(v, true)
++ }).filter(function(v) {
++ return v
++ }))
++
++ if (curVers.indexOf(newVersion) !== -1) {
++ return cb(conflictError(root.name, newVersion))
++ }
++
++ current.versions[newVersion] = root.versions[newVersion]
++ current._attachments = current._attachments || {}
++ 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]
++ }
++ }
++ var maint = JSON.parse(JSON.stringify(root.maintainers))
++ root.versions[newVersion].maintainers = maint
++
++ this.request("PUT", root.name, current, cb)
++}
++
++function conflictError (pkgid, version) {
++ var e = new Error("cannot modify pre-existing version")
+ e.code = "EPUBLISHCONFLICT"
+ e.pkgid = pkgid
++ e.version = version
+ 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)
+-}
+diff --git a/lib/request.js b/lib/request.js
+index ff45e0e..7f60666 100644
+--- a/lib/request.js
++++ b/lib/request.js
+@@ -1,19 +1,24 @@
+ module.exports = regRequest
+
+ var url = require("url")
+- , fs = require("graceful-fs")
++ , zlib = require("zlib")
+ , rm = require("rimraf")
+ , asyncMap = require("slide").asyncMap
+ , Stream = require("stream").Stream
+ , request = require("request")
+ , retry = require("retry")
++ , crypto = require("crypto")
++ , pkg = require("../package.json")
+
+-function regRequest (method, where, what, etag, nofollow, reauthed, cb_) {
+- if (typeof cb_ !== "function") cb_ = reauthed, reauthed = false
++function regRequest (method, where, what, etag, nofollow, cb_) {
+ if (typeof cb_ !== "function") cb_ = nofollow, nofollow = false
+ if (typeof cb_ !== "function") cb_ = etag, etag = null
+ if (typeof cb_ !== "function") cb_ = what, what = null
+
++ if (!this.sessionToken) {
++ this.sessionToken = crypto.randomBytes(8).toString("hex")
++ }
++
+ var registry = this.conf.get('registry')
+ if (!registry) return cb(new Error(
+ "No registry url provided: " + method + " " + where))
+@@ -35,9 +40,10 @@ function regRequest (method, where, what, etag, nofollow, reauthed, cb_) {
+ , adduserNew = /^\/?-\/user\/org\.couchdb\.user:([^\/]+)/
+ , nu = where.match(adduserNew)
+ , uc = where.match(adduserChange)
+- , isUpload = what || this.conf.get('always-auth')
++ , alwaysAuth = this.conf.get('always-auth')
+ , isDel = method === "DELETE"
+- , authRequired = isUpload && !nu || uc || isDel
++ , isWrite = what || isDel
++ , authRequired = (alwaysAuth || isWrite) && !nu || uc || isDel
+
+ // resolve to a full url on the registry
+ if (!where.match(/^https?:\/\//)) {
+@@ -64,40 +70,19 @@ function regRequest (method, where, what, etag, nofollow, reauthed, cb_) {
+ var remote = url.parse(where)
+ , auth = this.conf.get('_auth')
+
+- if (authRequired && !this.conf.get('always-auth')) {
+- var couch = this.couchLogin
+- , token = couch && (this.conf.get('_token') || couch.token)
+- , validToken = token && couch.valid(token)
+-
+- if (!validToken) token = null
+- else this.conf.set('_token', token)
+-
+- if (couch && !token) {
+- // login to get a valid token
+- var a = { name: this.conf.get('username'),
+- password: this.conf.get('_password') }
+- var args = arguments
+- return this.couchLogin.login(a, function (er, cr, data) {
+- if (er || !couch.valid(couch.token)) {
+- er = er || new Error('login error')
+- return cb(er, cr, data)
+- }
+- this.conf.set('_token', this.couchLogin.token)
+- return regRequest.call(this,
+- method, where, what,
+- etag, nofollow, reauthed, cb_)
+- }.bind(this))
+- }
++ if (authRequired && !auth) {
++ var un = this.conf.get('username')
++ var pw = this.conf.get('_password')
++ if (un && pw)
++ auth = new Buffer(un + ':' + pw).toString('base64')
+ }
+
+- // now we either have a valid token, or an auth.
+-
+- if (authRequired && !auth && !token) {
++ if (authRequired && !auth) {
+ return cb(new Error(
+- "Cannot insert data into the registry without auth"))
++ "This request requires auth credentials. Run `npm login` and repeat the request."))
+ }
+
+- if (auth && !token) {
++ if (auth && authRequired) {
+ remote.auth = new Buffer(auth, "base64").toString("utf8")
+ }
+
+@@ -114,9 +99,9 @@ function regRequest (method, where, what, etag, nofollow, reauthed, cb_) {
+ operation.attempt(function (currentAttempt) {
+ self.log.info("trying", "registry request attempt " + currentAttempt
+ + " at " + (new Date()).toLocaleTimeString())
+- makeRequest.call(self, method, remote, where, what, etag, nofollow, token
++ makeRequest.call(self, method, remote, where, what, etag, nofollow
+ , function (er, parsed, raw, response) {
+- if (!er || er.message.match(/^SSL Error/)) {
++ if (!er || (er.message && er.message.match(/^SSL Error/))) {
+ if (er)
+ er.code = 'ESSL'
+ return cb(er, parsed, raw, response)
+@@ -125,32 +110,21 @@ function regRequest (method, where, what, etag, nofollow, reauthed, cb_) {
+ // Only retry on 408, 5xx or no `response`.
+ var statusCode = response && response.statusCode
+
+- var reauth = !reauthed &&
+- ( statusCode === 401 ||
+- statusCode === 400 ||
+- statusCode === 403 )
+- if (reauth)
+- reauthed = true
+-
+ var timeout = statusCode === 408
+ var serverError = statusCode >= 500
+ var statusRetry = !statusCode || timeout || serverError
+- if (reauth && this.conf.get('_auth') && this.conf.get('_token')) {
+- this.conf.del('_token')
+- this.couchLogin.token = null
+- return regRequest.call(this, method, where, what,
+- etag, nofollow, reauthed, cb_)
+- }
+ if (er && statusRetry && operation.retry(er)) {
+ self.log.info("retry", "will retry, error on last attempt: " + er)
+ return
+ }
++ if (response)
++ this.log.verbose("headers", response.headers)
+ cb.apply(null, arguments)
+ }.bind(this))
+ }.bind(this))
+ }
+
+-function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
++function makeRequest (method, remote, where, what, etag, nofollow, cb_) {
+ var cbCalled = false
+ function cb () {
+ if (cbCalled) return
+@@ -162,7 +136,11 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
+ if (strict === undefined) strict = true
+ var opts = { url: remote
+ , method: method
++ , encoding: null // tell request let body be Buffer instance
+ , ca: this.conf.get('ca')
++ , localAddress: this.conf.get('local-address')
++ , cert: this.conf.get('cert')
++ , key: this.conf.get('key')
+ , strictSSL: strict }
+ , headers = opts.headers = {}
+ if (etag) {
+@@ -170,11 +148,15 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
+ headers[method === "GET" ? "if-none-match" : "if-match"] = etag
+ }
+
+- if (tok) {
+- headers.cookie = 'AuthSession=' + tok.AuthSession
++ headers['npm-session'] = this.sessionToken
++ headers.version = this.version || pkg.version
++
++ if (this.refer) {
++ headers.referer = this.refer
+ }
+
+ headers.accept = "application/json"
++ headers['accept-encoding'] = 'gzip'
+
+ headers["user-agent"] = this.conf.get('user-agent') ||
+ 'node/' + process.version
+@@ -205,7 +187,7 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
+ this.log.http(method, remote.href || "/")
+
+ var done = requestDone.call(this, method, where, cb)
+- var req = request(opts, done)
++ var req = request(opts, decodeResponseBody(done))
+
+ req.on("error", cb)
+ req.on("socket", function (s) {
+@@ -217,6 +199,26 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
+ }
+ }
+
++function decodeResponseBody(cb) {
++ return function (er, response, data) {
++ if (er) return cb(er, response, data)
++
++ // don't ever re-use connections that had server errors.
++ // those sockets connect to the Bad Place!
++ if (response.socket && response.statusCode > 500) {
++ response.socket.destroy()
++ }
++
++ if (response.headers['content-encoding'] !== 'gzip') return cb(er, response, data)
++
++ zlib.gunzip(data, function (er, buf) {
++ if (er) return cb(er, response, data)
++
++ cb(null, response, buf)
++ })
++ }
++}
++
+ // cb(er, parsed, raw, response)
+ function requestDone (method, where, cb) {
+ return function (er, response, data) {
+@@ -254,7 +256,7 @@ function requestDone (method, where, cb) {
+ , null, data, response )
+ }
+
+- var er = null
++ er = null
+ if (parsed && response.headers.etag) {
+ parsed._etag = response.headers.etag
+ }
+diff --git a/lib/star.js b/lib/star.js
+index 5b7ab4a..23fbd91 100644
+--- a/lib/star.js
++++ b/lib/star.js
+@@ -5,9 +5,7 @@ function star (package, starred, cb) {
+ if (!this.conf.get('username')) return cb(new Error(
+ "Must be logged in to star/unstar packages"))
+
+- var users = {}
+-
+- this.request("GET", package, function (er, fullData) {
++ this.request("GET", package + '?write=true', function (er, fullData) {
+ if (er) return cb(er)
+
+ fullData = { _id: fullData._id
+diff --git a/lib/stars.js b/lib/stars.js
+index 93f0d70..4ef57e2 100644
+--- a/lib/stars.js
++++ b/lib/stars.js
+@@ -1,5 +1,3 @@
+-var qs = require('querystring')
+-
+ module.exports = stars
+
+ function stars (name, cb) {
+diff --git a/lib/tag.js b/lib/tag.js
+index 96136b7..d7ebf08 100644
+--- a/lib/tag.js
++++ b/lib/tag.js
+@@ -1,6 +1,6 @@
+
+ module.exports = tag
+
+-function tag (project, version, tag, cb) {
+- this.request("PUT", project+"/"+tag, JSON.stringify(version), cb)
++function tag (project, version, tagName, cb) {
++ this.request("PUT", project+"/"+tagName, JSON.stringify(version), cb)
+ }
+diff --git a/lib/unpublish.js b/lib/unpublish.js
+index 9aaac1b..1887a99 100644
+--- a/lib/unpublish.js
++++ b/lib/unpublish.js
+@@ -14,7 +14,8 @@ var semver = require("semver")
+ function unpublish (name, ver, cb) {
+ if (typeof cb !== "function") cb = ver, ver = null
+
+- this.get(name, null, -1, true, function (er, data) {
++ var u = name + '?write=true'
++ this.get(u, null, -1, true, function (er, data) {
+ if (er) {
+ this.log.info("unpublish", name+" not published")
+ return cb()
+@@ -28,10 +29,11 @@ function unpublish (name, ver, cb) {
+ var versions = data.versions || {}
+ , versionPublic = versions.hasOwnProperty(ver)
+
++ var dist
+ if (!versionPublic) {
+ this.log.info("unpublish", name+"@"+ver+" not published")
+ } else {
+- var dist = versions[ver].dist
++ dist = versions[ver].dist
+ this.log.verbose("unpublish", "removing attachments", dist)
+ }
+
+diff --git a/test/adduser-new.js b/test/adduser-new.js
+index a0fee04..96dfc26 100644
+--- a/test/adduser-new.js
++++ b/test/adduser-new.js
+@@ -32,9 +32,7 @@ tap.test("create new user account", function (t) {
+
+ req.on("end", function () {
+ var o = JSON.parse(b)
+- var salt = o.salt
+- userdata.salt = salt
+- userdata.password_sha = sha(password + salt)
++ userdata.password = password
+ userdata.date = o.date
+ t.deepEqual(o, userdata)
+
+diff --git a/test/adduser-update.js b/test/adduser-update.js
+index 03a1edb..3704571 100644
+--- a/test/adduser-update.js
++++ b/test/adduser-update.js
+@@ -32,7 +32,7 @@ tap.test("update a user acct", function (t) {
+ res.json({error: "conflict"})
+ })
+
+- server.expect("GET", "/-/user/org.couchdb.user:username", function (req, res) {
++ server.expect("GET", "/-/user/org.couchdb.user:username?write=true", function (req, res) {
+ t.equal(req.method, "GET")
+ res.json(userdata)
+ })
+@@ -47,9 +47,7 @@ tap.test("update a user acct", function (t) {
+
+ req.on("end", function () {
+ var o = JSON.parse(b)
+- var salt = o.salt
+- userdata.salt = salt
+- userdata.password_sha = sha(password + salt)
++ userdata.password = password
+ userdata.date = o.date
+ t.deepEqual(o, userdata)
+
+diff --git a/test/fixtures/server.js b/test/fixtures/server.js
+index 468a89e..80bbf48 100644
+--- a/test/fixtures/server.js
++++ b/test/fixtures/server.js
+@@ -17,10 +17,10 @@ function handler (req, res) {
+ , mu = req.method + ' ' + req.url
+
+ var k = server._expect[mu] ? mu : server._expect[u] ? u : null
+- if (!k) throw Error('unexpected request', req.method, req.url)
++ if (!k) throw Error('unexpected request: ' + req.method + ' ' + req.url)
+
+ var fn = server._expect[k].shift()
+- if (!fn) throw Error('unexpected request', req.method, req.url)
++ if (!fn) throw Error('unexpected request' + req.method + ' ' + req.url)
+
+
+ var remain = (Object.keys(server._expect).reduce(function (s, k) {
+diff --git a/test/publish-again.js b/test/publish-again.js
+new file mode 100644
+index 0000000..011fbaf
+--- /dev/null
++++ b/test/publish-again.js
+@@ -0,0 +1,81 @@
++var tap = require('tap')
++var server = require('./fixtures/server.js')
++var RC = require('../')
++var client = new RC(
++ { cache: __dirname + '/fixtures/cache'
++ , registry: 'http://localhost:' + server.port
++ , username: "username"
++ , password: "password"
++ , email: "i at izs.me"
++ , _auth: new Buffer("username:password").toString('base64')
++ , "always-auth": true
++ })
++
++var fs = require("fs")
++
++tap.test("publish again", function (t) {
++ var lastTime = null
++ server.expect("/npm-registry-client", function (req, res) {
++ t.equal(req.method, "PUT")
++ var b = ""
++ req.setEncoding('utf8')
++ req.on("data", function (d) {
++ b += d
++ })
++
++ req.on("end", function () {
++ var o = lastTime = JSON.parse(b)
++ t.equal(o._id, "npm-registry-client")
++ t.equal(o["dist-tags"].latest, pkg.version)
++ t.has(o.versions[pkg.version], pkg)
++ t.same(o.maintainers, [ { name: 'username', email: 'i at izs.me' } ])
++ var att = o._attachments[ pkg.name + '-' + pkg.version + '.tgz' ]
++ t.same(att.data, pd)
++ res.statusCode = 409
++ res.json({reason: "must supply latest _rev to update existing package"})
++ })
++ })
++
++ server.expect("/npm-registry-client?write=true", function (req, res) {
++ t.equal(req.method, "GET")
++ t.ok(lastTime)
++ for (var i in lastTime.versions) {
++ var v = lastTime.versions[i]
++ delete lastTime.versions[i]
++ lastTime.versions["0.0.2"] = v
++ lastTime["dist-tags"] = { latest: "0.0.2" }
++ }
++ lastTime._rev = "asdf"
++ res.json(lastTime)
++ })
++
++ server.expect("/npm-registry-client", function (req, res) {
++ t.equal(req.method, "PUT")
++ t.ok(lastTime)
++
++ var b = ""
++ req.setEncoding('utf8')
++ req.on("data", function (d) {
++ b += d
++ })
++
++ req.on("end", function() {
++ var o = JSON.parse(b)
++ t.equal(o._rev, "asdf")
++ t.deepEqual(o.versions["0.0.2"], o.versions[pkg.version])
++ res.statusCode = 201
++ res.json({created: true})
++ })
++ })
++
++
++ // not really a tarball, but doesn't matter
++ var tarball = require.resolve('../package.json')
++ var pd = fs.readFileSync(tarball, 'base64')
++ var pkg = require('../package.json')
++ client.publish(pkg, tarball, function (er, data, raw, res) {
++ if (er) throw er
++ t.deepEqual(data, { created: true })
++ t.end()
++ })
++})
+diff --git a/test/publish.js b/test/publish.js
+new file mode 100644
+index 0000000..9dcfc33
+--- /dev/null
++++ b/test/publish.js
+@@ -0,0 +1,51 @@
++var tap = require('tap')
++var crypto = require('crypto')
++var server = require('./fixtures/server.js')
++var RC = require('../')
++var client = new RC(
++ { cache: __dirname + '/fixtures/cache'
++ , registry: 'http://localhost:' + server.port
++ , username: "username"
++ , password: "password"
++ , email: "i at izs.me"
++ , _auth: new Buffer("username:password").toString('base64')
++ , "always-auth": true
++ })
++
++var fs = require("fs")
++
++tap.test("publish", function (t) {
++ server.expect("/npm-registry-client", function (req, res) {
++ t.equal(req.method, "PUT")
++ var b = ""
++ req.setEncoding('utf8')
++ req.on("data", function (d) {
++ b += d
++ })
++
++ req.on("end", function () {
++ var o = JSON.parse(b)
++ t.equal(o._id, "npm-registry-client")
++ t.equal(o["dist-tags"].latest, pkg.version)
++ t.has(o.versions[pkg.version], pkg)
++ t.same(o.maintainers, [ { name: 'username', email: 'i at izs.me' } ])
++ t.same(o.maintainers, o.versions[pkg.version].maintainers)
++ var att = o._attachments[ pkg.name + '-' + pkg.version + '.tgz' ]
++ t.same(att.data, pd)
++ var hash = crypto.createHash('sha1').update(pd, 'base64').digest('hex')
++ t.equal(o.versions[pkg.version].dist.shasum, hash)
++ res.statusCode = 201
++ res.json({created:true})
++ })
++ })
++
++ // not really a tarball, but doesn't matter
++ var tarball = require.resolve('../package.json')
++ var pd = fs.readFileSync(tarball, 'base64')
++ var pkg = require('../package.json')
++ client.publish(pkg, tarball, function (er, data, raw, res) {
++ if (er) throw er
++ t.deepEqual(data, { created: true })
++ t.end()
++ })
++})
+diff --git a/test/request-gzip-content.js b/test/request-gzip-content.js
+new file mode 100644
+index 0000000..2c7dcae
+--- /dev/null
++++ b/test/request-gzip-content.js
+@@ -0,0 +1,47 @@
++var zlib = require('zlib')
++var tap = require('tap')
++var server = require('./fixtures/server.js')
++var RC = require('../')
++var pkg = {
++ _id: 'some-package-gzip at 1.2.3',
++ name: 'some-package-gzip',
++ version: '1.2.3'
++}
++
++zlib.gzip(JSON.stringify(pkg), function (err, pkgGzip) {
++ var client = new RC({
++ cache: __dirname + '/fixtures/cache'
++ , 'fetch-retries': 1
++ , 'fetch-retry-mintimeout': 10
++ , 'fetch-retry-maxtimeout': 100
++ , registry: 'http://localhost:' + server.port })
++
++ tap.test('request gzip package content', function (t) {
++ server.expect('GET', '/some-package-gzip/1.2.3', function (req, res) {
++ res.statusCode = 200
++ res.setHeader('Content-Encoding', 'gzip');
++ res.setHeader('Content-Type', 'application/json');
++ res.end(pkgGzip)
++ })
++
++ client.get('/some-package-gzip/1.2.3', function (er, data, raw, res) {
++ if (er) throw er
++ t.deepEqual(data, pkg)
++ t.end()
++ })
++ })
++
++ tap.test('request wrong gzip package content', function (t) {
++ server.expect('GET', '/some-package-gzip-error/1.2.3', function (req, res) {
++ res.statusCode = 200
++ res.setHeader('Content-Encoding', 'gzip')
++ res.setHeader('Content-Type', 'application/json')
++ res.end(new Buffer('wrong gzip content'))
++ })
++
++ client.get('/some-package-gzip-error/1.2.3', function (er, data, raw, res) {
++ t.ok(er)
++ t.end()
++ })
++ })
++});
diff --git a/nodejs-npm-registry-client.spec b/nodejs-npm-registry-client.spec
index 4c6230b..bac6725 100644
--- a/nodejs-npm-registry-client.spec
+++ b/nodejs-npm-registry-client.spec
@@ -2,7 +2,7 @@
Name: nodejs-npm-registry-client
Version: 0.2.28
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: Client for the npm registry
Group: System Environment/Libraries
@@ -11,6 +11,11 @@ URL: https://github.com/isaacs/npm-registry-client
Source0: http://registry.npmjs.org/npm-registry-client/-/npm-registry-client-%{version}.tgz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+# this patch fixes `npm adduser` and `npm publish`
+# it effectively updates this package to v0.4.12; however we can't bump the
+# version of this package without breaking the world
+Patch1: %{name}-publish-fixes.patch
+
BuildArch: noarch
%if 0%{?fedora} >= 19
ExclusiveArch: %{nodejs_arches} noarch
@@ -25,6 +30,8 @@ Client for the npm registry, or private servers using the npm registry software.
%prep
%setup -q -n package
+%patch1 -p1
+%nodejs_fixdep -r couch-login
%build
#nothing to do
@@ -45,6 +52,9 @@ rm -rf %buildroot
%doc README.md LICENSE
%changelog
+* Sat May 16 2015 T.C. Hollingsworth <tchollingsworth at gmail.com> - 0.2.28-3
+- backport fixes to publish and adduser functions (RHBZ#1220472)
+
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.2.28-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
--
cgit v0.10.2
http://pkgs.fedoraproject.org/cgit/nodejs-npm-registry-client.git/commit/?h=el6&id=467e412aa6ef424eaa03c7dae6a12a062a558a86
More information about the scm-commits
mailing list