@@ -3,7 +3,6 @@ use assert_cmd::prelude::*;
33use assert_fs:: prelude:: * ;
44use indoc:: indoc;
55use predicates:: prelude:: * ;
6-
76use uv_python:: { PYTHON_VERSIONS_FILENAME , PYTHON_VERSION_FILENAME } ;
87use uv_static:: EnvVars ;
98
@@ -1087,3 +1086,57 @@ fn path_with_trailing_space_gives_proper_error() {
10871086 ) ;
10881087 // Note the extra trailing `/` in the snapshot is due to the filters, not the actual output.
10891088}
1089+
1090+ /// Check that the activate script still works with the path contains an apostrophe.
1091+ #[ test]
1092+ #[ cfg( target_os = "linux" ) ]
1093+ fn create_venv_apostrophe ( ) {
1094+ use std:: env;
1095+ use std:: ffi:: OsString ;
1096+ use std:: io:: Write ;
1097+ use std:: process:: Command ;
1098+ use std:: process:: Stdio ;
1099+
1100+ let context = TestContext :: new_with_versions ( & [ "3.12" ] ) ;
1101+
1102+ let venv_dir = context. temp_dir . join ( "Testing's" ) ;
1103+
1104+ uv_snapshot ! ( context. filters( ) , context. venv( )
1105+ . arg( & venv_dir)
1106+ . arg( "--python" )
1107+ . arg( "3.12" ) , @r###"
1108+ success: true
1109+ exit_code: 0
1110+ ----- stdout -----
1111+
1112+ ----- stderr -----
1113+ Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
1114+ Creating virtual environment at: Testing's
1115+ Activate with: source Testing's/[BIN]/activate
1116+ "###
1117+ ) ;
1118+
1119+ // One of them should be commonly available on a linux developer machine, if not, we have to
1120+ // extend the fallbacks.
1121+ let shell = env:: var_os ( "SHELL" ) . unwrap_or ( OsString :: from ( "bash" ) ) ;
1122+ let mut child = Command :: new ( shell)
1123+ . stdin ( Stdio :: piped ( ) )
1124+ . stdout ( Stdio :: piped ( ) )
1125+ . current_dir ( & venv_dir)
1126+ . spawn ( )
1127+ . expect ( "Failed to spawn shell script" ) ;
1128+
1129+ let mut stdin = child. stdin . take ( ) . expect ( "Failed to open stdin" ) ;
1130+ std:: thread:: spawn ( move || {
1131+ stdin
1132+ . write_all ( ". bin/activate && python -c 'import sys; print(sys.prefix)'" . as_bytes ( ) )
1133+ . expect ( "Failed to write to stdin" ) ;
1134+ } ) ;
1135+
1136+ let output = child. wait_with_output ( ) . expect ( "Failed to read stdout" ) ;
1137+
1138+ assert ! ( output. status. success( ) , "{output:?}" ) ;
1139+
1140+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
1141+ assert_eq ! ( stdout. trim( ) , venv_dir. to_string_lossy( ) ) ;
1142+ }
0 commit comments