1'use strict' 2var path = require('path') 3var log = require('npmlog') 4var validate = require('aproba') 5var uniq = require('lodash.uniq') 6var asyncMap = require('slide').asyncMap 7var npm = require('../npm.js') 8var exists = require('./exists.js') 9var writable = require('./writable.js') 10 11module.exports = function (actions, next) { 12 validate('AF', arguments) 13 var errors = [] 14 asyncMap(actions, function (action, done) { 15 var cmd = action[0] 16 var pkg = action[1] 17 switch (cmd) { 18 case 'add': 19 hasAnyWriteAccess(path.resolve(pkg.path, '..'), errors, done) 20 break 21 case 'update': 22 case 'remove': 23 hasWriteAccess(pkg.path, errors, andHasWriteAccess(path.resolve(pkg.path, '..'), errors, done)) 24 break 25 case 'move': 26 hasAnyWriteAccess(pkg.path, errors, andHasWriteAccess(path.resolve(pkg.fromPath, '..'), errors, done)) 27 break 28 default: 29 done() 30 } 31 }, function () { 32 if (!errors.length) return next() 33 uniq(errors.map(function (er) { return 'Missing write access to ' + er.path })).forEach(function (er) { 34 log.warn('checkPermissions', er) 35 }) 36 npm.config.get('force') ? next() : next(errors[0]) 37 }) 38} 39 40function andHasWriteAccess (dir, errors, done) { 41 validate('SAF', arguments) 42 return function () { 43 hasWriteAccess(dir, errors, done) 44 } 45} 46 47function hasAnyWriteAccess (dir, errors, done) { 48 validate('SAF', arguments) 49 findNearestDir() 50 function findNearestDir () { 51 var nextDir = path.resolve(dir, '..') 52 exists(dir, function (dirDoesntExist) { 53 if (!dirDoesntExist || nextDir === dir) { 54 return hasWriteAccess(dir, errors, done) 55 } else { 56 dir = nextDir 57 findNearestDir() 58 } 59 }) 60 } 61} 62 63function hasWriteAccess (dir, errors, done) { 64 validate('SAF', arguments) 65 writable(dir, function (er) { 66 if (er) errors.push(er) 67 done() 68 }) 69} 70