Add support for running create-astro in cloned empty git repository (#4805)

This commit is contained in:
HiDeoo 2022-09-20 14:30:13 +02:00 committed by GitHub
parent f2b515d0b4
commit c84d85ba4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 6 deletions

View file

@ -0,0 +1,5 @@
---
'create-astro': patch
---
Add support for running in cloned empty git repository

View file

@ -43,6 +43,46 @@ function isEmpty(dirPath: string) {
return !fs.existsSync(dirPath) || fs.readdirSync(dirPath).length === 0;
}
// Some existing files and directories can be safely ignored when checking if a directory is a valid project directory.
// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/create-react-app/createReactApp.js#L907-L934
const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
'.DS_Store',
'.git',
'.gitattributes',
'.gitignore',
'.gitlab-ci.yml',
'.hg',
'.hgcheck',
'.hgignore',
'.idea',
'.npmignore',
'.travis.yml',
'.yarn',
'.yarnrc.yml',
'docs',
'LICENSE',
'mkdocs.yml',
'Thumbs.db',
/\.iml$/,
/^npm-debug\.log/,
/^yarn-debug\.log/,
/^yarn-error\.log/,
];
function isValidProjectDirectory(dirPath: string) {
if (!fs.existsSync(dirPath)) {
return true;
}
const conflicts = fs.readdirSync(dirPath).filter((content) => {
return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
return typeof safeContent === 'string' ? content === safeContent : safeContent.test(content);
});
});
return conflicts.length === 0;
}
const { version } = JSON.parse(
fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8')
);
@ -59,7 +99,7 @@ export async function main() {
let cwd = args['_'][2] as string;
if (cwd && isEmpty(cwd)) {
if (cwd && isValidProjectDirectory(cwd)) {
let acknowledgeProjectDir = ora({
color: 'green',
text: `Using ${bold(cwd)} as project directory.`,
@ -67,10 +107,10 @@ export async function main() {
acknowledgeProjectDir.succeed();
}
if (!cwd || !isEmpty(cwd)) {
if (!cwd || !isValidProjectDirectory(cwd)) {
const notEmptyMsg = (dirPath: string) => `"${bold(dirPath)}" is not empty!`;
if (!isEmpty(cwd)) {
if (!isValidProjectDirectory(cwd)) {
let rejectProjectDir = ora({ color: 'red', text: notEmptyMsg(cwd) });
rejectProjectDir.fail();
}
@ -81,7 +121,7 @@ export async function main() {
message: 'Where would you like to create your new project?',
initial: './my-astro-site',
validate(value) {
if (!isEmpty(value)) {
if (!isValidProjectDirectory(value)) {
return notEmptyMsg(value);
}
return true;
@ -143,8 +183,10 @@ export async function main() {
// degit does not return an error when an invalid template is provided, as such we need to handle this manually
// It's not very pretty, but to the user eye, we just return a nice message and nothing weird happened
if (isEmpty(cwd)) {
fs.rmdirSync(cwd);
if (isValidProjectDirectory(cwd)) {
if (isEmpty(cwd)) {
fs.rmdirSync(cwd);
}
throw new Error(`Error: The provided template (${cyan(options.template)}) does not exist`);
}
} catch (err: any) {

View file

@ -4,6 +4,7 @@ import { PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout } from './
const inputs = {
nonEmptyDir: './fixtures/select-directory/nonempty-dir',
nonEmptySafeDir: './fixtures/select-directory/nonempty-safe-dir',
emptyDir: './fixtures/select-directory/empty-dir',
nonexistentDir: './fixtures/select-directory/banana-dir',
};
@ -30,6 +31,16 @@ describe('[create-astro] select directory', function () {
});
});
});
it('should proceed on a non-empty safe directory', function () {
return promiseWithTimeout((resolve) => {
const { stdout } = setup([inputs.nonEmptySafeDir]);
stdout.on('data', (chunk) => {
if (chunk.includes(PROMPT_MESSAGES.template)) {
resolve();
}
});
});
});
it('should proceed on an empty directory', async function () {
const resolvedEmptyDirPath = path.resolve(testDir, inputs.emptyDir);
if (!existsSync(resolvedEmptyDirPath)) {