Skip to content

Commit 6adee29

Browse files
Copilotvhvb1989
andauthored
Prompt to create directory when using -C/--cwd with non-existent path (#6266)
* Initial plan * Initial planning for cwd directory creation prompt Co-authored-by: vhvb1989 <[email protected]> * Add directory creation prompt for -C/--cwd flag Co-authored-by: vhvb1989 <[email protected]> * Complete directory creation feature for -C/--cwd flag Co-authored-by: vhvb1989 <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: vhvb1989 <[email protected]>
1 parent b26ed3e commit 6adee29

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,4 @@ cli/azd/extensions/microsoft.azd.ai.builder/microsoft.azd.ai.builder
6767
cli/azd/extensions/microsoft.azd.ai.builder/microsoft.azd.ai.builder.exe
6868
cli/azd/extensions/microsoft.azd.demo/microsoft.azd.demo
6969
cli/azd/extensions/microsoft.azd.demo/microsoft.azd.demo.exe
70+
cli/azd/azd-test

cli/azd/cmd/root.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/azure/azure-dev/cli/azd/internal/cmd/show"
2727
"github.com/azure/azure-dev/cli/azd/internal/telemetry"
2828
"github.com/azure/azure-dev/cli/azd/pkg/output"
29+
"github.com/azure/azure-dev/cli/azd/pkg/ux"
2930
"github.com/spf13/cobra"
3031
)
3132

@@ -80,6 +81,44 @@ func NewRootCmd(
8081

8182
prevDir = current
8283

84+
// Check if the directory exists
85+
if _, err := os.Stat(opts.Cwd); os.IsNotExist(err) {
86+
// Directory doesn't exist, prompt user to create it
87+
shouldCreate := true // Default to Yes
88+
89+
if !opts.NoPrompt {
90+
// Prompt the user
91+
defaultValue := true
92+
confirm := ux.NewConfirm(&ux.ConfirmOptions{
93+
Message: fmt.Sprintf(
94+
"Directory '%s' does not exist. Would you like to create it?",
95+
opts.Cwd,
96+
),
97+
DefaultValue: &defaultValue,
98+
})
99+
100+
result, err := confirm.Ask(cmd.Context())
101+
if err != nil {
102+
return fmt.Errorf("failed to prompt for directory creation: %w", err)
103+
}
104+
105+
if result == nil {
106+
return fmt.Errorf("no response received for directory creation prompt")
107+
}
108+
109+
shouldCreate = *result
110+
}
111+
112+
if !shouldCreate {
113+
return fmt.Errorf("directory '%s' does not exist and creation was declined", opts.Cwd)
114+
}
115+
116+
// Create the directory
117+
if err := os.MkdirAll(opts.Cwd, 0755); err != nil {
118+
return fmt.Errorf("failed to create directory '%s': %w", opts.Cwd, err)
119+
}
120+
}
121+
83122
if err := os.Chdir(opts.Cwd); err != nil {
84123
return fmt.Errorf("failed to change directory to %s: %w", opts.Cwd, err)
85124
}

cli/azd/test/functional/init_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,56 @@ func Test_CLI_Init_CanUseTemplate(t *testing.T) {
291291
require.FileExists(t, filepath.Join(dir, "README.md"))
292292
}
293293

294+
// Test_CLI_Init_WithCwdAutoCreate tests the automatic directory creation when using -C/--cwd flag.
295+
func Test_CLI_Init_WithCwdAutoCreate(t *testing.T) {
296+
tests := []struct {
297+
name string
298+
subDir string // subdirectory to create within temp dir (using -C flag)
299+
args []string
300+
}{
301+
{
302+
name: "single level directory",
303+
subDir: "new-project",
304+
args: []string{"init", "-t", "azure-samples/todo-nodejs-mongo", "--no-prompt"},
305+
},
306+
{
307+
name: "nested directory",
308+
subDir: "parent/child/project",
309+
args: []string{"init", "-t", "azure-samples/todo-nodejs-mongo", "--no-prompt"},
310+
},
311+
}
312+
313+
for _, tt := range tests {
314+
t.Run(tt.name, func(t *testing.T) {
315+
ctx, cancel := newTestContext(t)
316+
defer cancel()
317+
318+
// Create a parent temp directory
319+
parentDir := tempDirWithDiagnostics(t)
320+
cli := azdcli.NewCLI(t)
321+
cli.WorkingDirectory = parentDir
322+
323+
// Add -C flag with the subdirectory path
324+
targetDir := filepath.Join(parentDir, tt.subDir)
325+
args := append([]string{"-C", tt.subDir}, tt.args...)
326+
327+
// Directory should not exist before running the command
328+
require.NoDirExists(t, targetDir)
329+
330+
// Run the command
331+
// Note: We expect an error because --no-prompt will fail on environment name prompt
332+
// but the directory creation should succeed before that
333+
cli.RunCommand(ctx, args...)
334+
335+
// Verify the directory was created
336+
require.DirExists(t, targetDir)
337+
338+
// Verify that the template was initialized in the created directory
339+
require.FileExists(t, filepath.Join(targetDir, azdcontext.ProjectFileName))
340+
})
341+
}
342+
}
343+
294344
// verifyEnvInitialized is a helper function that returns a verification function.
295345
// This avoids duplicating the verification logic in the test table.
296346
func verifyEnvInitialized(envName string) func(t *testing.T, dir string) {

0 commit comments

Comments
 (0)