UNPKG

3.78 kBJavaScriptView Raw
1module.exports = unbuild
2unbuild.usage = "npm unbuild <folder>\n(this is plumbing)"
3
4var readJson = require("read-package-json")
5 , gentlyRm = require("./utils/gently-rm.js")
6 , npm = require("./npm.js")
7 , path = require("path")
8 , isInside = require("path-is-inside")
9 , lifecycle = require("./utils/lifecycle.js")
10 , asyncMap = require("slide").asyncMap
11 , chain = require("slide").chain
12 , log = require("npmlog")
13 , build = require("./build.js")
14
15// args is a list of folders.
16// remove any bins/etc, and then delete the folder.
17function unbuild (args, silent, cb) {
18 if (typeof silent === "function") cb = silent, silent = false
19 asyncMap(args, unbuild_(silent), cb)
20}
21
22function unbuild_ (silent) { return function (folder, cb_) {
23 function cb (er) {
24 cb_(er, path.relative(npm.root, folder))
25 }
26 folder = path.resolve(folder)
27 var base = isInside(folder, npm.prefix) ? npm.prefix : folder
28 delete build._didBuild[folder]
29 log.verbose("unbuild", folder.substr(npm.prefix.length + 1))
30 readJson(path.resolve(folder, "package.json"), function (er, pkg) {
31 // if no json, then just trash it, but no scripts or whatever.
32 if (er) return gentlyRm(folder, false, base, cb)
33 readJson.cache.del(folder)
34 chain
35 ( [ [lifecycle, pkg, "preuninstall", folder, false, true]
36 , [lifecycle, pkg, "uninstall", folder, false, true]
37 , !silent && function(cb) {
38 console.log("unbuild " + pkg._id)
39 cb()
40 }
41 , [rmStuff, pkg, folder]
42 , [lifecycle, pkg, "postuninstall", folder, false, true]
43 , [gentlyRm, folder, false, base] ]
44 , cb )
45 })
46}}
47
48function rmStuff (pkg, folder, cb) {
49 // if it's global, and folder is in {prefix}/node_modules,
50 // then bins are in {prefix}/bin
51 // otherwise, then bins are in folder/../.bin
52 var parent = path.dirname(folder)
53 , gnm = npm.dir
54 , top = gnm === parent
55
56 readJson.cache.del(path.resolve(folder, "package.json"))
57
58 log.verbose("unbuild rmStuff", pkg._id, "from", gnm)
59 if (!top) log.verbose("unbuild rmStuff", "in", parent)
60 asyncMap([rmBins, rmMans], function (fn, cb) {
61 fn(pkg, folder, parent, top, cb)
62 }, cb)
63}
64
65function rmBins (pkg, folder, parent, top, cb) {
66 if (!pkg.bin) return cb()
67 var binRoot = top ? npm.bin : path.resolve(parent, ".bin")
68 asyncMap(Object.keys(pkg.bin), function (b, cb) {
69 if (process.platform === "win32") {
70 chain([ [gentlyRm, path.resolve(binRoot, b) + ".cmd", true]
71 , [gentlyRm, path.resolve(binRoot, b), true] ], cb)
72 } else {
73 gentlyRm(path.resolve(binRoot, b), true, cb)
74 }
75 }, cb)
76}
77
78function rmMans (pkg, folder, parent, top, cb) {
79 if (!pkg.man
80 || !top
81 || process.platform === "win32"
82 || !npm.config.get("global")) {
83 return cb()
84 }
85 var manRoot = path.resolve(npm.config.get("prefix"), "share", "man")
86 log.verbose("rmMans", "man files are", pkg.man, "in", manRoot)
87 asyncMap(pkg.man, function (man, cb) {
88 if (Array.isArray(man)) {
89 man.forEach(rmMan)
90 } else {
91 rmMan(man)
92 }
93
94 function rmMan (man) {
95 log.silly("rmMan", "preparing to remove", man)
96 var parseMan = man.match(/(.*\.([0-9]+)(\.gz)?)$/)
97 if (!parseMan) {
98 log.error(
99 "rmMan", man, "is not a valid name for a man file.",
100 "Man files must end with a number, " +
101 "and optionally a .gz suffix if they are compressed."
102 )
103 return cb()
104 }
105
106 var stem = parseMan[1]
107 var sxn = parseMan[2]
108 var gz = parseMan[3] || ""
109 var bn = path.basename(stem)
110 var manDest = path.join(
111 manRoot,
112 "man"+sxn,
113 (bn.indexOf(pkg.name) === 0 ? bn : pkg.name+"-"+bn)+"."+sxn+gz
114 )
115 gentlyRm(manDest, true, cb)
116 }
117 }, cb)
118}