'use strict'; //core import * as assert from 'assert'; import * as path from 'path'; import * as fs from 'fs'; //npm import async = require('async'); import chalk from 'chalk'; // project import log from '../../logging'; import {EVCb, NLUAddOpts} from "../../index"; //////////////////////////////////////////////////////////////// export const makeFindProjects = function (mainProjectName: string, ignore: Array, opts: NLUAddOpts, map: any, toAdd: Array, status: any) { let isIgnored = function (pth: string) { return ignore.some(r => { if (r.test(pth)) { if (opts.verbosity > 2) { log.warning(`Path with value "${pth}" was ignored because it matched the following regex:`); log.warning(`${r}`); } return true; } }); }; return function findProject(item: string, cb: EVCb) { item = path.normalize(item); log.good('new path being searched:', chalk.blue(item)); (function getMarkers(dir, cb) { if (status.searching === false) { return process.nextTick(cb); } if (isIgnored(String(dir + '/'))) { if (opts.verbosity > 2) { log.warning('path ignored => ', dir); } return process.nextTick(cb); } fs.readdir(dir, function (err, items) { if (err) { log.warn('Could not read a directory at path:', dir); log.warn(err.message || err); if (String(err.message || err).match(/permission denied/)) { return cb(null); } return cb(err); } if (status.searching === false) { return process.nextTick(cb); } items = items.map(function (item) { return path.resolve(dir, item); }); async.eachLimit(items, 3, function (item: string, cb: EVCb) { if (isIgnored(String(item))) { if (opts.verbosity > 2) { log.warning('path ignored => ', item); } return process.nextTick(cb); } fs.lstat(item, function (err, stats) { if (err) { opts.verbosity > 2 && log.warning('warning => maybe a symlink? => ', err.message || err); return cb(null); } if (status.searching === false) { return process.nextTick(cb); } if (stats.isSymbolicLink()) { opts.verbosity > 2 && log.warning('warning => looks like a symlink => ', item); return cb(); } if (stats.isDirectory()) { if (isIgnored(String(item + '/'))) { if (opts.verbosity > 2) { opts.verbosity > 2 && log.warning('path ignored by settings/regex => ', item); } cb(null); } else { // continue drilling down getMarkers(item, cb); } return; } if (!stats.isFile()) { opts.verbosity > 2 && log.warning('Not a directory or file (maybe a symlink?) => ', item); return cb(null); } let dirname = path.dirname(item); let filename = path.basename(item); if (String(filename) !== 'package.json') { return cb(null); } let pkg: any, nluIsLink1 = true; try { pkg = require(item); nluIsLink1 = !(pkg.nlu && pkg.nlu.linkable === false) } catch (err) { return cb(err); } let npmlinkup: any, nluIsLink2 = true; try { npmlinkup = require(path.resolve(dirname + '/.nlu.json')); nluIsLink2 = npmlinkup['npm-link-up'] !== false } catch (e) { //ignore } const index = toAdd.indexOf(pkg.name); const isAdd = index > -1; if (isAdd && nluIsLink1 && nluIsLink2) { // remove the item, because we found it toAdd.splice(index, 1); if (toAdd.length < 1) { // we are done searching status.searching = false; } log.good('We found a relevant project:', chalk.blueBright.bold(pkg.name), ', at path:', chalk.gray.bold(dirname)); const helpLink = 'https://github.com/ORESoftware/npm-link-up/tree/master/docs/easy-duplicate-package-mitigation.md'; if (map[pkg.name]) { // this pkg.name is already in the map! log.warn('The following package name exists in multiple package.json files on your fs:', pkg.name); return cb(new Error(`Multiple packages with name "${pkg.name}", to easily mitigate this problem see: ${chalk.blueBright(helpLink)}.`)) } map[pkg.name] = { name: pkg.name, isMainProject: pkg.name === mainProjectName, path: dirname, deps: npmlinkup && npmlinkup.list || [] }; } cb(null); }); }, cb); }); })(item, cb); } };