@@ -5,9 +5,11 @@ use std::io;
55use std:: io:: { BufWriter , Write } ;
66use std:: path:: Path ;
77
8+ use console:: Term ;
89use fs_err as fs;
910use fs_err:: File ;
1011use itertools:: Itertools ;
12+ use owo_colors:: OwoColorize ;
1113use tracing:: debug;
1214
1315use uv_configuration:: PreviewMode ;
@@ -53,6 +55,7 @@ pub(crate) fn create(
5355 prompt : Prompt ,
5456 system_site_packages : bool ,
5557 allow_existing : bool ,
58+ clear : bool ,
5659 relocatable : bool ,
5760 seed : bool ,
5861 upgradeable : bool ,
@@ -83,10 +86,17 @@ pub(crate) fn create(
8386 format ! ( "File exists at `{}`" , location. user_display( ) ) ,
8487 ) ) ) ;
8588 } else if metadata. is_dir ( ) {
89+ let confirmation_required = !clear && !allow_existing;
90+ let confirmed_clear = confirmation_required && confirm_clear ( location) ?;
91+
8692 if allow_existing {
87- debug ! ( "Allowing existing directory" ) ;
88- } else if uv_fs:: is_virtualenv_base ( location) {
89- debug ! ( "Removing existing directory" ) ;
93+ debug ! ( "Allowing existing directory due to `--allow-existing`" ) ;
94+ } else if clear || confirmed_clear {
95+ if clear {
96+ debug ! ( "Removing existing directory due to `--clear`" ) ;
97+ } else {
98+ debug ! ( "Removing existing directory" ) ;
99+ }
90100
91101 // On Windows, if the current executable is in the directory, guard against
92102 // self-deletion.
@@ -110,8 +120,12 @@ pub(crate) fn create(
110120 return Err ( Error :: Io ( io:: Error :: new (
111121 io:: ErrorKind :: AlreadyExists ,
112122 format ! (
113- "The directory `{}` exists, but it's not a virtual environment" ,
114- location. user_display( )
123+ "The directory `{}` exists. \n \n {}{} Use `{}` to remove the directory first or `{}` to write to the directory without clearing" ,
124+ location. user_display( ) ,
125+ "hint" . bold( ) . cyan( ) ,
126+ ":" . bold( ) ,
127+ "--clear" . green( ) ,
128+ "--allow-existing" . green( ) ,
115129 ) ,
116130 ) ) ) ;
117131 }
@@ -464,6 +478,19 @@ pub(crate) fn create(
464478 } )
465479}
466480
481+ fn confirm_clear ( location : & Path ) -> Result < bool , io:: Error > {
482+ let term = Term :: stderr ( ) ;
483+ if term. is_term ( ) {
484+ let prompt = format ! (
485+ "The directory `{}` exists. Did you mean to clear its contents (`--clear`)?" ,
486+ location. user_display( ) ,
487+ ) ;
488+ uv_console:: confirm ( & prompt, & term, true )
489+ } else {
490+ Ok ( false )
491+ }
492+ }
493+
467494#[ derive( Debug , Copy , Clone ) ]
468495enum WindowsExecutable {
469496 /// The `python.exe` executable (or `venvlauncher.exe` launcher shim).
0 commit comments