1 | module.exports = unbuild
|
2 | unbuild.usage = "npm unbuild <folder>\n(this is plumbing)"
|
3 |
|
4 | var 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 |
|
16 |
|
17 | function unbuild (args, silent, cb) {
|
18 | if (typeof silent === "function") cb = silent, silent = false
|
19 | asyncMap(args, unbuild_(silent), cb)
|
20 | }
|
21 |
|
22 | function 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 |
|
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 |
|
48 | function rmStuff (pkg, folder, cb) {
|
49 |
|
50 |
|
51 |
|
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 |
|
65 | function 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 |
|
78 | function 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 | }
|