Skip to content

Commit

Permalink
Added prompt, if the directory already exists (#9362)
Browse files Browse the repository at this point in the history
Co-authored-by: Tobbe Lundberg <[email protected]>
  • Loading branch information
ahaywood and Tobbe authored Nov 18, 2023
1 parent 8057208 commit 8c4a520
Showing 1 changed file with 118 additions and 24 deletions.
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

0 comments on commit 8c4a520

Please sign in to comment.