Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorForrest L Norvell <forrest@npmjs.com>2014-04-29 04:43:54 +0400
committerForrest L Norvell <forrest@npmjs.com>2014-05-08 04:37:11 +0400
commitcc8dd4e63294443be8798bae881ef9ebb4b728c7 (patch)
treeda0240d97eac85d6b8d61aac36732b6199c09a32
parent0de64345a7ee94b60121ab9685d9468ab0146b3b (diff)
split out cache locking into separate file
-rw-r--r--lib/cache.js111
-rw-r--r--lib/cache/get-stat.js62
-rw-r--r--lib/utils/locker.js54
-rw-r--r--lib/utils/tar.js6
4 files changed, 131 insertions, 102 deletions
diff --git a/lib/cache.js b/lib/cache.js
index 32fb9f832..88aff8038 100644
--- a/lib/cache.js
+++ b/lib/cache.js
@@ -1,3 +1,6 @@
+'use strict';
+/* jshint node: true */
+
// XXX lib/utils/tar.js and this file need to be rewritten.
// URL-to-cache folder mapping:
@@ -54,8 +57,6 @@ exports = module.exports = cache
cache.read = read
cache.clean = clean
cache.unpack = unpack
-cache.lock = lock
-cache.unlock = unlock
var mkdir = require("mkdirp")
, spawn = require("child_process").spawn
@@ -76,7 +77,6 @@ var mkdir = require("mkdirp")
, fileCompletion = require("./utils/completion/file-completion.js")
, url = require("url")
, chownr = require("chownr")
- , lockFile = require("lockfile")
, crypto = require("crypto")
, retry = require("retry")
, zlib = require("zlib")
@@ -85,6 +85,10 @@ var mkdir = require("mkdirp")
, isGitUrl = require("./utils/is-git-url.js")
, pathIsInside = require("path-is-inside")
, http = require("http")
+ , getCacheStat = require("./cache/get-stat.js")
+ , locker = require("./utils/locker.js")
+ , lock = locker.lock
+ , unlock = locker.unlock
cache.usage = "npm cache add <tarball file>"
+ "\nnpm cache add <folder>"
@@ -346,7 +350,7 @@ function fetchAndShaCheck (u, tmp, shasum, cb) {
// validate that the url we just downloaded matches the expected shasum.
sha.check(tmp, shasum, function (er) {
- if (er != null && er.message) {
+ if (er && er.message) {
// add original filename for better debuggability
er.message = er.message + '\n' + 'From: ' + u
}
@@ -502,7 +506,7 @@ function checkGitDir (p, u, co, origUrl, silent, cb) {
return cb(err)
}
exec(git, args, {cwd: p, env: env}, function (er, stdout, stderr) {
- stdoutTrimmed = (stdout + "\n" + stderr).trim()
+ var stdoutTrimmed = (stdout + "\n" + stderr).trim()
if (er || u !== stdout.trim()) {
log.warn( "`git config --get remote.origin.url` returned "
+ "wrong result ("+u+")", stdoutTrimmed )
@@ -1041,59 +1045,6 @@ function addLocalTarball (p, name, version, shasum, cb_) {
})
}
-// to maintain the cache dir's permissions consistently.
-var cacheStat = null
-function getCacheStat (cb) {
- if (cacheStat) return cb(null, cacheStat)
- fs.stat(npm.cache, function (er, st) {
- if (er) return makeCacheDir(cb)
- if (!st.isDirectory()) {
- log.error("getCacheStat", "invalid cache dir %j", npm.cache)
- return cb(er)
- }
- return cb(null, cacheStat = st)
- })
-}
-
-function makeCacheDir (cb) {
- if (!process.getuid) return mkdir(npm.cache, cb)
-
- var uid = +process.getuid()
- , gid = +process.getgid()
-
- if (uid === 0) {
- if (process.env.SUDO_UID) uid = +process.env.SUDO_UID
- if (process.env.SUDO_GID) gid = +process.env.SUDO_GID
- }
- if (uid !== 0 || !process.env.HOME) {
- cacheStat = {uid: uid, gid: gid}
- return mkdir(npm.cache, afterMkdir)
- }
-
- fs.stat(process.env.HOME, function (er, st) {
- if (er) {
- log.error("makeCacheDir", "homeless?")
- return cb(er)
- }
- cacheStat = st
- log.silly("makeCacheDir", "cache dir uid, gid", [st.uid, st.gid])
- return mkdir(npm.cache, afterMkdir)
- })
-
- function afterMkdir (er, made) {
- if (er || !cacheStat || isNaN(cacheStat.uid) || isNaN(cacheStat.gid)) {
- return cb(er, cacheStat)
- }
-
- if (!made) return cb(er, cacheStat)
-
- // ensure that the ownership is correct.
- chownr(made, cacheStat.uid, cacheStat.gid, function (er) {
- return cb(er, cacheStat)
- })
- }
-}
-
@@ -1307,10 +1258,11 @@ function addTmpTarball (tgz, name, version, shasum, cb) {
tmp = true
name = 'tmp_' + crypto.randomBytes(6).toString('hex')
}
+ var pdir
if (!tmp) {
- var pdir = path.resolve(npm.cache, name, version, "package")
+ pdir = path.resolve(npm.cache, name, version, "package")
} else {
- var pdir = path.resolve(npm.cache, name + version + "package")
+ pdir = path.resolve(npm.cache, name + version + "package")
}
getCacheStat(function (er, cs) {
@@ -1396,45 +1348,6 @@ function deprCheck (data) {
}
}
-function lockFileName (u) {
- var c = u.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "")
- , h = crypto.createHash("sha1").update(u).digest("hex")
- h = h.substr(0, 8)
- c = c.substr(-32)
- log.silly("lockFile", h + "-" + c, u)
- return path.resolve(npm.config.get("cache"), h + "-" + c + ".lock")
-}
-
-var myLocks = {}
-function lock (u, cb) {
- // the cache dir needs to exist already for this.
- getCacheStat(function (er, cs) {
- if (er) return cb(er)
- var opts = { stale: npm.config.get("cache-lock-stale")
- , retries: npm.config.get("cache-lock-retries")
- , wait: npm.config.get("cache-lock-wait") }
- var lf = lockFileName(u)
- log.verbose("lock", u, lf)
- lockFile.lock(lf, opts, function(er) {
- if (!er) myLocks[lf] = true
- cb(er)
- })
- })
-}
-
-function unlock (u, cb) {
- var lf = lockFileName(u)
- , locked = myLocks[lf]
- if (locked === false) {
- return process.nextTick(cb)
- } else if (locked === true) {
- myLocks[lf] = false
- lockFile.unlock(lockFileName(u), cb)
- } else {
- throw new Error("Attempt to unlock " + u + ", which hasn't been locked")
- }
-}
-
function needName(er, data) {
return er ? er
: (data && !data.name) ? new Error("No name provided")
diff --git a/lib/cache/get-stat.js b/lib/cache/get-stat.js
new file mode 100644
index 000000000..5e9709731
--- /dev/null
+++ b/lib/cache/get-stat.js
@@ -0,0 +1,62 @@
+'use strict';
+/* jshint node: true */
+
+var fs = require("fs")
+
+var npm = require("../npm.js")
+var log = require("npmlog")
+var mkdir = require("mkdirp")
+var chownr = require("chownr")
+
+function makeCacheDir (cb) {
+ if (!process.getuid) return mkdir(npm.cache, cb)
+
+ var uid = +process.getuid()
+ , gid = +process.getgid()
+
+ if (uid === 0) {
+ if (process.env.SUDO_UID) uid = +process.env.SUDO_UID
+ if (process.env.SUDO_GID) gid = +process.env.SUDO_GID
+ }
+ if (uid !== 0 || !process.env.HOME) {
+ cacheStat = {uid: uid, gid: gid}
+ return mkdir(npm.cache, afterMkdir)
+ }
+
+ fs.stat(process.env.HOME, function (er, st) {
+ if (er) {
+ log.error("makeCacheDir", "homeless?")
+ return cb(er)
+ }
+ cacheStat = st
+ log.silly("makeCacheDir", "cache dir uid, gid", [st.uid, st.gid])
+ return mkdir(npm.cache, afterMkdir)
+ })
+
+ function afterMkdir (er, made) {
+ if (er || !cacheStat || isNaN(cacheStat.uid) || isNaN(cacheStat.gid)) {
+ return cb(er, cacheStat)
+ }
+
+ if (!made) return cb(er, cacheStat)
+
+ // ensure that the ownership is correct.
+ chownr(made, cacheStat.uid, cacheStat.gid, function (er) {
+ return cb(er, cacheStat)
+ })
+ }
+}
+
+// to maintain the cache dir's permissions consistently.
+var cacheStat = null
+module.exports = function getCacheStat (cb) {
+ if (cacheStat) return cb(null, cacheStat)
+ fs.stat(npm.cache, function (er, st) {
+ if (er) return makeCacheDir(cb)
+ if (!st.isDirectory()) {
+ log.error("getCacheStat", "invalid cache dir %j", npm.cache)
+ return cb(er)
+ }
+ return cb(null, cacheStat = st)
+ })
+}
diff --git a/lib/utils/locker.js b/lib/utils/locker.js
new file mode 100644
index 000000000..e3c8f2e80
--- /dev/null
+++ b/lib/utils/locker.js
@@ -0,0 +1,54 @@
+'use strict';
+/* jshint node: true */
+var crypto = require("crypto")
+var path = require("path")
+
+var npm = require("../npm.js")
+var lockFile = require("lockfile")
+var log = require("npmlog")
+var getCacheStat = require("../cache/get-stat.js")
+
+function lockFileName (u) {
+ var c = u.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "")
+ , h = crypto.createHash("sha1").update(u).digest("hex")
+ h = h.substr(0, 8)
+ c = c.substr(-32)
+ log.silly("lockFile", h + "-" + c, u)
+ return path.resolve(npm.config.get("cache"), h + "-" + c + ".lock")
+}
+
+var myLocks = {}
+function lock (u, cb) {
+ // the cache dir needs to exist already for this.
+ getCacheStat(function (er, cs) {
+ if (er) return cb(er)
+ var opts = { stale: npm.config.get("cache-lock-stale")
+ , retries: npm.config.get("cache-lock-retries")
+ , wait: npm.config.get("cache-lock-wait") }
+ var lf = lockFileName(u)
+ log.verbose("lock", u, lf)
+ lockFile.lock(lf, opts, function(er) {
+ if (!er) myLocks[lf] = true
+ cb(er)
+ })
+ })
+}
+
+function unlock (u, cb) {
+ var lf = lockFileName(u)
+ , locked = myLocks[lf]
+ if (locked === false) {
+ return process.nextTick(cb)
+ } else if (locked === true) {
+ myLocks[lf] = false
+ lockFile.unlock(lockFileName(u), cb)
+ } else {
+ throw new Error("Attempt to unlock " + u + ", which hasn't been locked")
+ }
+}
+
+module.exports = {
+ lock: lock,
+ unlock: unlock,
+ _lockFileName: lockFileName
+}
diff --git a/lib/utils/tar.js b/lib/utils/tar.js
index b73c134e4..3121bb028 100644
--- a/lib/utils/tar.js
+++ b/lib/utils/tar.js
@@ -8,7 +8,6 @@ var npm = require("../npm.js")
, uidNumber = require("uid-number")
, rm = require("./gently-rm.js")
, readJson = require("read-package-json")
- , cache = require("../cache.js")
, myUid = process.getuid && process.getuid()
, myGid = process.getgid && process.getgid()
, tar = require("tar")
@@ -16,13 +15,14 @@ var npm = require("../npm.js")
, fstream = require("fstream")
, Packer = require("fstream-npm")
, lifecycle = require("./lifecycle.js")
+ , locker = require("./locker.js")
function lock(path, cb) {
- return cache.lock('tar://' + path, cb)
+ return locker.lock('tar://' + path, cb)
}
function unlock(path, cb) {
- return cache.unlock('tar://' + path, cb)
+ return locker.unlock('tar://' + path, cb)
}
if (process.env.SUDO_UID && myUid === 0) {