"use strict"; /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ const Path = require('path'); const Fs = require('fs'); const ChildProcess = require('child_process'); const { promisify } = require('util'); const execAsync = promisify(ChildProcess.execFile); /** * @param {string} repoRoot * @param {string} output * @returns {Iterable} */ function parseLsFilesOutput(repoRoot, output) { const files = new Set(); for (const line of output.split('\n').map(l => l.trim())) { if (!line) { continue; } const repoRel = line.slice(2); // trim the single char status and separating space from the line if (line.startsWith('C ')) { // this line indicates that the previous path is changed in the working // tree, so we need to determine if it was deleted and remove it if so if (!Fs.existsSync(Path.resolve(repoRoot, repoRel))) { files.delete(repoRel); } } else { files.add(repoRel); } } return files; } /** * @param {string} repoRoot * @param {string[] | undefined} include * @param {string[] | undefined} exclude * @returns {string[]} */ function getGitFlags(repoRoot, include = undefined, exclude = undefined) { var _include$map, _exclude$map; return ['ls-files', '-comt', '--exclude-standard', (_include$map = include === null || include === void 0 ? void 0 : include.map(p => Path.isAbsolute(p) ? Path.relative(repoRoot, p) : p)) !== null && _include$map !== void 0 ? _include$map : [], (_exclude$map = exclude === null || exclude === void 0 ? void 0 : exclude.map(p => `--exclude=${Path.isAbsolute(p) ? Path.relative(repoRoot, p) : p}`)) !== null && _exclude$map !== void 0 ? _exclude$map : []].flat(); } /** * List the files in the repo, only including files which are manged by version * control or "untracked" (new, not committed, and not ignored). * @param {string} repoRoot limit the list to specfic absolute paths * @param {string[] | undefined} include limit the list to specfic absolute paths * @param {string[] | undefined} exclude exclude specific absolute paths * @returns {Promise>} */ async function getRepoRels(repoRoot, include = undefined, exclude = undefined) { const proc = await execAsync('git', getGitFlags(repoRoot, include, exclude), { cwd: repoRoot, encoding: 'utf8', maxBuffer: Infinity }); return parseLsFilesOutput(repoRoot, proc.stdout); } /** * Synchronously list the files in the repo, only including files which are manged by version * control or "untracked" (new, not committed, and not ignored). * @param {string} repoRoot limit the list to specfic absolute paths * @param {string[] | undefined} include limit the list to specfic absolute paths * @param {string[] | undefined} exclude exclude specific absolute paths * @returns {Iterable} */ function getRepoRelsSync(repoRoot, include = undefined, exclude = undefined) { const stdout = ChildProcess.execFileSync('git', getGitFlags(repoRoot, include, exclude), { cwd: repoRoot, encoding: 'utf8' }); return parseLsFilesOutput(repoRoot, stdout); } module.exports = { getRepoRels, getRepoRelsSync };