Add support for running create-astro
in cloned empty git repository (#4805)
This commit is contained in:
parent
f2b515d0b4
commit
c84d85ba4d
5 changed files with 64 additions and 6 deletions
5
.changeset/six-weeks-grab.md
Normal file
5
.changeset/six-weeks-grab.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'create-astro': patch
|
||||
---
|
||||
|
||||
Add support for running in cloned empty git repository
|
|
@ -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) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
0
packages/create-astro/test/fixtures/select-directory/nonempty-safe-dir/.gitignore
vendored
Normal file
0
packages/create-astro/test/fixtures/select-directory/nonempty-safe-dir/.gitignore
vendored
Normal file
0
packages/create-astro/test/fixtures/select-directory/nonempty-safe-dir/module.iml
vendored
Normal file
0
packages/create-astro/test/fixtures/select-directory/nonempty-safe-dir/module.iml
vendored
Normal file
Loading…
Reference in a new issue