function getDependencies (manifest, opts, cb) {
  manifest = manifest || {}

  // Allow callback to be passed as second parameter
  if (!cb) {
    cb = opts
    opts = {}
  } else {
    opts = opts || {}
  }

  opts.error = opts.error || {}
  opts.ignore = opts.ignore || []

  if (manifest.david && manifest.david.ignore) {
    opts.ignore = opts.ignore.concat(manifest.david.ignore)
  }

  var pkgs = {}
  var deps = normaliseDeps(manifest[depType(opts)] || {})
  var depNames = Object.keys(deps)
  var error // Return any error that occurred but don't stop processing

  if (!depNames.length) {
    return setImmediate(function () { cb(null, pkgs) })
  }

  var tasks = depNames.map(function (depName) {
    return function (cb) {
      if (multimatch(depName, opts.ignore).length > 0) {
        return cb()
      }

      var err

      if (Object.prototype.toString.call(deps[depName]) !== '[object String]') {
        err = new Error('Non-string dependency: ' + deps[depName])
        err.code = 'EDEPTYPE'

        if (!opts.error.EDEPTYPE) {
          pkgs[depName] = { required: deps[depName], warn: err }
        } else {
          error = err
        }

        return cb()
      }

      if (Version.isScm(deps[depName])) {
        err = new Error('SCM dependency: ' + deps[depName])
        err.code = 'ESCM'

        if (!opts.error.ESCM) {
          pkgs[depName] = { required: deps[depName], warn: err }
        } else {
          error = err
        }
        return cb()
      }

      Npm.getVersionsInfo(depName, opts, function (err, versionsInfo) {
        if (err) {
          if (!opts.error.E404 && err.code === 'E404') {
            if (err === '404 Not Found') {
              err = new Error('404 Not Found: ' + depName)
              err.pkgid = depName
              err.statusCode = 404
              err.code = 'E404'
            }

            pkgs[depName] = { required: deps[depName], warn: err }
          } else {
            error = err
          }
          return cb()
        }

        try {
          var latestVersionInfo = Version.getLatest(versionsInfo.current, versionsInfo.versions, opts)

          pkgs[depName] = {
            required: deps[depName],
            stable: latestVersionInfo.stable,
            latest: latestVersionInfo.latest
          }

          if (opts.versions) {
            pkgs[depName].versions = versionsInfo.versions
          }

          if (opts.rangeVersions) {
            pkgs[depName].rangeVersions = Version.getVersionsInRange(deps[depName], versionsInfo.versions, opts.loose)
          }
        } catch (err) {
          error = err
        }

        cb()
      })
    }
  })

  parallel(tasks, function () { cb(error, pkgs) })
}
Get a list of dependencies for the passed manifest.
@param {Object} manifest Parsed package.json file contents
@param {Object|Function} [opts] Options or callback
@param {Boolean} [opts.dev] Consider devDependencies
@param {Boolean} [opts.optional] Consider optionalDependencies
@param {Boolean} [opts.peer] Consider peerDependencies
@param {Boolean} [opts.loose] Use loose option when querying semver
@param {Object} [opts.npm] npm configuration options
@param {Boolean} [opts.error.E404] Error on 404s
@param {Boolean} [opts.versions] For each dependency, return the available versions
@param {Boolean} [opts.rangeVersions] For each dependency, return the available versions for the range specified in the package.json
@param {Array} [opts.ignore] List of dependency names or globs to ignore
@param {Function} cb Function that receives the results