Skip to content
This repository has been archived by the owner on Aug 11, 2022. It is now read-only.

Commit

Permalink
Merge branch 'bindist'
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Mar 30, 2011
2 parents 5c83253 + 7988680 commit b6ed06b
Show file tree
Hide file tree
Showing 18 changed files with 364 additions and 78 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Expand Up @@ -4,6 +4,6 @@
[submodule "node_modules/abbrev"]
path = node_modules/abbrev
url = git://github.com/isaacs/abbrev-js.git
[submodule "node_modules/optparse"]
path = node_modules/optparse
url = git://github.com/isaacs/node-optparse.git
[submodule "node_modules/nopt"]
path = node_modules/nopt
url = git://github.com/isaacs/nopt.git
4 changes: 2 additions & 2 deletions bin/npm.js
Expand Up @@ -15,11 +15,11 @@ var fs = require("../lib/utils/graceful-fs")
, configDefs = require("../lib/utils/config-defs")
, shorthands = configDefs.shorthands
, types = configDefs.types
, optparse = require("optparse")
, nopt = require("nopt")

log.verbose(process.argv, "cli")

var conf = optparse(types, shorthands)
var conf = nopt(types, shorthands)
npm.argv = conf.argv.remain
if (npm.deref(npm.argv[0])) npm.command = npm.argv.shift()
else conf.usage = true
Expand Down
17 changes: 17 additions & 0 deletions doc/config.md
Expand Up @@ -130,6 +130,23 @@ then the user could change the behavior by doing:

## Config Settings

### bindist

* Default: Unstable node versions, `null`, otherwise
`"<node version>-<platform>-<os release>"`
* Type: String or `null`

Experimental: on stable versions of node, binary distributions will be
created with this tag. If a user then installs that package, and their
`bindist` tag is found in the list of binary distributions, they will
get that prebuilt version.

Pre-build node packages have their preinstall, install, and postinstall
scripts stripped (since they are run prior to publishing), and do not
have their `build` directories automatically ignored.

It's yet to be seen if this is a good idea.

### browser

* Default: OS X: `"open"`, others: `"google-chrome"`
Expand Down
38 changes: 33 additions & 5 deletions lib/cache.js
Expand Up @@ -102,6 +102,7 @@ function read (name, ver, cb) {
if (data) deprCheck(data)
return cb(er, data)
}

if (npm.config.get("force") || process.platform === "cygwin") {
log.verbose(true, "force found, skipping cache")
return addNamed(name, ver, c)
Expand All @@ -110,6 +111,7 @@ function read (name, ver, cb) {
if (name+"@"+ver in cacheSeen) {
return cb(null, cacheSeen[name+"@"+ver])
}

readJson(jsonFile, function (er, data) {
if (er) return addNamed(name, ver, c)
deprCheck(data)
Expand Down Expand Up @@ -281,20 +283,38 @@ function addNameVersion (name, ver, cb) {
registry.get(name, ver, function (er, data, json, response) {
if (er) return cb(er)
deprCheck(data)
if (!data.dist || !data.dist.tarball) return cb(new Error(
"No dist.tarball in package data"))
var dist = data.dist

if (!dist) return cb(new Error("No dist in "+data._id+" package"))

var bd = npm.config.get("bindist")
, b = dist.bin && bd && dist.bin[bd]
log.verbose([bd, dist], "bin dist")
if (b && b.tarball && b.shasum) {
log.info(data._id, "prebuilt")
log.verbose(b, "prebuilt "+data._id)
dist = b
}

if (!dist.tarball) return cb(new Error(
"No dist.tarball in " + data._id + " package"))

if (response.statusCode !== 304 || npm.config.get("force")
|| process.platform === "cygwin") {
return fetchit()
}

// we got cached data, so let's see if we have a tarball.
fs.stat(path.join(npm.cache, name, ver, "package.tgz"), function (er, s) {
if (!er) return cb(null, data)
else return fetchit()
})

function fetchit () {
return addRemoteTarball( data.dist.tarball.replace(/^https/,'http')
, data.dist.shasum, name+"-"+ver, cb)
return addRemoteTarball( dist.tarball.replace(/^https/,'http')
, dist.shasum
, name+"-"+ver
, cb )
}
})
}
Expand Down Expand Up @@ -438,8 +458,16 @@ function addTmpTarball (tgz, name, cb) {
}

function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb) {
if (typeof cb !== "function") cb = gid, gid = null
if (typeof cb !== "function") cb = uid, uid = null
if (typeof cb !== "function") cb = fMode, fMode = null
if (typeof cb !== "function") cb = dMode, dMode = null

read(pkg, ver, function (er, data) {
if (er) return log.er(cb, "Could not read data for "+pkg+"@"+ver)(er)
if (er) {
log.error("Could not read data for "+pkg+"@"+ver)
return cb(er)
}
tar.unpack( path.join(npm.cache, pkg, ver, "package.tgz")
, unpackTarget
, dMode, fMode
Expand Down
4 changes: 2 additions & 2 deletions lib/completion.js
Expand Up @@ -7,7 +7,7 @@ var output = require("./utils/output")
, configDefs = require("./utils/config-defs")
, configTypes = configDefs.types
, shorthands = configDefs.shorthands
, optparse = require("optparse")
, nopt = require("nopt")
, configNames = Object.keys(configTypes).filter(function (e) {
return e.charAt(0) !== "_"
})
Expand Down Expand Up @@ -116,7 +116,7 @@ function completion (args, cb) {
// don't have to worry about the last arg being implicitly
// boolean'ed, since the last block will catch that.
var parsed = opts.conf =
optparse(configTypes, shorthands, partialWords.slice(0, -1), 0)
nopt(configTypes, shorthands, partialWords.slice(0, -1), 0)
// check if there's a command already.
console.error(parsed)
var cmd = parsed.argv.remain[1]
Expand Down
91 changes: 82 additions & 9 deletions lib/publish.js
Expand Up @@ -4,6 +4,11 @@ module.exports = publish
var npm = require("../npm")
, registry = require("./utils/npm-registry-client")
, log = require("./utils/log")
, 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>"
Expand All @@ -28,16 +33,84 @@ 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
var bd = data.scripts
&& ( data.scripts.preinstall
|| data.scripts.install
|| data.scripts.postinstall )
&& npm.config.get("bindist")
preBuild(data, bd, function (er, tb) {
if (er) return cb(er)
return regPublish(data, tb, isRetry, args, cb)
})
})
}

function preBuild (data, bd, cb) {
if (!bd) return cb()
// unpack to cache/n/v/build
// build there
// pack to cache/package-<bd>.tgz
var cf = path.resolve(npm.cache, data.name, data.version)
var pb = path.resolve(cf, "build")
, tb = path.resolve(cf, "package-"+bd+".tgz")

log.verbose("about to cache unpack")
npm.commands.cache.unpack(data.name, data.version, pb, function (er) {
log.verbose("back from cache unpack")
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 "+bd)
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
}
pbo.prebuilt = bd
pbo.files = pbo.files || []
pbo.files.push("build")
fs.writeFile(pbj, JSON.stringify(pbo, null, 2), 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.bin = data.dist.bin || {}
data.dist.bin[bd] = data.dist.bin[bd] || {}
data.dist.bin[bd].shasum = shasum
return cb(null, tb)
})
})
})
})
})
})
}

function regPublish (data, prebuilt, isRetry, args, 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)
})
}
9 changes: 9 additions & 0 deletions lib/utils/config-defs.js
Expand Up @@ -5,9 +5,17 @@ var path = require("path")
, stdio = process.binding("stdio")
, url = require("url")
, Stream = require("stream").Stream
, semver = require("semver")
, stableFamily = semver.parse(process.version)
, os = require("os")

if (!stableFamily || (+stableFamily[2] % 2)) stableFamily = null
else stableFamily = stableFamily[1] + "." + stableFamily[2]

exports.defaults =
{ argv : []
, bindist : stableFamily
&& (stableFamily + "-" + process.platform + "-" + os.release())
// are there others?
, browser : process.platform === "darwin" ? "open" : "google-chrome"
, cache : path.resolve( process.env.HOME
Expand Down Expand Up @@ -61,6 +69,7 @@ exports.defaults =

exports.types =
{ argv : NaN
, bindist : [String, null]
, browser : String
, cache : path
, color : ["always", Boolean]
Expand Down

0 comments on commit b6ed06b

Please sign in to comment.