@@ -292,7 +292,7 @@ async function getNamedCondaPythonInfo(
292292 const shellDeactivation : Map < string , PythonCommandRunConfiguration [ ] > = new Map ( ) ;
293293
294294 if ( conda . includes ( '/' ) || conda . includes ( '\\' ) ) {
295- const shActivate = path . join ( path . dirname ( path . dirname ( conda ) ) , 'etc' , 'profile.d' , 'conda.sh' ) ;
295+ const shActivate = await getCondaShPath ( conda ) ;
296296
297297 if ( isWindows ( ) ) {
298298 shellActivation . set ( ShellConstants . GITBASH , [
@@ -385,7 +385,7 @@ async function getPrefixesCondaPythonInfo(
385385 const shellDeactivation : Map < string , PythonCommandRunConfiguration [ ] > = new Map ( ) ;
386386
387387 if ( conda . includes ( '/' ) || conda . includes ( '\\' ) ) {
388- const shActivate = path . join ( path . dirname ( path . dirname ( conda ) ) , 'etc' , 'profile.d' , 'conda.sh' ) ;
388+ const shActivate = await getCondaShPath ( conda ) ;
389389
390390 if ( isWindows ( ) ) {
391391 shellActivation . set ( ShellConstants . GITBASH , [
@@ -1055,6 +1055,88 @@ export async function checkForNoPythonCondaEnvironment(
10551055
10561056// Cache for conda hook paths to avoid redundant filesystem checks
10571057const condaHookPathCache = new Map < string , Promise < string > > ( ) ;
1058+ const condaShPathCache = new Map < string , Promise < string > > ( ) ;
1059+
1060+ /**
1061+ * Helper function that checks for a file in a list of locations.
1062+ * Returns the first location where the file exists, or undefined if not found.
1063+ */
1064+ async function findFileInLocations (
1065+ locations : string [ ] ,
1066+ description : string ,
1067+ condaPath : string ,
1068+ ) : Promise < string | undefined > {
1069+ for ( const location of locations ) {
1070+ if ( await fse . pathExists ( location ) ) {
1071+ traceInfo ( `${ description } found in ${ location } ` ) ;
1072+ return location ;
1073+ }
1074+ }
1075+ traceError (
1076+ `${ description } not found in any of the locations: ${ locations . join ( ', ' ) } , ` +
1077+ `given conda path: ${ condaPath } ` ,
1078+ ) ;
1079+ return undefined ;
1080+ }
1081+
1082+ /**
1083+ * Returns the path to conda.sh given a conda executable path.
1084+ *
1085+ * Searches for conda.sh in these locations (relative to the conda root):
1086+ * - etc/profile.d/conda.sh
1087+ * - shell/etc/profile.d/conda.sh
1088+ * - Library/etc/profile.d/conda.sh
1089+ * - lib/pythonX.Y/site-packages/conda/shell/etc/profile.d/conda.sh
1090+ * - site-packages/conda/shell/etc/profile.d/conda.sh
1091+ * Also checks some system-level locations
1092+ */
1093+ async function getCondaShPath ( condaPath : string ) : Promise < string > {
1094+ // Check cache first
1095+ const cachedPath = condaShPathCache . get ( condaPath ) ;
1096+ if ( cachedPath ) {
1097+ return cachedPath ;
1098+ }
1099+
1100+ // Create the promise for finding the conda.sh path
1101+ const shPathPromise = ( async ( ) => {
1102+ const condaRoot = path . dirname ( path . dirname ( condaPath ) ) ;
1103+
1104+ // First try standard conda installation locations
1105+ const standardLocations = [
1106+ path . join ( condaRoot , 'etc' , 'profile.d' , 'conda.sh' ) ,
1107+ path . join ( condaRoot , 'shell' , 'etc' , 'profile.d' , 'conda.sh' ) ,
1108+ path . join ( condaRoot , 'Library' , 'etc' , 'profile.d' , 'conda.sh' ) ,
1109+ ] ;
1110+
1111+ // Check standard locations first
1112+ const standardLocation = await findFileInLocations ( standardLocations , 'conda.sh' , condaPath ) ;
1113+ if ( standardLocation ) {
1114+ return standardLocation ;
1115+ }
1116+
1117+ // If not found in standard locations, try pip install locations
1118+ const possiblePythonVersions = [ 'python3.9' , 'python3.10' , 'python3.11' , 'python3.12' , 'python3.8' ] ;
1119+ const pipInstallLocations = [
1120+ ...possiblePythonVersions . map ( ( ver ) =>
1121+ path . join ( condaRoot , 'lib' , ver , 'site-packages' , 'conda' , 'shell' , 'etc' , 'profile.d' , 'conda.sh' ) ,
1122+ ) ,
1123+ path . join ( condaRoot , 'site-packages' , 'conda' , 'shell' , 'etc' , 'profile.d' , 'conda.sh' ) ,
1124+ ] ;
1125+
1126+ // Check pip install locations
1127+ const pipLocation = await findFileInLocations ( pipInstallLocations , 'conda.sh' , condaPath ) ;
1128+ if ( pipLocation ) {
1129+ return pipLocation ;
1130+ }
1131+
1132+ // Fall back to the traditional location as a last resort
1133+ return path . join ( condaRoot , 'etc' , 'profile.d' , 'conda.sh' ) ;
1134+ } ) ( ) ;
1135+
1136+ // Store in cache and return
1137+ condaShPathCache . set ( condaPath , shPathPromise ) ;
1138+ return shPathPromise ;
1139+ }
10581140
10591141/**
10601142 * Returns the best guess path to conda-hook.ps1 given a conda executable path.
@@ -1076,31 +1158,19 @@ async function getCondaHookPs1Path(condaPath: string): Promise<string> {
10761158 const hookPathPromise = ( async ( ) => {
10771159 const condaRoot = path . dirname ( path . dirname ( condaPath ) ) ;
10781160
1079- const condaRootCandidates : string [ ] = [
1080- path . join ( condaRoot , 'shell' , 'condabin' ) ,
1081- path . join ( condaRoot , 'Library' , 'shell' , 'condabin' ) ,
1082- path . join ( condaRoot , 'condabin' ) ,
1083- path . join ( condaRoot , 'etc' , 'profile.d' ) ,
1161+ const hookLocations = [
1162+ path . join ( condaRoot , 'shell' , 'condabin' , 'conda-hook.ps1' ) ,
1163+ path . join ( condaRoot , 'Library' , 'shell' , 'condabin' , 'conda-hook.ps1' ) ,
1164+ path . join ( condaRoot , 'condabin' , 'conda-hook.ps1' ) ,
1165+ path . join ( condaRoot , 'etc' , 'profile.d' , 'conda-hook.ps1' ) ,
10841166 ] ;
10851167
1086- const checks = condaRootCandidates . map ( async ( hookSearchDir ) => {
1087- const candidate = path . join ( hookSearchDir , 'conda-hook.ps1' ) ;
1088- if ( await fse . pathExists ( candidate ) ) {
1089- traceInfo ( `Conda hook found at: ${ candidate } ` ) ;
1090- return candidate ;
1091- }
1092- return undefined ;
1093- } ) ;
1094- const results = await Promise . all ( checks ) ;
1095- const found = results . find ( Boolean ) ;
1168+ const found = await findFileInLocations ( hookLocations , 'conda-hook.ps1' , condaPath ) ;
10961169 if ( found ) {
1097- return found as string ;
1170+ return found ;
10981171 }
1099- traceError (
1100- `Conda hook not found in any of the expected locations: ${ condaRootCandidates . join (
1101- ', ' ,
1102- ) } , given conda path: ${ condaPath } `,
1103- ) ;
1172+
1173+ // Fall back to the traditional location as a last resort
11041174 return path . join ( condaRoot , 'shell' , 'condabin' , 'conda-hook.ps1' ) ;
11051175 } ) ( ) ;
11061176
0 commit comments