Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/six-weeks-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'create-astro': patch
---

Add support for running in cloned empty git repository
54 changes: 48 additions & 6 deletions packages/create-astro/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
);
Expand All @@ -59,18 +99,18 @@ 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.`,
});
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();
}
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
11 changes: 11 additions & 0 deletions packages/create-astro/test/directory-step.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
};
Expand All @@ -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)) {
Expand Down