1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
// link the supplied folder to .npm/{name}/{version}/package
var npm = require("../npm")
, chain = require("./utils/chain")
, log = require("./utils/log")
, fs = require("./utils/graceful-fs")
, readJson = require("./utils/read-json")
, rm = require("./utils/rm-rf")
, mkdir = require("./utils/mkdir-p")
, path = require("path")
, crypto
, readInstalled = require("./utils/read-installed")
, semver = require("./utils/semver")
try {
crypto = process.binding("crypto") && require("crypto")
} catch (ex) {}
module.exports = link
function link (args, cb) {
if (!crypto) return cb(new Error(
"You must compile node with ssl support to use the link feature"))
var folder = args.shift() || "."
// folder's root MUST contain a package.json
// read that for package info, then link it in, clobbering if necessary.
if (folder.charAt(0) !== "/") folder = path.join(process.cwd(), folder)
var jsonFile = path.join(folder, "package.json")
log(folder, "link")
chain
( function (cb) { fs.stat(folder, function (er, stats) {
if (er) return cb(er)
if (!stats.isDirectory()) return cb(new Error(
"npm link requires a directory"))
cb()
})}
, [log.verbose, "reading "+jsonFile, "link"]
, [readAndLink, jsonFile, folder]
, cb
)
}
function readAndLink (jsonFile, folder, cb) {
readJson
( jsonFile
, { "tag" : "-1-LINK-"+(
crypto.createHash("sha1").update(folder).digest("hex").substr(0,8)
)}
, doLink(folder, cb)
)
}
function getDeps (data) {
var deps = data.dependencies || {}
, devDeps = data.devDependencies || {}
Object.keys(devDeps).forEach(function (d) { deps[d] = devDeps[d] })
return deps
}
function doLink (folder, cb) { return function (er, data) {
if (er) return cb(er)
log.verbose(data.name+" "+data.version, "link")
var pkgDir = path.join(npm.dir, data.name, data.version, "package")
, deps = getDeps(data)
, depNames = Object.keys(deps)
// skip any that are installed
readInstalled(depNames, function (er, inst) {
if (er) return log.er(cb, "Couldn't read installed packages")(er)
for (var d in inst) if (deps[d]) {
var satis = semver.maxSatisfying(Object.keys(inst[d]), deps[d])
if (satis) delete deps[d]
}
var depsNeeded = Object.keys(deps).map(function (d) {
return d+"@"+deps[d]
})
log.verbose(depsNeeded, "link install deps")
chain
( depsNeeded.length
? [ npm.commands, "install", depsNeeded.slice(0) ]
: function (cb) { cb() }
, [ require("./utils/link"), folder, pkgDir ]
, [ npm.commands, "build", [data] ]
, function (er) {
if (!er) return cb()
// error, rollback
npm.ROLLBACK = true
log.error(er, "error linking, rollback")
var rb = depsNeeded.concat([data.name+"@"+data.version])
npm.commands.rm(rb, function (er_) {
if (er_) log.error(er_, "error rolling back")
cb(er)
})
}
)
})
}}
|