Hackable Mercurial Can't Find os Module

Adrian Buehlmann adrian at cadifra.com
Thu Aug 27 06:37:20 UTC 2015


On 2015-08-27 01:08, Jensen, Aaron wrote:
>> Perhaps the commit message of 93d97a212559 might be helpful when investigating your problem:
>>
>>  https://selenic.com/hg/rev/93d97a212559
> 
> It looks like the code is looking for a PYTHONHOME environment variable. Once I added that environment variable pointing to the hg-python26 directory, hackable Mercurial is working. I've updated the Hackable Mercurial for Windows wiki page [1].
> 
> In summary, to get hackable Mercurial for Windows working, I had to:
> 
>  1. Add the path to the package's hg-python26 directory to my PATH.
>  2. Create a PYTHONHOME environment variable, set to the full path to the package's hg-python26 directory.
> 
> 
> [1] https://mercurial.selenic.com/wiki/HackableMercurial

I think there should be a better way to fix your problem.

The code in exewrapper.c (which is the source for the hg.exe that the
prcocess is running) is indeed looking for PYTHONHOME and uses it, if it
is set. This just mimicks a feature that is present in the official
python interpreter (python.exe) as installed by any Windows-installer
provided by the Python folks.

But the interesting part in exewrapper.c is _inside_ the check for
PYTHONHOME, which is executed iff it is _not_ set:

    if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
                   sizeof(envpyhome)) == 0)
    {
        /* environment var PYTHONHOME is not set */

This part looks for a directory namend "hg-python" next to the hg.exe
and then tries to load the Python DLL from that directory into the
process (which is hg.exe) and sets Py_SetPythonHome, which should make
sure the Python interpreter finds its Python libraries ("os" is one of
them):

        p = strrchr(pyhome, '\\');
        if (p == NULL) {
            err = "can't find backslash in module filename";
            goto bail;
        }
        *p = 0; /* cut at directory */

        /* check for private Python of HackableMercurial */
        strcat_s(pyhome, sizeof(pyhome), "\\hg-python");

        hfind = FindFirstFile(pyhome, &fdata);
        if (hfind != INVALID_HANDLE_VALUE) {
            /* path pyhome exists, let's use it */
            FindClose(hfind);
            strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
            strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB);
            pydll = LoadLibrary(pydllfile);
            if (pydll == NULL) {
                err = "failed to load private Python DLL";
                goto bail;
            }
            Py_SetPythonHome = (void*)GetProcAddress(pydll,
                            "Py_SetPythonHome");
            if (Py_SetPythonHome == NULL) {
                err = "failed to get Py_SetPythonHome";
                goto bail;
            }
            Py_SetPythonHome(pyhome);
        }
    }

After everything is prepared, the code basically then just calls the
Python interpreter with Py_Main(), feeding it the name of the Python
script to be executed, which by default is the name of the process
without the trailing ".exe" (i.e. "hg").

So, to me, it looks like one problem you have is that the name of the
directory which has your contents of HackableMercurial is hg-python26
(as you wrote), instead of "hg-python" which hg.exe is looking for.



More information about the Mercurial mailing list