Skip to content

Commit 38846dd

Browse files
committed
dispatcher: multi-candidate registry lookup + Windows path fixes
- Try venv_root, self_dir, and self_dir parent for registry lookup so Windows installs (where find_venv_root misses backslash separators) can still find the correct adopted Python. - Handle 'python.exe' basename: strip .exe before version comparison. - Use both '/' and '\' as path separators when extracting version. - fallback_to_python_v: also search parent dir and include python.exe in candidate names (covers Scripts/ -> prefix/ layout on Windows).
1 parent c2620ed commit 38846dd

1 file changed

Lines changed: 40 additions & 13 deletions

File tree

src/omnipkg/dispatcher.c

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -978,14 +978,22 @@ static void fallback_to_python_v(const char *self_dir, char **argv,
978978

979979
/* Try the config first */
980980
if (!read_self_config(self_dir, py, sizeof(py)) || !file_exists(py)) {
981-
/* Try common names in self_dir */
981+
/* Try common names in self_dir, then parent (Scripts/ -> prefix/ on Windows). */
982982
const char *names[] = {"python3.11","python3.10","python3.9",
983-
"python3","python",NULL};
983+
"python3","python","python.exe",NULL};
984984
int found = 0;
985985
for (int i = 0; names[i]; i++) {
986986
snprintf(py, sizeof(py), "%s/%s", self_dir, names[i]);
987987
if (file_exists(py)) { found = 1; break; }
988988
}
989+
if (!found) {
990+
char parent_dir[MAX_PATH];
991+
dir_of(self_dir, parent_dir, sizeof(parent_dir));
992+
for (int i = 0; names[i]; i++) {
993+
snprintf(py, sizeof(py), "%s/%s", parent_dir, names[i]);
994+
if (file_exists(py)) { found = 1; break; }
995+
}
996+
}
989997
if (!found) {
990998
fprintf(stderr, "omnipkg: cannot find host Python for fallback\n");
991999
exit(1);
@@ -1591,8 +1599,25 @@ int main(int argc, char **argv) {
15911599
if (cli_version) {
15921600
char venv_root[MAX_PATH];
15931601
find_venv_root(self_real, venv_root, sizeof(venv_root));
1594-
if (venv_root[0] && registry_lookup(venv_root, cli_version,
1595-
target_python, sizeof(target_python))) {
1602+
1603+
/* Multi-candidate registry lookup: find_venv_root may miss on Windows
1604+
* (uses strrchr('/') only). Try venv_root, self_dir, self_dir parent. */
1605+
int reg_hit = 0;
1606+
if (venv_root[0])
1607+
reg_hit = registry_lookup(venv_root, cli_version,
1608+
target_python, sizeof(target_python));
1609+
if (!reg_hit)
1610+
reg_hit = registry_lookup(self_dir, cli_version,
1611+
target_python, sizeof(target_python));
1612+
if (!reg_hit) {
1613+
char parent_dir[MAX_PATH];
1614+
dir_of(self_dir, parent_dir, sizeof(parent_dir));
1615+
if (parent_dir[0])
1616+
reg_hit = registry_lookup(parent_dir, cli_version,
1617+
target_python, sizeof(target_python));
1618+
}
1619+
1620+
if (reg_hit) {
15961621
if (!file_exists(target_python)) {
15971622
/* Not adopted yet → fallback to Python for auto-adopt */
15981623
if (debug) fprintf(stderr, "[C-DISPATCH] %s not found → auto-adopt fallback\n", target_python);
@@ -1602,28 +1627,30 @@ int main(int argc, char **argv) {
16021627
fprintf(stderr, "[C-DISPATCH] registry hit %s → %s\n",
16031628
cli_version, target_python);
16041629
} else {
1605-
/* Registry miss — could be the native interpreter (not adopted, so not
1606-
* in registry.json). Check if the self-aware config python matches the
1607-
* requested version before giving up and paying the Python fallback cost. */
1630+
/* Registry miss — check if self-aware config python matches.
1631+
* Handle Windows where basename may be "python.exe". */
16081632
char self_py[MAX_PATH] = "";
16091633
read_self_config(self_dir, self_py, sizeof(self_py));
16101634
if (self_py[0] && file_exists(self_py)) {
1611-
/* Extract version from the path, e.g. ".../bin/python3.11" → "3.11" */
1635+
/* Extract version from path. Try both / and \\ separators. */
16121636
const char *base = strrchr(self_py, '/');
1637+
const char *base2 = strrchr(self_py, '\\');
1638+
if (base2 && (!base || base2 > base)) base = base2;
16131639
base = base ? base + 1 : self_py;
1614-
/* skip "python" prefix */
16151640
const char *ver_in_path = base;
16161641
if (strncmp(ver_in_path, "python", 6) == 0) ver_in_path += 6;
1617-
if (strncmp(ver_in_path, "3.", 2) == 0 &&
1618-
strcmp(ver_in_path, cli_version) == 0) {
1619-
/* Native interpreter matches — use it directly, no fallback needed */
1642+
char ver_buf[32] = "";
1643+
strncpy(ver_buf, ver_in_path, sizeof(ver_buf) - 1);
1644+
char *dot_exe = strstr(ver_buf, ".exe");
1645+
if (dot_exe) *dot_exe = '\0';
1646+
if (strncmp(ver_buf, "3.", 2) == 0 &&
1647+
strcmp(ver_buf, cli_version) == 0) {
16201648
strncpy(target_python, self_py, sizeof(target_python) - 1);
16211649
target_python[sizeof(target_python) - 1] = '\0';
16221650
if (debug)
16231651
fprintf(stderr, "[C-DISPATCH] native match %s → %s\n",
16241652
cli_version, target_python);
16251653
} else {
1626-
/* Genuinely unknown version → Python fallback for auto-adopt */
16271654
if (debug) fprintf(stderr, "[C-DISPATCH] unknown version %s → fallback\n", cli_version);
16281655
fallback_to_python_v(self_dir, argv, cli_version);
16291656
}

0 commit comments

Comments
 (0)