##// END OF EJS Templates
revset: add a 'descend' argument to followlines to return descendants...
revset: add a 'descend' argument to followlines to return descendants This is useful to follow changes in a block of lines forward in the history (for instance, when one wants to find out how a function evolved from a point in history). We added a 'descend' parameter to followlines(), which defaults to False. If True, followlines() returns descendants of startrev. Because context.blockdescendants() does not follow renames, these are not followed by the revset either, so history will end when a rename occurs (as can be seen in tests).

File last commit:

r31443:0241dd94 default
r31938:5e3b49de default
Show More
exewrapper.c
159 lines | 3.9 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;
Kostia Balytskyi
exewrapper: prefer HackableMercurial python if availbale...
r31443
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");
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732
Kostia Balytskyi
exewrapper: prefer HackableMercurial python if availbale...
r31443 hfind = FindFirstFile(pyhome, &fdata);
if (hfind != INVALID_HANDLE_VALUE) {
/* Path .\hg-python exists. We are probably in HackableMercurial
scenario, so let's load python dll from this dir. */
FindClose(hfind);
strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB ".dll");
pydll = LoadLibrary(pydllfile);
if (pydll == NULL) {
err = "failed to load private Python DLL " HGPYTHONLIB ".dll";
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 goto bail;
}
Kostia Balytskyi
exewrapper: prefer HackableMercurial python if availbale...
r31443 Py_SetPythonHome = (void*)GetProcAddress(pydll, "Py_SetPythonHome");
if (Py_SetPythonHome == NULL) {
err = "failed to get Py_SetPythonHome";
goto bail;
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 }
Kostia Balytskyi
exewrapper: prefer HackableMercurial python if availbale...
r31443 Py_SetPythonHome(pyhome);
Adrian Buehlmann
exewrapper: adapt for legacy HackableMercurial...
r17732 }
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;
}