[PATCH Variant A] hgexe: adding new hgexe.c
Adrian Buehlmann
adrian at cadifra.com
Thu Jun 28 15:10:37 CDT 2012
# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1340914025 -7200
# Node ID 76023d6a977b51a4088377fc9afc6a777d1ec658
# Parent 0a413b28fdd193483e544c1c1412985356ce0b6e
hgexe: adding new hgexe.c
diff --git a/mercurial/hgexe.c b/mercurial/hgexe.c
new file mode 100644
--- /dev/null
+++ b/mercurial/hgexe.c
@@ -0,0 +1,117 @@
+/*
+hgexe.c - wrapper for calling Mercurial on Windows
+
+Copyright (c) 2012 Adrian Buehlmann and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <Python.h>
+#include <windows.h>
+
+
+#ifdef __GNUC__
+int strcat_s(char *d, size_t n, const char *s)
+{
+ return !strncat(d, s, n);
+}
+#endif
+
+
+static char pyscript[MAX_PATH + 10];
+
+int main(int argc, char *argv[])
+{
+ char* dot;
+ int ret;
+ int i;
+ int n;
+ char **pyargv;
+ WIN32_FIND_DATA fdata;
+ HANDLE hfind;
+ const char *err;
+
+ if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
+ {
+ err = "GetModuleFileName failed";
+ goto bail;
+ }
+
+ dot = strrchr(pyscript, '.');
+ if (dot == NULL) {
+ err = "malformed module filename";
+ goto bail;
+ }
+ *dot = 0; /* cut trailing ".exe" */
+
+ 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");
+ }
+
+ /*
+ Only add the pyscript to the args, if it's not already there. It may
+ already be there, if Mercurial spawned a child process of itself, in
+ 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;
+}
More information about the Mercurial-devel
mailing list