diff --git a/packages/providence-analytics/src/cli/cli-helpers.js b/packages/providence-analytics/src/cli/cli-helpers.js index 391a97022..e97e3c714 100644 --- a/packages/providence-analytics/src/cli/cli-helpers.js +++ b/packages/providence-analytics/src/cli/cli-helpers.js @@ -6,6 +6,7 @@ const readPackageTree = require('../program/utils/read-package-tree-with-bower-s const { InputDataService } = require('../program/services/InputDataService.js'); const { LogService } = require('../program/services/LogService.js'); const { aForEach } = require('../program/utils/async-array-utils.js'); +const { toPosixPath } = require('../program/utils/to-posix-path.js'); function flatten(arr) { return Array.prototype.concat.apply([], arr); @@ -47,9 +48,9 @@ function pathsArrayFromCs(t, cwd = process.cwd()) { // eslint-disable-next-line no-param-reassign t = `${t}/`; } - return glob.sync(t, { cwd, absolute: true }); + return glob.sync(t, { cwd, absolute: true }).map(toPosixPath); } - return pathLib.resolve(cwd, t.trim()); + return toPosixPath(pathLib.resolve(cwd, t.trim())); }), ); } @@ -144,7 +145,7 @@ async function appendProjectDependencyPaths(rootPaths, matchPattern, modes = ['n // depProjectPaths.filter(depP => depP.startsWith(rootP)).; // }); - return depProjectPaths.concat(rootPaths); + return depProjectPaths.concat(rootPaths).map(toPosixPath); } async function installDeps(searchTargetPaths) { diff --git a/packages/providence-analytics/src/cli/cli.js b/packages/providence-analytics/src/cli/cli.js index be7d4f7b8..b943d86d0 100755 --- a/packages/providence-analytics/src/cli/cli.js +++ b/packages/providence-analytics/src/cli/cli.js @@ -11,6 +11,7 @@ const { InputDataService } = require('../program/services/InputDataService.js'); const promptModule = require('./prompt-analyzer-menu.js'); const cliHelpers = require('./cli-helpers.js'); const extendDocsModule = require('./generate-extend-docs-data.js'); +const { toPosixPath } = require('../program/utils/to-posix-path.js'); const { extensionsFromCs, setQueryMethod, targetDefault, installDeps } = cliHelpers; @@ -282,7 +283,7 @@ async function cli({ cwd } = {}) { .option( '--output-folder [output-folder]', `This is the file path where the result file "providence-extend-docs-data.json" will be written to`, - p => pathLib.resolve(process.cwd(), p.trim()), + p => toPosixPath(pathLib.resolve(process.cwd(), p.trim())), process.cwd(), ) .action(options => { diff --git a/packages/providence-analytics/src/program/analyzers/helpers/Analyzer.js b/packages/providence-analytics/src/program/analyzers/helpers/Analyzer.js index e71811189..45508c6a9 100644 --- a/packages/providence-analytics/src/program/analyzers/helpers/Analyzer.js +++ b/packages/providence-analytics/src/program/analyzers/helpers/Analyzer.js @@ -7,6 +7,7 @@ const { QueryService } = require('../../services/QueryService.js'); const { ReportService } = require('../../services/ReportService.js'); const { InputDataService } = require('../../services/InputDataService.js'); const { aForEach } = require('../../utils/async-array-utils.js'); +const { toPosixPath } = require('../../utils/to-posix-path.js'); const { getFilePathRelativeFromRoot } = require('../../utils/get-file-path-relative-from-root.js'); /** @@ -27,6 +28,29 @@ async function analyzePerAstEntry(projectData, astAnalysis) { return filteredEntries; } +/** + * Transforms QueryResult entries to posix path notations on Windows + * @param {array|object} data + */ +function posixify(data) { + if (!data) { + return; + } + if (Array.isArray(data)) { + data.forEach(posixify); + } else if (typeof data === 'object') { + Object.entries(data).forEach(([k, v]) => { + if (Array.isArray(v) || typeof v === 'object') { + posixify(v); + } + // TODO: detect whether filePath instead of restricting by key name? + else if (typeof v === 'string' && k === 'file') { + data[k] = toPosixPath(v); + } + }); + } +} + /** * @desc This method ensures that the result returned by an analyzer always has a consistent format. * By returning the configuration for the queryOutput, it will be possible to run later queries @@ -81,6 +105,11 @@ function ensureAnalyzerResultFormat(queryOutput, configuration, analyzer) { } }); } + + if (process.platform === 'win32') { + posixify(aResult); + } + return aResult; } diff --git a/packages/providence-analytics/src/program/analyzers/helpers/normalize-source-paths.js b/packages/providence-analytics/src/program/analyzers/helpers/normalize-source-paths.js index 79dcf0926..91c9868c4 100644 --- a/packages/providence-analytics/src/program/analyzers/helpers/normalize-source-paths.js +++ b/packages/providence-analytics/src/program/analyzers/helpers/normalize-source-paths.js @@ -6,6 +6,7 @@ const { } = require('../../utils/relative-source-path.js'); const { resolveImportPath } = require('../../utils/resolve-import-path.js'); const { aMap } = require('../../utils/async-array-utils.js'); +const { toPosixPath } = require('../../utils/to-posix-path.js'); function toLocalPath(currentDirPath, resolvedPath) { let relativeSourcePath = pathLib.relative(currentDirPath, resolvedPath); @@ -15,7 +16,7 @@ function toLocalPath(currentDirPath, resolvedPath) { // so 'my-local-files.js' -> './my-local-files.js' relativeSourcePath = `./${relativeSourcePath}`; } - return relativeSourcePath; + return toPosixPath(relativeSourcePath); } /** diff --git a/packages/providence-analytics/src/program/services/InputDataService.js b/packages/providence-analytics/src/program/services/InputDataService.js index d44849944..037710f8c 100644 --- a/packages/providence-analytics/src/program/services/InputDataService.js +++ b/packages/providence-analytics/src/program/services/InputDataService.js @@ -4,6 +4,7 @@ require('../types/index.js'); const fs = require('fs'); const pathLib = require('path'); + const child_process = require('child_process'); // eslint-disable-line camelcase const glob = require('glob'); const anymatch = require('anymatch'); @@ -11,6 +12,7 @@ const isNegatedGlob = require('is-negated-glob'); const { LogService } = require('./LogService.js'); const { AstService } = require('./AstService.js'); const { getFilePathRelativeFromRoot } = require('../utils/get-file-path-relative-from-root.js'); +const { toPosixPath } = require('../utils/to-posix-path.js'); function getGitignoreFile(rootPath) { try { @@ -39,7 +41,7 @@ function getGitIgnorePaths(rootPath) { // normalize entries to be compatible with anymatch const normalizedEntries = entries.map(e => { - let entry = e; + let entry = toPosixPath(e); if (entry.startsWith('/')) { entry = entry.slice(1); @@ -87,11 +89,11 @@ function ensureArray(v) { return Array.isArray(v) ? v : [v]; } -function multiGlobSync(patterns, { keepDirs = false } = {}) { +function multiGlobSync(patterns, { keepDirs = false, root } = {}) { patterns = ensureArray(patterns); const res = new Set(); patterns.forEach(pattern => { - const files = glob.sync(pattern); + const files = glob.sync(pattern, { root }); files.forEach(filePath => { if (fs.lstatSync(filePath).isDirectory() && !keepDirs) { return; @@ -211,7 +213,10 @@ class InputDataService { const newEntries = []; projectObj.entries.forEach(entry => { const code = fs.readFileSync(entry, 'utf8'); - const file = getFilePathRelativeFromRoot(entry, projectObj.project.path); + const file = getFilePathRelativeFromRoot( + toPosixPath(entry), + toPosixPath(projectObj.project.path), + ); if (pathLib.extname(file) === '.html') { const extractedScripts = AstService.getScriptsFromHtml(code); // eslint-disable-next-line no-shadow @@ -223,7 +228,7 @@ class InputDataService { } }); - const project = this.getProjectMeta(projectObj.project.path); + const project = this.getProjectMeta(toPosixPath(projectObj.project.path)); return { project, entries: newEntries }; }); @@ -289,6 +294,11 @@ class InputDataService { static getGlobPattern(startPath, cfg, withoutDepth = false) { // if startPath ends with '/', remove let globPattern = startPath.replace(/\/$/, ''); + // let globPattern = ''; + if (process.platform === 'win32') { + // root = root.replace(/^.\:/, '').replace(/\\/g, '/'); + globPattern = globPattern.replace(/^.:/, '').replace(/\\/g, '/'); + } if (!withoutDepth) { if (cfg.depth !== Infinity) { globPattern += `/*`.repeat(cfg.depth + 1); @@ -296,7 +306,8 @@ class InputDataService { globPattern += `/**/*`; } } - return globPattern; + // globPattern = globPattern.slice(1) + return { globPattern }; } /** @@ -350,14 +361,14 @@ class InputDataService { } }); - let globPattern = this.getGlobPattern(startPath, cfg); + let { globPattern } = this.getGlobPattern(startPath, cfg); globPattern += `.{${cfg.extensions.map(e => e.slice(1)).join(',')},}`; const globRes = multiGlobSync(globPattern); let filteredGlobRes; if (removeFilter.length || keepFilter.length) { filteredGlobRes = globRes.filter(filePath => { - const localFilePath = filePath.replace(`${startPath}/`, ''); + const localFilePath = toPosixPath(filePath).replace(`${toPosixPath(startPath)}/`, ''); let shouldRemove = removeFilter.length && anymatch(removeFilter, localFilePath); let shouldKeep = keepFilter.length && anymatch(keepFilter, localFilePath); @@ -382,10 +393,14 @@ class InputDataService { return shouldKeep; }); } + if (!filteredGlobRes || !filteredGlobRes.length) { LogService.warn(`No files found for path '${startPath}'`); } - return filteredGlobRes; + + // reappend startPath + // const res = filteredGlobRes.map(f => pathLib.resolve(startPath, f)); + return filteredGlobRes.map(toPosixPath); } /** diff --git a/packages/providence-analytics/src/program/utils/relative-source-path.js b/packages/providence-analytics/src/program/utils/relative-source-path.js index b7cc8a1b6..74bfcd6c3 100644 --- a/packages/providence-analytics/src/program/utils/relative-source-path.js +++ b/packages/providence-analytics/src/program/utils/relative-source-path.js @@ -1,3 +1,5 @@ +const { toPosixPath } = require('./to-posix-path.js'); + /** * @desc determines for a source path of an import- or export specifier, whether * it is relative (an internal import/export) or absolute (external) @@ -18,7 +20,7 @@ function isRelativeSourcePath(source) { * @param {string} rootPath like '/path/to/repo' */ function toRelativeSourcePath(fullPath, rootPath) { - return fullPath.replace(rootPath, '.'); + return toPosixPath(fullPath).replace(rootPath, '.'); } module.exports = { isRelativeSourcePath, toRelativeSourcePath }; diff --git a/packages/providence-analytics/src/program/utils/to-posix-path.js b/packages/providence-analytics/src/program/utils/to-posix-path.js new file mode 100644 index 000000000..7d763285e --- /dev/null +++ b/packages/providence-analytics/src/program/utils/to-posix-path.js @@ -0,0 +1,12 @@ +/** + * @param {string} pathStr C:\Example\path/like/this + * returns {string} /Example/path/like/this + */ +function toPosixPath(pathStr) { + if (process.platform === 'win32') { + return pathStr.replace(/^.:/, '').replace(/\\/g, '/'); + } + return pathStr; +} + +module.exports = { toPosixPath }; diff --git a/packages/providence-analytics/test-node/cli/cli.test.js b/packages/providence-analytics/test-node/cli/cli.test.js index fbd067483..377e71f3f 100644 --- a/packages/providence-analytics/test-node/cli/cli.test.js +++ b/packages/providence-analytics/test-node/cli/cli.test.js @@ -21,6 +21,7 @@ const extendDocsModule = require('../../src/cli/generate-extend-docs-data.js'); const cliHelpersModule = require('../../src/cli/cli-helpers.js'); const { cli } = require('../../src/cli/cli.js'); const promptAnalyzerModule = require('../../src/cli/prompt-analyzer-menu.js'); +const { toPosixPath } = require('../../src/program/utils/to-posix-path.js'); const { pathsArrayFromCs, @@ -29,7 +30,8 @@ const { } = cliHelpersModule; const queryResults = []; -const rootDir = pathLib.resolve(__dirname, '../../'); + +const rootDir = toPosixPath(pathLib.resolve(__dirname, '../../')); const externalCfgMock = { searchTargetCollections: { @@ -429,7 +431,7 @@ describe('CLI helpers', () => { pathsArrayFromCollectionName('lion-collection', 'search-target', externalCfgMock, rootDir), ).to.eql( externalCfgMock.searchTargetCollections['lion-collection'].map(p => - pathLib.join(rootDir, p), + toPosixPath(pathLib.join(rootDir, p)), ), ); }); @@ -444,7 +446,7 @@ describe('CLI helpers', () => { ), ).to.eql( externalCfgMock.referenceCollections['lion-based-ui-collection'].map(p => - pathLib.join(rootDir, p), + toPosixPath(pathLib.join(rootDir, p)), ), ); });