
exports = module.exports = lifecycle
exports.cmd = cmd

var log = require("./log")
  , exec = require("./exec")
  , npm = require("../../npm")
  , path = require("path")
  , readJson = require("./read-json")
  , fs = require("fs")

function lifecycle (pkg, stage, cb) {
  while (pkg && pkg._data) pkg = pkg._data
  if (!pkg) return cb(new Error("Invalid package data"))
  if (!pkg.scripts || !(stage in pkg.scripts)) return cb()

  // run package lifecycle scripts in the package root, or the nearest parent.
  var d = path.join(npm.dir, pkg.name, pkg.version, "package")
  while (d) {
    try {
      process.chdir(d)
      break
    } catch (ex) {
      d = path.dirname(d)
    }
  }
  log(pkg._id, stage)

  // set the env variables, then run the script as a child process.
  // NOTE: The env vars won't work until node supports env hashes for child procs
  var env = makeEnv(pkg)
  env.npm_lifecycle_event = stage
  env.npm_lifecycle_script = pkg.scripts[stage]
  exec("sh", ["-c", env.npm_lifecycle_script], env, function (er) {
    if (er) {
      log("Failed to exec "+stage+" script", pkg._id)
      er.message = pkg._id + " " + stage + ": `" + env.npm_lifecycle_script+"`\n"
                 + er.message
      return cb(er)
    }
    // check for a hook script
    var hook = path.join(npm.dir, ".hooks", stage)
    fs.stat(hook, function (er) {
      if (er) return cb()
      exec(hook, env, function (er) {
        if (er) log("Failed to exec "+stage+" hook script", pkg._id)
        cb(er)
      })
    })
  })
}

function makeEnv (data, prefix, env) {
  if (data._lifecycleEnv) return data._lifecycleEnv
  prefix = prefix || "npm_package_"
  if (!env) {
    env = {}
    for (var i in process.env) env[i] = process.env[i]
  } else {
    Object.defineProperty(data, "_lifecycleEnv",
      { value : env
      , enumerable : false
      })
  }

  for (var i in data) if (i.charAt(0) !== "_") {
    if (data[i] && typeof(data[i]) === "object") {
      env[prefix+i] = JSON.stringify(data[i])
      makeEnv(data[i], prefix+i+"_", env)
    } else {
      env[prefix+i] = String(data[i])
    }
  }
  if (prefix !== "npm_package_") return env
  prefix = "npm_config_"
  var conf = npm.config.get()
  for (var i in conf) if (i.charAt(0) !== "_") {
    env[prefix+i] = String(conf[i])
  }
  return env
}

function cmd (stage, req) { return function (args, cb) {
  var pkg = args[0]
    , ver = pkg.indexOf("/") !== -1 ? "" : (args[1] || "active")
    , json = path.join(npm.dir, pkg, ver, "package/package.json")
  readJson(json, function (er, data) {
    data.version = ver
    if (er) return log.er(cb, "Couldn't find "+path.join(pkg, ver))(er)
    if ( !data.scripts
        || !(stage in data.scripts)
        && !("pre"+stage in data.scripts)) {
      log("Nothing to do", stage)
      return cb(req ? new Error("Nothing to do") : null)
    }
    lifecycle(data, "pre"+stage, function (er) {
      if (er) return log.er(cb, "Failed pre"+stage)(er)
      lifecycle(data, stage, cb)
    })
  })
}}

@@ -2354,24 +2354,25 @@
 on (args, cb
+_
 ) %7B%0A  var pk
@@ -2373,87 +2373,227 @@
 var 
-pkg
+d
  = args
-%5B0%5D%0A    , ver = pkg.indexOf(%22/%22) !== -1 ? %22%22 : (args%5B1%5D %7C%7C %22active
+.length%0A  function cb (er) %7B%0A    if (er) return cb_(er)%0A    if (-- d === 0) return cb_()%0A  %7D%0A  args.forEach(function (arg) %7B%0A    var pkg = arg.split(%22@%22)%0A      , name = pkg.shift()%0A      , ver = pkg.join(%22@
 %22)%0A
+  
     
@@ -2620,24 +2620,37 @@
 pm.dir, 
-pkg
+name
 , ver
+ %7C%7C %22active%22
 , %22packa
@@ -2667,16 +2667,18 @@
 .json%22)%0A
+  
   readJs
@@ -2714,29 +2714,8 @@
 %7B%0A  
-  data.version = ver%0A
     
@@ -2761,37 +2761,149 @@
 d %22+
-path.join(pkg, ver))(er)%0A
+name + %22@%22 + ver)(er)%0A      if (ver && ver !== data.version) %7B%0A        data.version = ver%0A        data._id = data.name+%22-%22+ver%0A      %7D%0A 
     
+ 
 if (
@@ -2917,16 +2917,18 @@
 scripts%0A
+  
         
@@ -2963,16 +2963,18 @@
         
+ 
+ 
 && !(%22pr
@@ -2998,24 +2998,26 @@
 scripts)) %7B%0A
+  
       log(%22N
@@ -3040,24 +3040,26 @@
 tage)%0A      
+  
 return cb(re
@@ -3097,26 +3097,30 @@
 : null)%0A    
-%7D%0A
+  %7D%0A  
     lifecycl
@@ -3154,32 +3154,34 @@
 on (er) %7B%0A      
+  
 if (er) return l
@@ -3216,24 +3216,26 @@
 )(er)%0A      
+  
 lifecycle(da
@@ -3249,16 +3249,25 @@
 ge, cb)%0A
+      %7D)%0A
     %7D)%0A 

Update the lifecycle commands to follow the "name@version" convention, and also support multiple args