@@ -195,6 +195,13 @@ join(wchar_t *buffer, size_t bufferLength, const wchar_t *fragment)
195
195
}
196
196
197
197
198
+ bool
199
+ split_parent (wchar_t * buffer , size_t bufferLength )
200
+ {
201
+ return SUCCEEDED (PathCchRemoveFileSpec (buffer , bufferLength ));
202
+ }
203
+
204
+
198
205
int
199
206
_compare (const wchar_t * x , int xLen , const wchar_t * y , int yLen )
200
207
{
@@ -414,8 +421,8 @@ typedef struct {
414
421
// if true, treats 'tag' as a non-PEP 514 filter
415
422
bool oldStyleTag ;
416
423
// if true, ignores 'tag' when a high priority environment is found
417
- // gh-92817: This is currently set when a tag is read from configuration or
418
- // the environment, rather than the command line or a shebang line, and the
424
+ // gh-92817: This is currently set when a tag is read from configuration,
425
+ // the environment, or a shebang, rather than the command line, and the
419
426
// only currently possible high priority environment is an active virtual
420
427
// environment
421
428
bool lowPriorityTag ;
@@ -794,6 +801,8 @@ searchPath(SearchInfo *search, const wchar_t *shebang, int shebangLength)
794
801
}
795
802
}
796
803
804
+ debug (L"# Search PATH for %s\n" , filename );
805
+
797
806
wchar_t pathVariable [MAXLEN ];
798
807
int n = GetEnvironmentVariableW (L"PATH" , pathVariable , MAXLEN );
799
808
if (!n ) {
@@ -1031,8 +1040,12 @@ checkShebang(SearchInfo *search)
1031
1040
debug (L"Shebang: %s\n" , shebang );
1032
1041
1033
1042
// Handle shebangs that we should search PATH for
1043
+ int executablePathWasSetByUsrBinEnv = 0 ;
1034
1044
exitCode = searchPath (search , shebang , shebangLength );
1035
- if (exitCode != RC_NO_SHEBANG ) {
1045
+ if (exitCode == 0 ) {
1046
+ // We might need to clear executable path later if we match a template
1047
+ executablePathWasSetByUsrBinEnv = 1 ;
1048
+ } else if (exitCode != RC_NO_SHEBANG ) {
1036
1049
return exitCode ;
1037
1050
}
1038
1051
@@ -1082,6 +1095,13 @@ checkShebang(SearchInfo *search)
1082
1095
}
1083
1096
}
1084
1097
search -> oldStyleTag = true;
1098
+ search -> lowPriorityTag = true;
1099
+ if (executablePathWasSetByUsrBinEnv ) {
1100
+ // If it was allocated, it's in a free list, so just clear it
1101
+ debug (L"# Shebang template made us forget executablePath %s\n" ,
1102
+ search -> executablePath );
1103
+ search -> executablePath = NULL ;
1104
+ }
1085
1105
search -> executableArgs = & command [commandLength ];
1086
1106
search -> executableArgsLength = shebangLength - commandLength ;
1087
1107
if (search -> tag && search -> tagLength ) {
@@ -1765,7 +1785,15 @@ virtualenvSearch(const SearchInfo *search, EnvironmentInfo **result)
1765
1785
return 0 ;
1766
1786
}
1767
1787
1768
- if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW (buffer )) {
1788
+ DWORD attr = GetFileAttributesW (buffer );
1789
+ if (INVALID_FILE_ATTRIBUTES == attr && search -> lowPriorityTag ) {
1790
+ if (!split_parent (buffer , MAXLEN ) || !join (buffer , MAXLEN , L"python.exe" )) {
1791
+ return 0 ;
1792
+ }
1793
+ attr = GetFileAttributesW (buffer );
1794
+ }
1795
+
1796
+ if (INVALID_FILE_ATTRIBUTES == attr ) {
1769
1797
debug (L"Python executable %s missing from virtual env\n" , buffer );
1770
1798
return 0 ;
1771
1799
}
0 commit comments