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

Added prompt, if the directory already exists #9362

Merged
Merged
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
142 changes: 118 additions & 24 deletions packages/create-redwood-app/src/create-redwood-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ function checkNodeAndYarnVersion(templateDir) {
})
}

async function createProjectFiles(newAppDir, { templateDir, overwrite }) {
async function createProjectFiles(appDir, { templateDir, overwrite }) {
let newAppDir = appDir

const tuiContent = new ReactiveTUIContent({
mode: 'text',
content: 'Creating project files',
Expand All @@ -222,26 +224,7 @@ async function createProjectFiles(newAppDir, { templateDir, overwrite }) {
})
tui.startReactive(tuiContent)

// Check if the new app directory already exists
if (fs.existsSync(newAppDir) && !overwrite) {
// Check if the directory contains files and show an error if it does
if (fs.readdirSync(newAppDir).length > 0) {
tui.stopReactive(true)
tui.displayError(
'Project directory already contains files',
[
`'${RedwoodStyling.info(newAppDir)}' already exists and is not empty`,
``,
`You can use the '${RedwoodStyling.info(
'overwrite'
)}' flag to create the project even if target directory isn't empty`,
].join('\n')
)
recordErrorViaTelemetry(`Project directory already contains files`)
await shutdownTelemetry()
process.exit(1)
}
}
newAppDir = await doesDirectoryAlreadyExist(newAppDir, { overwrite })

// Ensure the new app directory exists
fs.ensureDirSync(path.dirname(newAppDir))
Expand All @@ -266,6 +249,8 @@ async function createProjectFiles(newAppDir, { templateDir, overwrite }) {
content: `${RedwoodStyling.green('✔')} Project files created`,
})
tui.stopReactive()

return newAppDir
}

async function installNodeModules(newAppDir) {
Expand Down Expand Up @@ -501,6 +486,114 @@ async function handleGitPreference(gitInitFlag) {
}
}

async function doesDirectoryAlreadyExist(
appDir,
{ overwrite, suppressWarning }
) {
let newAppDir = appDir

// Check if the new app directory already exists
if (fs.existsSync(newAppDir) && !overwrite) {
// Check if the directory contains files and show an error if it does
if (fs.readdirSync(newAppDir).length > 0) {
const styledAppDir = RedwoodStyling.info(newAppDir)

if (!suppressWarning) {
tui.stopReactive(true)
tui.displayWarning(
'Project directory already contains files',
[`'${styledAppDir}' already exists and is not empty`].join('\n')
)
}

try {
const response = await tui.prompt({
type: 'select',
name: 'projectDirectoryAlreadyExists',
message: 'How would you like to proceed?',
choices: [
'Quit install',
`Overwrite files in '${styledAppDir}' and continue install`,
'Specify a different directory',
],
initial: 0,
})

// overwrite the existing files
if (
response.projectDirectoryAlreadyExists ===
`Overwrite files in '${styledAppDir}' and continue install`
) {
// blow away the existing directory and create a new one
await fs.remove(newAppDir)
} // specify a different directory
else if (
response.projectDirectoryAlreadyExists ===
'Specify a different directory'
) {
const newDirectoryName = await handleNewDirectoryNamePreference()

if (/^~\w/.test(newDirectoryName)) {
tui.stopReactive(true)
tui.displayError(
'The `~username` syntax is not supported here',
'Please use the full path or specify the target directory on the command line.'
)

// Calling doesDirectoryAlreadyExist again with the same old
// appDir as a way to prompt the user for a new directory name
// after displaying the error above
newAppDir = await doesDirectoryAlreadyExist(appDir, {
overwrite,
suppressWarning: true,
})
} else {
newAppDir = path.resolve(process.cwd(), untildify(newDirectoryName))
}

// check to see if the new directory exists
newAppDir = await doesDirectoryAlreadyExist(newAppDir, { overwrite })
} // Quit Install and Throw and Error
else if (response.projectDirectoryAlreadyExists === 'Quit install') {
// quit and throw an error
recordErrorViaTelemetry(
'User quit after directory already exists error'
)
await shutdownTelemetry()
process.exit(1)
}
// overwrite the existing files
} catch (_error) {
recordErrorViaTelemetry(
`User cancelled install after directory already exists error`
)
await shutdownTelemetry()
process.exit(1)
}
}
}

return newAppDir
}

async function handleNewDirectoryNamePreference() {
try {
const response = await tui.prompt({
type: 'input',
name: 'targetDirectoryInput',
message: 'What directory would you like to create the app in?',
initial: 'my-redwood-app',
})
return response.targetDirectoryInput
} catch (_error) {
recordErrorViaTelemetry(
'User cancelled install at specify a different directory prompt'
)
await shutdownTelemetry()
process.exit(1)
}
}

/**
* @param {string?} commitMessageFlag
*/
Expand Down Expand Up @@ -674,10 +767,11 @@ async function createRedwoodApp() {
yarnInstall = await handleYarnInstallPreference(yarnInstallFlag)
}

const newAppDir = path.resolve(process.cwd(), targetDir)
let newAppDir = path.resolve(process.cwd(), targetDir)

// Create project files
await createProjectFiles(newAppDir, { templateDir, overwrite })
// if this directory already exists then createProjectFiles may set a new directory name
newAppDir = await createProjectFiles(newAppDir, { templateDir, overwrite })

// Install the node packages
if (yarnInstall) {
Expand Down Expand Up @@ -717,7 +811,7 @@ async function createRedwoodApp() {
...[
`${RedwoodStyling.redwood(
` > ${RedwoodStyling.green(
`cd ${path.relative(process.cwd(), targetDir)}`
`cd ${path.relative(process.cwd(), newAppDir)}`
)}`
)}`,
!yarnInstall &&
Expand Down
Loading