##// END OF EJS Templates
perf: import newer modules separately for earlier Mercurial...
perf: import newer modules separately for earlier Mercurial demandimport of early Mercurial loads an imported module immediately, if a module is imported absolutely by "from a import b" style. Recent perf.py satisfies this condition, because it does: - have "from __future__ import absolute_import" line - use "from a import b" style for modules in "mercurial" package Before this patch, importing modules below prevents perf.py from being loaded by earlier Mercurial, because these aren't available in such Mercurial, even though there are some code paths for Mercurial earlier than 1.9. - branchmap 2.5 (or bcee63733aad) - repoview 2.5 (or 3a6ddacb7198) - obsolete 2.3 (or ad0d6c2b3279) - scmutil 1.9 (or 8b252e826c68) For example, setting "_prereadsize" attribute in perfindex() and perfnodelookup() is effective only with Mercurial earlier than 1.8 (or 61c9bc3da402). After this patch, "mercurial.error" is the only blocker in "from mercurial import" statement for loading perf.py with Mercurial earlier than 1.2. This patch ignores it, because just importing it separately isn't enough.

File last commit:

r29019:210bb28c stable
r29567:7e2b3894 default
Show More
exewrapper.c
175 lines | 4.4 KiB | text/x-c | CLexer
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 /*
exewrapper.c - wrapper for calling a python script on Windows
Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
This software may be used and distributed according to the terms of the
GNU General Public License version 2 or any later version.
*/
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 #include <stdio.h>
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 #include <windows.h>
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 #include "hgpythonlib.h"
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058
#ifdef __GNUC__
int strcat_s(char *d, size_t n, const char *s)
{
return !strncat(d, s, n);
}
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 int strcpy_s(char *d, size_t n, const char *s)
{
return !strncpy(d, s, n);
}
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 #endif
static char pyscript[MAX_PATH + 10];
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 static char pyhome[MAX_PATH + 10];
static char envpyhome[MAX_PATH + 10];
static char pydllfile[MAX_PATH + 10];
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058
int main(int argc, char *argv[])
{
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 char *p;
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 int ret;
int i;
int n;
char **pyargv;
WIN32_FIND_DATA fdata;
HANDLE hfind;
const char *err;
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 HMODULE pydll;
void (__cdecl *Py_SetPythonHome)(char *home);
int (__cdecl *Py_Main)(int argc, char *argv[]);
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058
if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
{
err = "GetModuleFileName failed";
goto bail;
}
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 p = strrchr(pyscript, '.');
if (p == NULL) {
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 err = "malformed module filename";
goto bail;
}
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 *p = 0; /* cut trailing ".exe" */
strcpy_s(pyhome, sizeof(pyhome), pyscript);
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058
hfind = FindFirstFile(pyscript, &fdata);
if (hfind != INVALID_HANDLE_VALUE) {
/* pyscript exists, close handle */
FindClose(hfind);
} else {
/* file pyscript isn't there, take <pyscript>exe.py */
strcat_s(pyscript, sizeof(pyscript), "exe.py");
}
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 pydll = NULL;
Adrian Buehlmann
exewrapper: add comments about PYTHONHOME...
r26664 /*
We first check, that environment variable PYTHONHOME is *not* set.
This just mimicks the behavior of the regular python.exe, which uses
PYTHONHOME to find its installation directory (if it has been set).
Note: Users of HackableMercurial are expected to *not* set PYTHONHOME!
*/
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
sizeof(envpyhome)) == 0)
{
Adrian Buehlmann
exewrapper: add comments about PYTHONHOME...
r26664 /*
Environment var PYTHONHOME is *not* set. Let's see if we are
running inside a HackableMercurial.
*/
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732
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);
Gregory Szorc
exewrapper: add .dll to LoadLibrary() argument...
r29019 strcat_s(pydllfile, sizeof(pydllfile),
"\\" HGPYTHONLIB ".dll");
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 pydll = LoadLibrary(pydllfile);
if (pydll == NULL) {
Adrian Buehlmann
exewrapper: report name of failed private DLL in error message...
r26663 err = "failed to load private Python DLL "
HGPYTHONLIB ".dll";
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 goto bail;
}
Py_SetPythonHome = (void*)GetProcAddress(pydll,
"Py_SetPythonHome");
if (Py_SetPythonHome == NULL) {
err = "failed to get Py_SetPythonHome";
goto bail;
}
Py_SetPythonHome(pyhome);
}
}
if (pydll == NULL) {
Gregory Szorc
exewrapper: add .dll to LoadLibrary() argument...
r29019 pydll = LoadLibrary(HGPYTHONLIB ".dll");
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 if (pydll == NULL) {
Adrian Buehlmann
exewrapper: report name of failed DLL in error message...
r26662 err = "failed to load Python DLL " HGPYTHONLIB ".dll";
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 goto bail;
}
}
Py_Main = (void*)GetProcAddress(pydll, "Py_Main");
if (Py_Main == NULL) {
err = "failed to get Py_Main";
goto bail;
}
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 /*
Only add the pyscript to the args, if it's not already there. It may
Adrian Buehlmann
exewrapper: use generic term script...
r17063 already be there, if the script spawned a child process of itself, in
Adrian Buehlmann
exewrapper: adding new exewrapper.c
r17058 the same way as it got called, that is, with the pyscript already in
place. So we optionally accept the pyscript as the first argument
(argv[1]), letting our exe taking the role of the python interpreter.
*/
if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
/*
pyscript is already in the args, so there is no need to copy
the args and we can directly call the python interpreter with
the original args.
*/
return Py_Main(argc, argv);
}
/*
Start assembling the args for the Python interpreter call. We put the
name of our exe (argv[0]) in the position where the python.exe
canonically is, and insert the pyscript next.
*/
pyargv = malloc((argc + 5) * sizeof(char*));
if (pyargv == NULL) {
err = "not enough memory";
goto bail;
}
n = 0;
pyargv[n++] = argv[0];
pyargv[n++] = pyscript;
/* copy remaining args from the command line */
for (i = 1; i < argc; i++)
pyargv[n++] = argv[i];
/* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
pyargv[n] = NULL;
ret = Py_Main(n, pyargv); /* The Python interpreter call */
free(pyargv);
return ret;
bail:
fprintf(stderr, "abort: %s\n", err);
return 255;
}