mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-26 01:33:02 +00:00
add getGitSuperProjectRoot API
This commit is contained in:
parent
3b0abf4d68
commit
e5f67712ec
|
|
@ -16,6 +16,7 @@ import {
|
|||
getGitLastUpdate,
|
||||
getGitCreation,
|
||||
getGitRepoRoot,
|
||||
getGitSuperProjectRoot,
|
||||
} from '../gitUtils';
|
||||
|
||||
class Git {
|
||||
|
|
@ -95,6 +96,54 @@ class Git {
|
|||
{env: {GIT_COMMITTER_DATE: `${date}T00:00:00Z`}},
|
||||
);
|
||||
}
|
||||
|
||||
async commitFile(
|
||||
filePath: string,
|
||||
{
|
||||
fileContent,
|
||||
commitMessage,
|
||||
commitDate,
|
||||
commitAuthor,
|
||||
}: {
|
||||
fileContent?: string;
|
||||
commitMessage?: string;
|
||||
commitDate?: string;
|
||||
commitAuthor?: string;
|
||||
} = {},
|
||||
): Promise<void> {
|
||||
await fs.ensureDir(path.join(this.dir, path.dirname(filePath)));
|
||||
await fs.writeFile(
|
||||
path.join(this.dir, filePath),
|
||||
fileContent ?? `Content of ${filePath}`,
|
||||
);
|
||||
await this.commit(
|
||||
commitMessage ?? `Create ${filePath}`,
|
||||
commitDate ?? '2020-06-19',
|
||||
commitAuthor ?? 'Seb <seb@example.com>',
|
||||
);
|
||||
}
|
||||
|
||||
async addSubmodule(name: string, repoPath: string): Promise<void> {
|
||||
return this.runOptimisticGitCommand('git', [
|
||||
'-c protocol.file.allow=always',
|
||||
'submodule',
|
||||
'add',
|
||||
repoPath,
|
||||
name,
|
||||
]);
|
||||
}
|
||||
|
||||
async defineSubmodules(submodules: {[name: string]: string}): Promise<void> {
|
||||
for (const entry of Object.entries(submodules)) {
|
||||
await this.addSubmodule(entry[0], entry[1]);
|
||||
}
|
||||
await this.runOptimisticGitCommand('git', [
|
||||
'submodule',
|
||||
'update',
|
||||
'--init',
|
||||
'--recursive',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
async function createGitRepoEmpty(): Promise<{repoDir: string; git: Git}> {
|
||||
|
|
@ -348,3 +397,91 @@ describe('getGitRepoRoot', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('submodules APIs', () => {
|
||||
async function initTestRepo() {
|
||||
const superproject = await createGitRepoEmpty();
|
||||
await superproject.git.commitFile('README.md');
|
||||
await superproject.git.commitFile('website/docs/myDoc.md');
|
||||
|
||||
const submodule1 = await createGitRepoEmpty();
|
||||
await submodule1.git.commitFile('file1.txt');
|
||||
|
||||
const submodule2 = await createGitRepoEmpty();
|
||||
await submodule2.git.commitFile('subDir/file2.txt');
|
||||
|
||||
await superproject.git.defineSubmodules({
|
||||
'submodules/submodule1': submodule1.repoDir,
|
||||
'submodules/submodule2': submodule2.repoDir,
|
||||
});
|
||||
|
||||
return {superproject, submodule1, submodule2};
|
||||
}
|
||||
|
||||
describe('getGitSuperProjectRoot', () => {
|
||||
it('returns superproject dir for cwd=superproject', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(repo.superproject.repoDir);
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns superproject dir for cwd=superproject/submodules', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(repo.superproject.repoDir, 'submodules');
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns superproject dir for cwd=superproject/website/docs', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(repo.superproject.repoDir, 'website/docs');
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns superproject dir for cwd=submodule1', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(repo.superproject.repoDir, 'submodules/submodule1');
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns superproject dir for cwd=submodule2', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(repo.superproject.repoDir, 'submodules/submodule2');
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns superproject dir for cwd=submodule2/subDir', async () => {
|
||||
const repo = await initTestRepo();
|
||||
const cwd = path.join(
|
||||
repo.superproject.repoDir,
|
||||
'submodules/submodule2/subDir',
|
||||
);
|
||||
await expect(getGitSuperProjectRoot(cwd)).resolves.toEqual(
|
||||
repo.superproject.repoDir,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects for cwd of untracked dir', async () => {
|
||||
const cwd = await os.tmpdir();
|
||||
|
||||
// Do we really want this to throw?
|
||||
// Not sure, and Git doesn't help us failsafe and return null...
|
||||
await expect(getGitSuperProjectRoot(cwd)).rejects
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Couldn't find the git superproject root directory
|
||||
Failure while running \`git rev-parse --show-superproject-working-tree\` from cwd="<TEMP_DIR>"
|
||||
The command executed throws an error: Command failed with exit code 128: git rev-parse --show-superproject-working-tree
|
||||
fatal: not a git repository (or any of the parent directories): .git"
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -265,9 +265,9 @@ export async function getGitCreation(
|
|||
export async function getGitRepoRoot(cwd: string): Promise<string> {
|
||||
const createErrorMessageBase = () => {
|
||||
return `Couldn't find the git repository root directory
|
||||
Running ${logger.code('git rev-parse --show-toplevel')} from cwd=${logger.path(
|
||||
cwd,
|
||||
)})`;
|
||||
Failure while running ${logger.code(
|
||||
'git rev-parse --show-toplevel',
|
||||
)} from cwd=${logger.path(cwd)}`;
|
||||
};
|
||||
|
||||
const result = await execa('git', ['rev-parse', '--show-toplevel'], {
|
||||
|
|
@ -276,7 +276,7 @@ Running ${logger.code('git rev-parse --show-toplevel')} from cwd=${logger.path(
|
|||
// We enter this rejection when cwd is not a dir for example
|
||||
throw new Error(
|
||||
`${createErrorMessageBase()}
|
||||
The command executed throws an error`,
|
||||
The command executed throws an error: ${error.message}`,
|
||||
{cause: error},
|
||||
);
|
||||
});
|
||||
|
|
@ -292,3 +292,49 @@ The command returned exit code ${logger.code(result.exitCode)}: ${logger.subdue(
|
|||
|
||||
return fs.realpath.native(result.stdout.trim());
|
||||
}
|
||||
|
||||
// A Git "superproject" is a Git repository that contains submodules
|
||||
// See https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---show-superproject-working-tree
|
||||
// See https://git-scm.com/book/en/v2/Git-Tools-Submodules
|
||||
export async function getGitSuperProjectRoot(
|
||||
cwd: string,
|
||||
): Promise<string | null> {
|
||||
const createErrorMessageBase = () => {
|
||||
return `Couldn't find the git superproject root directory
|
||||
Failure while running ${logger.code(
|
||||
'git rev-parse --show-superproject-working-tree',
|
||||
)} from cwd=${logger.path(cwd)}`;
|
||||
};
|
||||
|
||||
const result = await execa(
|
||||
'git',
|
||||
['rev-parse', '--show-superproject-working-tree'],
|
||||
{
|
||||
cwd,
|
||||
},
|
||||
).catch((error) => {
|
||||
// We enter this rejection when cwd is not a dir for example
|
||||
throw new Error(
|
||||
`${createErrorMessageBase()}
|
||||
The command executed throws an error: ${error.message}`,
|
||||
{cause: error},
|
||||
);
|
||||
});
|
||||
|
||||
if (result.exitCode !== 0) {
|
||||
throw new Error(
|
||||
`${createErrorMessageBase()}
|
||||
The command returned exit code ${logger.code(result.exitCode)}: ${logger.subdue(
|
||||
result.stderr,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
const output = result.stdout.trim();
|
||||
// this command only works when inside submodules
|
||||
// otherwise it doesn't return anything when we are inside the main repo
|
||||
if (output) {
|
||||
return output;
|
||||
}
|
||||
return getGitRepoRoot(cwd);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue