• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 var crypto = require('crypto')
2 var resolve = require('path').resolve
3 
4 var lockfile = require('lockfile')
5 var log = require('npmlog')
6 
7 var npm = require('../npm.js')
8 var correctMkdir = require('../utils/correct-mkdir.js')
9 
10 var installLocks = {}
11 
12 function lockFileName (base, name) {
13   var c = name.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '')
14   var p = resolve(base, name)
15   var h = crypto.createHash('sha1').update(p).digest('hex')
16   var l = resolve(npm.cache, '_locks')
17 
18   return resolve(l, c.substr(0, 24) + '-' + h.substr(0, 16) + '.lock')
19 }
20 
21 function lock (base, name, cb) {
22   var lockDir = resolve(npm.cache, '_locks')
23   correctMkdir(lockDir, function (er) {
24     if (er) return cb(er)
25 
26     var opts = {
27       stale: npm.config.get('cache-lock-stale'),
28       retries: npm.config.get('cache-lock-retries'),
29       wait: npm.config.get('cache-lock-wait')
30     }
31     var lf = lockFileName(base, name)
32     lockfile.lock(lf, opts, function (er) {
33       if (er) log.warn('locking', lf, 'failed', er)
34 
35       if (!er) {
36         log.verbose('lock', 'using', lf, 'for', resolve(base, name))
37         installLocks[lf] = true
38       }
39 
40       cb(er)
41     })
42   })
43 }
44 
45 function unlock (base, name, cb) {
46   var lf = lockFileName(base, name)
47   var locked = installLocks[lf]
48   if (locked === false) {
49     return process.nextTick(cb)
50   } else if (locked === true) {
51     lockfile.unlock(lf, function (er) {
52       if (er) {
53         log.warn('unlocking', lf, 'failed', er)
54       } else {
55         installLocks[lf] = false
56         log.verbose('unlock', 'done using', lf, 'for', resolve(base, name))
57       }
58 
59       cb(er)
60     })
61   } else {
62     var notLocked = new Error(
63       'Attempt to unlock ' + resolve(base, name) + ", which hasn't been locked"
64     )
65     notLocked.code = 'ENOTLOCKED'
66     throw notLocked
67   }
68 }
69 
70 module.exports = {
71   lock: lock,
72   unlock: unlock
73 }
74