add getGitAllRepoRoots API

This commit is contained in:
sebastien 2025-11-07 16:08:19 +01:00
parent d243079036
commit df568926f9
2 changed files with 99 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import {
getGitRepoRoot,
getGitSuperProjectRoot,
getGitSubmodulePaths,
getGitAllRepoRoots,
} from '../gitUtils';
class Git {
@ -548,4 +549,80 @@ describe('submodules APIs', () => {
);
});
});
describe('getGitAllRepoRoots', () => {
it('returns root paths for cwd=superproject', async () => {
const repo = await initTestRepo();
const cwd = path.join(repo.superproject.repoDir);
await expect(getGitAllRepoRoots(cwd)).resolves.toEqual([
repo.superproject.repoDir,
path.join(repo.superproject.repoDir, 'submodules', 'submodule1'),
path.join(repo.superproject.repoDir, 'submodules', 'submodule2'),
]);
});
it('returns root paths for cwd=superproject/website/docs', async () => {
const repo = await initTestRepo();
const cwd = path.join(repo.superproject.repoDir, 'website', 'docs');
await expect(getGitAllRepoRoots(cwd)).resolves.toEqual([
repo.superproject.repoDir,
path.join(repo.superproject.repoDir, 'submodules', 'submodule1'),
path.join(repo.superproject.repoDir, 'submodules', 'submodule2'),
]);
});
it('returns root paths for cwd=superproject/submodules', async () => {
const repo = await initTestRepo();
const cwd = path.join(repo.superproject.repoDir, 'submodules');
await expect(getGitAllRepoRoots(cwd)).resolves.toEqual([
repo.superproject.repoDir,
path.join(repo.superproject.repoDir, 'submodules', 'submodule1'),
path.join(repo.superproject.repoDir, 'submodules', 'submodule2'),
]);
});
it('returns root paths for cwd=superproject/submodules/submodule1', async () => {
const repo = await initTestRepo();
const cwd = path.join(
repo.superproject.repoDir,
'submodules',
'submodule1',
);
await expect(getGitAllRepoRoots(cwd)).resolves.toEqual([
repo.superproject.repoDir,
path.join(repo.superproject.repoDir, 'submodules', 'submodule1'),
path.join(repo.superproject.repoDir, 'submodules', 'submodule2'),
]);
});
it('returns root paths for cwd=superproject/submodules/submodule2/subDir', async () => {
const repo = await initTestRepo();
const cwd = path.join(
repo.superproject.repoDir,
'submodules',
'submodule2',
'subDir',
);
await expect(getGitAllRepoRoots(cwd)).resolves.toEqual([
repo.superproject.repoDir,
path.join(repo.superproject.repoDir, 'submodules', 'submodule1'),
path.join(repo.superproject.repoDir, 'submodules', 'submodule2'),
]);
});
it('rejects for cwd=doesNotExist', async () => {
const repo = await initTestRepo();
const cwd = path.join(repo.superproject.repoDir, 'doesNotExist');
await expect(getGitAllRepoRoots(cwd)).rejects.toThrow(
/Could not get all the git repository root paths/,
);
});
it('rejects for cwd=notTracked', async () => {
const cwd = await os.tmpdir();
await expect(getGitAllRepoRoots(cwd)).rejects.toThrow(
/Could not get all the git repository root paths/,
);
});
});
});

View File

@ -390,3 +390,25 @@ The command returned exit code ${logger.code(result.exitCode)}: ${logger.subdue(
return Promise.all(output.split('\n').map(getSubmodulePath));
}
// Find the root git repository alongside all its submodules, if any
export async function getGitAllRepoRoots(cwd: string): Promise<string[]> {
try {
const superProjectRoot = await getGitSuperProjectRoot(cwd);
if (!superProjectRoot) {
return [];
}
let submodulePaths = await getGitSubmodulePaths(superProjectRoot);
submodulePaths = await Promise.all(
submodulePaths.map((submodulePath) =>
fs.realpath.native(path.resolve(superProjectRoot, submodulePath)),
),
);
return [superProjectRoot, ...submodulePaths];
} catch (error) {
throw new Error(
`Could not get all the git repository root paths (superproject + submodules) from cwd=${cwd}`,
{cause: error},
);
}
}