##// END OF EJS Templates
exewrapper: adapt for legacy HackableMercurial...
Adrian Buehlmann -
r17732:93d97a21 default
parent child Browse files
Show More
@@ -1,57 +1,58 b''
1 syntax: glob
1 syntax: glob
2
2
3 *.elc
3 *.elc
4 *.orig
4 *.orig
5 *.rej
5 *.rej
6 *~
6 *~
7 *.mergebackup
7 *.mergebackup
8 *.o
8 *.o
9 *.so
9 *.so
10 *.dll
10 *.dll
11 *.exe
11 *.exe
12 *.pyd
12 *.pyd
13 *.pyc
13 *.pyc
14 *.pyo
14 *.pyo
15 *$py.class
15 *$py.class
16 *.swp
16 *.swp
17 *.prof
17 *.prof
18 *.zip
18 *.zip
19 \#*\#
19 \#*\#
20 .\#*
20 .\#*
21 tests/.coverage*
21 tests/.coverage*
22 tests/annotated
22 tests/annotated
23 tests/*.err
23 tests/*.err
24 tests/htmlcov
24 tests/htmlcov
25 build
25 build
26 contrib/hgsh/hgsh
26 contrib/hgsh/hgsh
27 dist
27 dist
28 doc/*.[0-9]
28 doc/*.[0-9]
29 doc/*.[0-9].gendoc.txt
29 doc/*.[0-9].gendoc.txt
30 doc/*.[0-9].{x,ht}ml
30 doc/*.[0-9].{x,ht}ml
31 MANIFEST
31 MANIFEST
32 MANIFEST.in
32 MANIFEST.in
33 patches
33 patches
34 mercurial/__version__.py
34 mercurial/__version__.py
35 mercurial/hgpythonlib.h
35 mercurial.egg-info
36 mercurial.egg-info
36 .DS_Store
37 .DS_Store
37 tags
38 tags
38 cscope.*
39 cscope.*
39 i18n/hg.pot
40 i18n/hg.pot
40 locale/*/LC_MESSAGES/hg.mo
41 locale/*/LC_MESSAGES/hg.mo
41 hgext/__index__.py
42 hgext/__index__.py
42
43
43 # files installed with a local --pure build
44 # files installed with a local --pure build
44 mercurial/base85.py
45 mercurial/base85.py
45 mercurial/bdiff.py
46 mercurial/bdiff.py
46 mercurial/diffhelpers.py
47 mercurial/diffhelpers.py
47 mercurial/mpatch.py
48 mercurial/mpatch.py
48 mercurial/osutil.py
49 mercurial/osutil.py
49 mercurial/parsers.py
50 mercurial/parsers.py
50
51
51 syntax: regexp
52 syntax: regexp
52 ^\.pc/
53 ^\.pc/
53 ^\.(pydev)?project
54 ^\.(pydev)?project
54
55
55 # hackable windows distribution additions
56 # hackable windows distribution additions
56 ^hg-python
57 ^hg-python
57 ^hg.py$
58 ^hg.py$
@@ -1,101 +1,164 b''
1 /*
1 /*
2 exewrapper.c - wrapper for calling a python script on Windows
2 exewrapper.c - wrapper for calling a python script on Windows
3
3
4 Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
4 Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
5
5
6 This software may be used and distributed according to the terms of the
6 This software may be used and distributed according to the terms of the
7 GNU General Public License version 2 or any later version.
7 GNU General Public License version 2 or any later version.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <stdio.h>
11 #include <windows.h>
11 #include <windows.h>
12
12
13 #include "hgpythonlib.h"
13
14
14 #ifdef __GNUC__
15 #ifdef __GNUC__
15 int strcat_s(char *d, size_t n, const char *s)
16 int strcat_s(char *d, size_t n, const char *s)
16 {
17 {
17 return !strncat(d, s, n);
18 return !strncat(d, s, n);
18 }
19 }
20 int strcpy_s(char *d, size_t n, const char *s)
21 {
22 return !strncpy(d, s, n);
23 }
19 #endif
24 #endif
20
25
21
26
22 static char pyscript[MAX_PATH + 10];
27 static char pyscript[MAX_PATH + 10];
28 static char pyhome[MAX_PATH + 10];
29 static char envpyhome[MAX_PATH + 10];
30 static char pydllfile[MAX_PATH + 10];
23
31
24 int main(int argc, char *argv[])
32 int main(int argc, char *argv[])
25 {
33 {
26 char *dot;
34 char *p;
27 int ret;
35 int ret;
28 int i;
36 int i;
29 int n;
37 int n;
30 char **pyargv;
38 char **pyargv;
31 WIN32_FIND_DATA fdata;
39 WIN32_FIND_DATA fdata;
32 HANDLE hfind;
40 HANDLE hfind;
33 const char *err;
41 const char *err;
42 HMODULE pydll;
43 void (__cdecl *Py_SetPythonHome)(char *home);
44 int (__cdecl *Py_Main)(int argc, char *argv[]);
34
45
35 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
46 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
36 {
47 {
37 err = "GetModuleFileName failed";
48 err = "GetModuleFileName failed";
38 goto bail;
49 goto bail;
39 }
50 }
40
51
41 dot = strrchr(pyscript, '.');
52 p = strrchr(pyscript, '.');
42 if (dot == NULL) {
53 if (p == NULL) {
43 err = "malformed module filename";
54 err = "malformed module filename";
44 goto bail;
55 goto bail;
45 }
56 }
46 *dot = 0; /* cut trailing ".exe" */
57 *p = 0; /* cut trailing ".exe" */
58 strcpy_s(pyhome, sizeof(pyhome), pyscript);
47
59
48 hfind = FindFirstFile(pyscript, &fdata);
60 hfind = FindFirstFile(pyscript, &fdata);
49 if (hfind != INVALID_HANDLE_VALUE) {
61 if (hfind != INVALID_HANDLE_VALUE) {
50 /* pyscript exists, close handle */
62 /* pyscript exists, close handle */
51 FindClose(hfind);
63 FindClose(hfind);
52 } else {
64 } else {
53 /* file pyscript isn't there, take <pyscript>exe.py */
65 /* file pyscript isn't there, take <pyscript>exe.py */
54 strcat_s(pyscript, sizeof(pyscript), "exe.py");
66 strcat_s(pyscript, sizeof(pyscript), "exe.py");
55 }
67 }
56
68
69 pydll = NULL;
70 if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
71 sizeof(envpyhome)) == 0)
72 {
73 /* environment var PYTHONHOME is not set */
74
75 p = strrchr(pyhome, '\\');
76 if (p == NULL) {
77 err = "can't find backslash in module filename";
78 goto bail;
79 }
80 *p = 0; /* cut at directory */
81
82 /* check for private Python of HackableMercurial */
83 strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
84
85 hfind = FindFirstFile(pyhome, &fdata);
86 if (hfind != INVALID_HANDLE_VALUE) {
87 /* path pyhome exists, let's use it */
88 FindClose(hfind);
89 strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
90 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB);
91 pydll = LoadLibrary(pydllfile);
92 if (pydll == NULL) {
93 err = "failed to load private Python DLL";
94 goto bail;
95 }
96 Py_SetPythonHome = (void*)GetProcAddress(pydll,
97 "Py_SetPythonHome");
98 if (Py_SetPythonHome == NULL) {
99 err = "failed to get Py_SetPythonHome";
100 goto bail;
101 }
102 Py_SetPythonHome(pyhome);
103 }
104 }
105
106 if (pydll == NULL) {
107 pydll = LoadLibrary(HGPYTHONLIB);
108 if (pydll == NULL) {
109 err = "failed to load Python DLL";
110 goto bail;
111 }
112 }
113
114 Py_Main = (void*)GetProcAddress(pydll, "Py_Main");
115 if (Py_Main == NULL) {
116 err = "failed to get Py_Main";
117 goto bail;
118 }
119
57 /*
120 /*
58 Only add the pyscript to the args, if it's not already there. It may
121 Only add the pyscript to the args, if it's not already there. It may
59 already be there, if the script spawned a child process of itself, in
122 already be there, if the script spawned a child process of itself, in
60 the same way as it got called, that is, with the pyscript already in
123 the same way as it got called, that is, with the pyscript already in
61 place. So we optionally accept the pyscript as the first argument
124 place. So we optionally accept the pyscript as the first argument
62 (argv[1]), letting our exe taking the role of the python interpreter.
125 (argv[1]), letting our exe taking the role of the python interpreter.
63 */
126 */
64 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
127 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
65 /*
128 /*
66 pyscript is already in the args, so there is no need to copy
129 pyscript is already in the args, so there is no need to copy
67 the args and we can directly call the python interpreter with
130 the args and we can directly call the python interpreter with
68 the original args.
131 the original args.
69 */
132 */
70 return Py_Main(argc, argv);
133 return Py_Main(argc, argv);
71 }
134 }
72
135
73 /*
136 /*
74 Start assembling the args for the Python interpreter call. We put the
137 Start assembling the args for the Python interpreter call. We put the
75 name of our exe (argv[0]) in the position where the python.exe
138 name of our exe (argv[0]) in the position where the python.exe
76 canonically is, and insert the pyscript next.
139 canonically is, and insert the pyscript next.
77 */
140 */
78 pyargv = malloc((argc + 5) * sizeof(char*));
141 pyargv = malloc((argc + 5) * sizeof(char*));
79 if (pyargv == NULL) {
142 if (pyargv == NULL) {
80 err = "not enough memory";
143 err = "not enough memory";
81 goto bail;
144 goto bail;
82 }
145 }
83 n = 0;
146 n = 0;
84 pyargv[n++] = argv[0];
147 pyargv[n++] = argv[0];
85 pyargv[n++] = pyscript;
148 pyargv[n++] = pyscript;
86
149
87 /* copy remaining args from the command line */
150 /* copy remaining args from the command line */
88 for (i = 1; i < argc; i++)
151 for (i = 1; i < argc; i++)
89 pyargv[n++] = argv[i];
152 pyargv[n++] = argv[i];
90 /* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
153 /* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
91 pyargv[n] = NULL;
154 pyargv[n] = NULL;
92
155
93 ret = Py_Main(n, pyargv); /* The Python interpreter call */
156 ret = Py_Main(n, pyargv); /* The Python interpreter call */
94
157
95 free(pyargv);
158 free(pyargv);
96 return ret;
159 return ret;
97
160
98 bail:
161 bail:
99 fprintf(stderr, "abort: %s\n", err);
162 fprintf(stderr, "abort: %s\n", err);
100 return 255;
163 return 255;
101 }
164 }
@@ -1,534 +1,538 b''
1 #
1 #
2 # This is the mercurial setup script.
2 # This is the mercurial setup script.
3 #
3 #
4 # 'python setup.py install', or
4 # 'python setup.py install', or
5 # 'python setup.py --help' for more options
5 # 'python setup.py --help' for more options
6
6
7 import sys, platform
7 import sys, platform
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10
10
11 if sys.version_info[0] >= 3:
11 if sys.version_info[0] >= 3:
12 def b(s):
12 def b(s):
13 '''A helper function to emulate 2.6+ bytes literals using string
13 '''A helper function to emulate 2.6+ bytes literals using string
14 literals.'''
14 literals.'''
15 return s.encode('latin1')
15 return s.encode('latin1')
16 else:
16 else:
17 def b(s):
17 def b(s):
18 '''A helper function to emulate 2.6+ bytes literals using string
18 '''A helper function to emulate 2.6+ bytes literals using string
19 literals.'''
19 literals.'''
20 return s
20 return s
21
21
22 # Solaris Python packaging brain damage
22 # Solaris Python packaging brain damage
23 try:
23 try:
24 import hashlib
24 import hashlib
25 sha = hashlib.sha1()
25 sha = hashlib.sha1()
26 except ImportError:
26 except ImportError:
27 try:
27 try:
28 import sha
28 import sha
29 except ImportError:
29 except ImportError:
30 raise SystemExit(
30 raise SystemExit(
31 "Couldn't import standard hashlib (incomplete Python install).")
31 "Couldn't import standard hashlib (incomplete Python install).")
32
32
33 try:
33 try:
34 import zlib
34 import zlib
35 except ImportError:
35 except ImportError:
36 raise SystemExit(
36 raise SystemExit(
37 "Couldn't import standard zlib (incomplete Python install).")
37 "Couldn't import standard zlib (incomplete Python install).")
38
38
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 isironpython = False
40 isironpython = False
41 try:
41 try:
42 isironpython = (platform.python_implementation()
42 isironpython = (platform.python_implementation()
43 .lower().find("ironpython") != -1)
43 .lower().find("ironpython") != -1)
44 except AttributeError:
44 except AttributeError:
45 pass
45 pass
46
46
47 if isironpython:
47 if isironpython:
48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 else:
49 else:
50 try:
50 try:
51 import bz2
51 import bz2
52 except ImportError:
52 except ImportError:
53 raise SystemExit(
53 raise SystemExit(
54 "Couldn't import standard bz2 (incomplete Python install).")
54 "Couldn't import standard bz2 (incomplete Python install).")
55
55
56 import os, subprocess, time
56 import os, subprocess, time
57 import shutil
57 import shutil
58 import tempfile
58 import tempfile
59 from distutils import log
59 from distutils import log
60 from distutils.core import setup, Command, Extension
60 from distutils.core import setup, Command, Extension
61 from distutils.dist import Distribution
61 from distutils.dist import Distribution
62 from distutils.command.build import build
62 from distutils.command.build import build
63 from distutils.command.build_ext import build_ext
63 from distutils.command.build_ext import build_ext
64 from distutils.command.build_py import build_py
64 from distutils.command.build_py import build_py
65 from distutils.command.install_scripts import install_scripts
65 from distutils.command.install_scripts import install_scripts
66 from distutils.spawn import spawn, find_executable
66 from distutils.spawn import spawn, find_executable
67 from distutils.ccompiler import new_compiler
67 from distutils.ccompiler import new_compiler
68 from distutils import cygwinccompiler
68 from distutils import cygwinccompiler
69 from distutils.errors import CCompilerError, DistutilsExecError
69 from distutils.errors import CCompilerError, DistutilsExecError
70 from distutils.sysconfig import get_python_inc
70 from distutils.sysconfig import get_python_inc
71 from distutils.version import StrictVersion
71 from distutils.version import StrictVersion
72
72
73 convert2to3 = '--c2to3' in sys.argv
73 convert2to3 = '--c2to3' in sys.argv
74 if convert2to3:
74 if convert2to3:
75 try:
75 try:
76 from distutils.command.build_py import build_py_2to3 as build_py
76 from distutils.command.build_py import build_py_2to3 as build_py
77 from lib2to3.refactor import get_fixers_from_package as getfixers
77 from lib2to3.refactor import get_fixers_from_package as getfixers
78 except ImportError:
78 except ImportError:
79 if sys.version_info[0] < 3:
79 if sys.version_info[0] < 3:
80 raise SystemExit("--c2to3 is only compatible with python3.")
80 raise SystemExit("--c2to3 is only compatible with python3.")
81 raise
81 raise
82 sys.path.append('contrib')
82 sys.path.append('contrib')
83 elif sys.version_info[0] >= 3:
83 elif sys.version_info[0] >= 3:
84 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
84 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
85
85
86 scripts = ['hg']
86 scripts = ['hg']
87 if os.name == 'nt':
87 if os.name == 'nt':
88 scripts.append('contrib/win32/hg.bat')
88 scripts.append('contrib/win32/hg.bat')
89
89
90 # simplified version of distutils.ccompiler.CCompiler.has_function
90 # simplified version of distutils.ccompiler.CCompiler.has_function
91 # that actually removes its temporary files.
91 # that actually removes its temporary files.
92 def hasfunction(cc, funcname):
92 def hasfunction(cc, funcname):
93 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
93 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
94 devnull = oldstderr = None
94 devnull = oldstderr = None
95 try:
95 try:
96 try:
96 try:
97 fname = os.path.join(tmpdir, 'funcname.c')
97 fname = os.path.join(tmpdir, 'funcname.c')
98 f = open(fname, 'w')
98 f = open(fname, 'w')
99 f.write('int main(void) {\n')
99 f.write('int main(void) {\n')
100 f.write(' %s();\n' % funcname)
100 f.write(' %s();\n' % funcname)
101 f.write('}\n')
101 f.write('}\n')
102 f.close()
102 f.close()
103 # Redirect stderr to /dev/null to hide any error messages
103 # Redirect stderr to /dev/null to hide any error messages
104 # from the compiler.
104 # from the compiler.
105 # This will have to be changed if we ever have to check
105 # This will have to be changed if we ever have to check
106 # for a function on Windows.
106 # for a function on Windows.
107 devnull = open('/dev/null', 'w')
107 devnull = open('/dev/null', 'w')
108 oldstderr = os.dup(sys.stderr.fileno())
108 oldstderr = os.dup(sys.stderr.fileno())
109 os.dup2(devnull.fileno(), sys.stderr.fileno())
109 os.dup2(devnull.fileno(), sys.stderr.fileno())
110 objects = cc.compile([fname], output_dir=tmpdir)
110 objects = cc.compile([fname], output_dir=tmpdir)
111 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
111 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
112 except Exception:
112 except Exception:
113 return False
113 return False
114 return True
114 return True
115 finally:
115 finally:
116 if oldstderr is not None:
116 if oldstderr is not None:
117 os.dup2(oldstderr, sys.stderr.fileno())
117 os.dup2(oldstderr, sys.stderr.fileno())
118 if devnull is not None:
118 if devnull is not None:
119 devnull.close()
119 devnull.close()
120 shutil.rmtree(tmpdir)
120 shutil.rmtree(tmpdir)
121
121
122 # py2exe needs to be installed to work
122 # py2exe needs to be installed to work
123 try:
123 try:
124 import py2exe
124 import py2exe
125 py2exeloaded = True
125 py2exeloaded = True
126 # import py2exe's patched Distribution class
126 # import py2exe's patched Distribution class
127 from distutils.core import Distribution
127 from distutils.core import Distribution
128 except ImportError:
128 except ImportError:
129 py2exeloaded = False
129 py2exeloaded = False
130
130
131 def runcmd(cmd, env):
131 def runcmd(cmd, env):
132 if sys.platform == 'plan9':
132 if sys.platform == 'plan9':
133 # subprocess kludge to work around issues in half-baked Python
133 # subprocess kludge to work around issues in half-baked Python
134 # ports, notably bichued/python:
134 # ports, notably bichued/python:
135 _, out, err = os.popen3(cmd)
135 _, out, err = os.popen3(cmd)
136 return str(out), str(err)
136 return str(out), str(err)
137 else:
137 else:
138 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
138 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
139 stderr=subprocess.PIPE, env=env)
139 stderr=subprocess.PIPE, env=env)
140 out, err = p.communicate()
140 out, err = p.communicate()
141 return out, err
141 return out, err
142
142
143 def runhg(cmd, env):
143 def runhg(cmd, env):
144 out, err = runcmd(cmd, env)
144 out, err = runcmd(cmd, env)
145 # If root is executing setup.py, but the repository is owned by
145 # If root is executing setup.py, but the repository is owned by
146 # another user (as in "sudo python setup.py install") we will get
146 # another user (as in "sudo python setup.py install") we will get
147 # trust warnings since the .hg/hgrc file is untrusted. That is
147 # trust warnings since the .hg/hgrc file is untrusted. That is
148 # fine, we don't want to load it anyway. Python may warn about
148 # fine, we don't want to load it anyway. Python may warn about
149 # a missing __init__.py in mercurial/locale, we also ignore that.
149 # a missing __init__.py in mercurial/locale, we also ignore that.
150 err = [e for e in err.splitlines()
150 err = [e for e in err.splitlines()
151 if not e.startswith(b('Not trusting file')) \
151 if not e.startswith(b('Not trusting file')) \
152 and not e.startswith(b('warning: Not importing'))]
152 and not e.startswith(b('warning: Not importing'))]
153 if err:
153 if err:
154 return ''
154 return ''
155 return out
155 return out
156
156
157 version = ''
157 version = ''
158
158
159 # Execute hg out of this directory with a custom environment which
159 # Execute hg out of this directory with a custom environment which
160 # includes the pure Python modules in mercurial/pure. We also take
160 # includes the pure Python modules in mercurial/pure. We also take
161 # care to not use any hgrc files and do no localization.
161 # care to not use any hgrc files and do no localization.
162 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
162 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
163 env = {'PYTHONPATH': os.pathsep.join(pypath),
163 env = {'PYTHONPATH': os.pathsep.join(pypath),
164 'HGRCPATH': '',
164 'HGRCPATH': '',
165 'LANGUAGE': 'C'}
165 'LANGUAGE': 'C'}
166 if 'LD_LIBRARY_PATH' in os.environ:
166 if 'LD_LIBRARY_PATH' in os.environ:
167 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
167 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
168 if 'SystemRoot' in os.environ:
168 if 'SystemRoot' in os.environ:
169 # Copy SystemRoot into the custom environment for Python 2.6
169 # Copy SystemRoot into the custom environment for Python 2.6
170 # under Windows. Otherwise, the subprocess will fail with
170 # under Windows. Otherwise, the subprocess will fail with
171 # error 0xc0150004. See: http://bugs.python.org/issue3440
171 # error 0xc0150004. See: http://bugs.python.org/issue3440
172 env['SystemRoot'] = os.environ['SystemRoot']
172 env['SystemRoot'] = os.environ['SystemRoot']
173
173
174 if os.path.isdir('.hg'):
174 if os.path.isdir('.hg'):
175 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
175 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
176 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
176 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
177 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
177 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
178 if numerictags: # tag(s) found
178 if numerictags: # tag(s) found
179 version = numerictags[-1]
179 version = numerictags[-1]
180 if hgid.endswith('+'): # propagate the dirty status to the tag
180 if hgid.endswith('+'): # propagate the dirty status to the tag
181 version += '+'
181 version += '+'
182 else: # no tag found
182 else: # no tag found
183 cmd = [sys.executable, 'hg', 'parents', '--template',
183 cmd = [sys.executable, 'hg', 'parents', '--template',
184 '{latesttag}+{latesttagdistance}-']
184 '{latesttag}+{latesttagdistance}-']
185 version = runhg(cmd, env) + hgid
185 version = runhg(cmd, env) + hgid
186 if version.endswith('+'):
186 if version.endswith('+'):
187 version += time.strftime('%Y%m%d')
187 version += time.strftime('%Y%m%d')
188 elif os.path.exists('.hg_archival.txt'):
188 elif os.path.exists('.hg_archival.txt'):
189 kw = dict([[t.strip() for t in l.split(':', 1)]
189 kw = dict([[t.strip() for t in l.split(':', 1)]
190 for l in open('.hg_archival.txt')])
190 for l in open('.hg_archival.txt')])
191 if 'tag' in kw:
191 if 'tag' in kw:
192 version = kw['tag']
192 version = kw['tag']
193 elif 'latesttag' in kw:
193 elif 'latesttag' in kw:
194 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
194 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
195 else:
195 else:
196 version = kw.get('node', '')[:12]
196 version = kw.get('node', '')[:12]
197
197
198 if version:
198 if version:
199 f = open("mercurial/__version__.py", "w")
199 f = open("mercurial/__version__.py", "w")
200 f.write('# this file is autogenerated by setup.py\n')
200 f.write('# this file is autogenerated by setup.py\n')
201 f.write('version = "%s"\n' % version)
201 f.write('version = "%s"\n' % version)
202 f.close()
202 f.close()
203
203
204
204
205 try:
205 try:
206 from mercurial import __version__
206 from mercurial import __version__
207 version = __version__.version
207 version = __version__.version
208 except ImportError:
208 except ImportError:
209 version = 'unknown'
209 version = 'unknown'
210
210
211 class hgbuild(build):
211 class hgbuild(build):
212 # Insert hgbuildmo first so that files in mercurial/locale/ are found
212 # Insert hgbuildmo first so that files in mercurial/locale/ are found
213 # when build_py is run next.
213 # when build_py is run next.
214 sub_commands = [('build_mo', None),
214 sub_commands = [('build_mo', None),
215
215
216 # We also need build_ext before build_py. Otherwise, when 2to3 is
216 # We also need build_ext before build_py. Otherwise, when 2to3 is
217 # called (in build_py), it will not find osutil & friends,
217 # called (in build_py), it will not find osutil & friends,
218 # thinking that those modules are global and, consequently, making
218 # thinking that those modules are global and, consequently, making
219 # a mess, now that all module imports are global.
219 # a mess, now that all module imports are global.
220
220
221 ('build_ext', build.has_ext_modules),
221 ('build_ext', build.has_ext_modules),
222 ] + build.sub_commands
222 ] + build.sub_commands
223
223
224 class hgbuildmo(build):
224 class hgbuildmo(build):
225
225
226 description = "build translations (.mo files)"
226 description = "build translations (.mo files)"
227
227
228 def run(self):
228 def run(self):
229 if not find_executable('msgfmt'):
229 if not find_executable('msgfmt'):
230 self.warn("could not find msgfmt executable, no translations "
230 self.warn("could not find msgfmt executable, no translations "
231 "will be built")
231 "will be built")
232 return
232 return
233
233
234 podir = 'i18n'
234 podir = 'i18n'
235 if not os.path.isdir(podir):
235 if not os.path.isdir(podir):
236 self.warn("could not find %s/ directory" % podir)
236 self.warn("could not find %s/ directory" % podir)
237 return
237 return
238
238
239 join = os.path.join
239 join = os.path.join
240 for po in os.listdir(podir):
240 for po in os.listdir(podir):
241 if not po.endswith('.po'):
241 if not po.endswith('.po'):
242 continue
242 continue
243 pofile = join(podir, po)
243 pofile = join(podir, po)
244 modir = join('locale', po[:-3], 'LC_MESSAGES')
244 modir = join('locale', po[:-3], 'LC_MESSAGES')
245 mofile = join(modir, 'hg.mo')
245 mofile = join(modir, 'hg.mo')
246 mobuildfile = join('mercurial', mofile)
246 mobuildfile = join('mercurial', mofile)
247 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
247 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
248 if sys.platform != 'sunos5':
248 if sys.platform != 'sunos5':
249 # msgfmt on Solaris does not know about -c
249 # msgfmt on Solaris does not know about -c
250 cmd.append('-c')
250 cmd.append('-c')
251 self.mkpath(join('mercurial', modir))
251 self.mkpath(join('mercurial', modir))
252 self.make_file([pofile], mobuildfile, spawn, (cmd,))
252 self.make_file([pofile], mobuildfile, spawn, (cmd,))
253
253
254
254
255 class hgdist(Distribution):
255 class hgdist(Distribution):
256 pure = 0
256 pure = 0
257
257
258 global_options = Distribution.global_options + \
258 global_options = Distribution.global_options + \
259 [('pure', None, "use pure (slow) Python "
259 [('pure', None, "use pure (slow) Python "
260 "code instead of C extensions"),
260 "code instead of C extensions"),
261 ('c2to3', None, "(experimental!) convert "
261 ('c2to3', None, "(experimental!) convert "
262 "code with 2to3"),
262 "code with 2to3"),
263 ]
263 ]
264
264
265 def has_ext_modules(self):
265 def has_ext_modules(self):
266 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
266 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
267 # too late for some cases
267 # too late for some cases
268 return not self.pure and Distribution.has_ext_modules(self)
268 return not self.pure and Distribution.has_ext_modules(self)
269
269
270 class hgbuildext(build_ext):
270 class hgbuildext(build_ext):
271
271
272 def build_extension(self, ext):
272 def build_extension(self, ext):
273 try:
273 try:
274 build_ext.build_extension(self, ext)
274 build_ext.build_extension(self, ext)
275 except CCompilerError:
275 except CCompilerError:
276 if not getattr(ext, 'optional', False):
276 if not getattr(ext, 'optional', False):
277 raise
277 raise
278 log.warn("Failed to build optional extension '%s' (skipping)",
278 log.warn("Failed to build optional extension '%s' (skipping)",
279 ext.name)
279 ext.name)
280
280
281 class hgbuildpy(build_py):
281 class hgbuildpy(build_py):
282 if convert2to3:
282 if convert2to3:
283 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
283 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
284 getfixers("hgfixes")))
284 getfixers("hgfixes")))
285
285
286 def finalize_options(self):
286 def finalize_options(self):
287 build_py.finalize_options(self)
287 build_py.finalize_options(self)
288
288
289 if self.distribution.pure:
289 if self.distribution.pure:
290 if self.py_modules is None:
290 if self.py_modules is None:
291 self.py_modules = []
291 self.py_modules = []
292 for ext in self.distribution.ext_modules:
292 for ext in self.distribution.ext_modules:
293 if ext.name.startswith("mercurial."):
293 if ext.name.startswith("mercurial."):
294 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
294 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
295 self.distribution.ext_modules = []
295 self.distribution.ext_modules = []
296 else:
296 else:
297 if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
297 if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
298 raise SystemExit('Python headers are required to build '
298 raise SystemExit('Python headers are required to build '
299 'Mercurial')
299 'Mercurial')
300
300
301 def find_modules(self):
301 def find_modules(self):
302 modules = build_py.find_modules(self)
302 modules = build_py.find_modules(self)
303 for module in modules:
303 for module in modules:
304 if module[0] == "mercurial.pure":
304 if module[0] == "mercurial.pure":
305 if module[1] != "__init__":
305 if module[1] != "__init__":
306 yield ("mercurial", module[1], module[2])
306 yield ("mercurial", module[1], module[2])
307 else:
307 else:
308 yield module
308 yield module
309
309
310 class buildhgextindex(Command):
310 class buildhgextindex(Command):
311 description = 'generate prebuilt index of hgext (for frozen package)'
311 description = 'generate prebuilt index of hgext (for frozen package)'
312 user_options = []
312 user_options = []
313 _indexfilename = 'hgext/__index__.py'
313 _indexfilename = 'hgext/__index__.py'
314
314
315 def initialize_options(self):
315 def initialize_options(self):
316 pass
316 pass
317
317
318 def finalize_options(self):
318 def finalize_options(self):
319 pass
319 pass
320
320
321 def run(self):
321 def run(self):
322 if os.path.exists(self._indexfilename):
322 if os.path.exists(self._indexfilename):
323 os.unlink(self._indexfilename)
323 os.unlink(self._indexfilename)
324
324
325 # here no extension enabled, disabled() lists up everything
325 # here no extension enabled, disabled() lists up everything
326 code = ('import pprint; from mercurial import extensions; '
326 code = ('import pprint; from mercurial import extensions; '
327 'pprint.pprint(extensions.disabled())')
327 'pprint.pprint(extensions.disabled())')
328 out, err = runcmd([sys.executable, '-c', code], env)
328 out, err = runcmd([sys.executable, '-c', code], env)
329 if err:
329 if err:
330 raise DistutilsExecError(err)
330 raise DistutilsExecError(err)
331
331
332 f = open(self._indexfilename, 'w')
332 f = open(self._indexfilename, 'w')
333 f.write('# this file is autogenerated by setup.py\n')
333 f.write('# this file is autogenerated by setup.py\n')
334 f.write('docs = ')
334 f.write('docs = ')
335 f.write(out)
335 f.write(out)
336 f.close()
336 f.close()
337
337
338 class buildhgexe(build_ext):
338 class buildhgexe(build_ext):
339 description = 'compile hg.exe from mercurial/exewrapper.c'
339 description = 'compile hg.exe from mercurial/exewrapper.c'
340
340
341 def build_extensions(self):
341 def build_extensions(self):
342 if os.name != 'nt':
342 if os.name != 'nt':
343 return
343 return
344 if isinstance(self.compiler, HackedMingw32CCompiler):
344 if isinstance(self.compiler, HackedMingw32CCompiler):
345 self.compiler.compiler_so = self.compiler.compiler # no -mdll
345 self.compiler.compiler_so = self.compiler.compiler # no -mdll
346 self.compiler.dll_libraries = [] # no -lmsrvc90
346 self.compiler.dll_libraries = [] # no -lmsrvc90
347 hv = sys.hexversion
348 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
349 f = open('mercurial/hgpythonlib.h', 'wb')
350 f.write('/* this file is autogenerated by setup.py */\n')
351 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
352 f.close()
347 objects = self.compiler.compile(['mercurial/exewrapper.c'],
353 objects = self.compiler.compile(['mercurial/exewrapper.c'],
348 output_dir=self.build_temp)
354 output_dir=self.build_temp)
349 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
355 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
350 target = os.path.join(dir, 'hg')
356 target = os.path.join(dir, 'hg')
351 pythonlib = ("python%d%d" %
352 (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
353 self.compiler.link_executable(objects, target,
357 self.compiler.link_executable(objects, target,
354 libraries=[pythonlib],
358 libraries=[],
355 output_dir=self.build_temp)
359 output_dir=self.build_temp)
356
360
357 class hginstallscripts(install_scripts):
361 class hginstallscripts(install_scripts):
358 '''
362 '''
359 This is a specialization of install_scripts that replaces the @LIBDIR@ with
363 This is a specialization of install_scripts that replaces the @LIBDIR@ with
360 the configured directory for modules. If possible, the path is made relative
364 the configured directory for modules. If possible, the path is made relative
361 to the directory for scripts.
365 to the directory for scripts.
362 '''
366 '''
363
367
364 def initialize_options(self):
368 def initialize_options(self):
365 install_scripts.initialize_options(self)
369 install_scripts.initialize_options(self)
366
370
367 self.install_lib = None
371 self.install_lib = None
368
372
369 def finalize_options(self):
373 def finalize_options(self):
370 install_scripts.finalize_options(self)
374 install_scripts.finalize_options(self)
371 self.set_undefined_options('install',
375 self.set_undefined_options('install',
372 ('install_lib', 'install_lib'))
376 ('install_lib', 'install_lib'))
373
377
374 def run(self):
378 def run(self):
375 install_scripts.run(self)
379 install_scripts.run(self)
376
380
377 if (os.path.splitdrive(self.install_dir)[0] !=
381 if (os.path.splitdrive(self.install_dir)[0] !=
378 os.path.splitdrive(self.install_lib)[0]):
382 os.path.splitdrive(self.install_lib)[0]):
379 # can't make relative paths from one drive to another, so use an
383 # can't make relative paths from one drive to another, so use an
380 # absolute path instead
384 # absolute path instead
381 libdir = self.install_lib
385 libdir = self.install_lib
382 else:
386 else:
383 common = os.path.commonprefix((self.install_dir, self.install_lib))
387 common = os.path.commonprefix((self.install_dir, self.install_lib))
384 rest = self.install_dir[len(common):]
388 rest = self.install_dir[len(common):]
385 uplevel = len([n for n in os.path.split(rest) if n])
389 uplevel = len([n for n in os.path.split(rest) if n])
386
390
387 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
391 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
388
392
389 for outfile in self.outfiles:
393 for outfile in self.outfiles:
390 fp = open(outfile, 'rb')
394 fp = open(outfile, 'rb')
391 data = fp.read()
395 data = fp.read()
392 fp.close()
396 fp.close()
393
397
394 # skip binary files
398 # skip binary files
395 if b('\0') in data:
399 if b('\0') in data:
396 continue
400 continue
397
401
398 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
402 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
399 fp = open(outfile, 'wb')
403 fp = open(outfile, 'wb')
400 fp.write(data)
404 fp.write(data)
401 fp.close()
405 fp.close()
402
406
403 cmdclass = {'build': hgbuild,
407 cmdclass = {'build': hgbuild,
404 'build_mo': hgbuildmo,
408 'build_mo': hgbuildmo,
405 'build_ext': hgbuildext,
409 'build_ext': hgbuildext,
406 'build_py': hgbuildpy,
410 'build_py': hgbuildpy,
407 'build_hgextindex': buildhgextindex,
411 'build_hgextindex': buildhgextindex,
408 'install_scripts': hginstallscripts,
412 'install_scripts': hginstallscripts,
409 'build_hgexe': buildhgexe,
413 'build_hgexe': buildhgexe,
410 }
414 }
411
415
412 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
416 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
413 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
417 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
414 'hgext.largefiles']
418 'hgext.largefiles']
415
419
416 pymodules = []
420 pymodules = []
417
421
418 extmodules = [
422 extmodules = [
419 Extension('mercurial.base85', ['mercurial/base85.c']),
423 Extension('mercurial.base85', ['mercurial/base85.c']),
420 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
424 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
421 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
425 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
422 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
426 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
423 Extension('mercurial.parsers', ['mercurial/parsers.c',
427 Extension('mercurial.parsers', ['mercurial/parsers.c',
424 'mercurial/pathencode.c']),
428 'mercurial/pathencode.c']),
425 ]
429 ]
426
430
427 osutil_ldflags = []
431 osutil_ldflags = []
428
432
429 if sys.platform == 'darwin':
433 if sys.platform == 'darwin':
430 osutil_ldflags += ['-framework', 'ApplicationServices']
434 osutil_ldflags += ['-framework', 'ApplicationServices']
431
435
432 # disable osutil.c under windows + python 2.4 (issue1364)
436 # disable osutil.c under windows + python 2.4 (issue1364)
433 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
437 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
434 pymodules.append('mercurial.pure.osutil')
438 pymodules.append('mercurial.pure.osutil')
435 else:
439 else:
436 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
440 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
437 extra_link_args=osutil_ldflags))
441 extra_link_args=osutil_ldflags))
438
442
439 # the -mno-cygwin option has been deprecated for years
443 # the -mno-cygwin option has been deprecated for years
440 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
444 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
441
445
442 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
446 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
443 def __init__(self, *args, **kwargs):
447 def __init__(self, *args, **kwargs):
444 Mingw32CCompiler.__init__(self, *args, **kwargs)
448 Mingw32CCompiler.__init__(self, *args, **kwargs)
445 for i in 'compiler compiler_so linker_exe linker_so'.split():
449 for i in 'compiler compiler_so linker_exe linker_so'.split():
446 try:
450 try:
447 getattr(self, i).remove('-mno-cygwin')
451 getattr(self, i).remove('-mno-cygwin')
448 except ValueError:
452 except ValueError:
449 pass
453 pass
450
454
451 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
455 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
452
456
453 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
457 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
454 # The inotify extension is only usable with Linux 2.6 kernels.
458 # The inotify extension is only usable with Linux 2.6 kernels.
455 # You also need a reasonably recent C library.
459 # You also need a reasonably recent C library.
456 # In any case, if it fails to build the error will be skipped ('optional').
460 # In any case, if it fails to build the error will be skipped ('optional').
457 cc = new_compiler()
461 cc = new_compiler()
458 if hasfunction(cc, 'inotify_add_watch'):
462 if hasfunction(cc, 'inotify_add_watch'):
459 inotify = Extension('hgext.inotify.linux._inotify',
463 inotify = Extension('hgext.inotify.linux._inotify',
460 ['hgext/inotify/linux/_inotify.c'],
464 ['hgext/inotify/linux/_inotify.c'],
461 ['mercurial'])
465 ['mercurial'])
462 inotify.optional = True
466 inotify.optional = True
463 extmodules.append(inotify)
467 extmodules.append(inotify)
464 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
468 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
465
469
466 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
470 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
467 'help/*.txt']}
471 'help/*.txt']}
468
472
469 def ordinarypath(p):
473 def ordinarypath(p):
470 return p and p[0] != '.' and p[-1] != '~'
474 return p and p[0] != '.' and p[-1] != '~'
471
475
472 for root in ('templates',):
476 for root in ('templates',):
473 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
477 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
474 curdir = curdir.split(os.sep, 1)[1]
478 curdir = curdir.split(os.sep, 1)[1]
475 dirs[:] = filter(ordinarypath, dirs)
479 dirs[:] = filter(ordinarypath, dirs)
476 for f in filter(ordinarypath, files):
480 for f in filter(ordinarypath, files):
477 f = os.path.join(curdir, f)
481 f = os.path.join(curdir, f)
478 packagedata['mercurial'].append(f)
482 packagedata['mercurial'].append(f)
479
483
480 datafiles = []
484 datafiles = []
481 setupversion = version
485 setupversion = version
482 extra = {}
486 extra = {}
483
487
484 if py2exeloaded:
488 if py2exeloaded:
485 extra['console'] = [
489 extra['console'] = [
486 {'script':'hg',
490 {'script':'hg',
487 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
491 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
488 'product_version':version}]
492 'product_version':version}]
489 # sub command of 'build' because 'py2exe' does not handle sub_commands
493 # sub command of 'build' because 'py2exe' does not handle sub_commands
490 build.sub_commands.insert(0, ('build_hgextindex', None))
494 build.sub_commands.insert(0, ('build_hgextindex', None))
491
495
492 if os.name == 'nt':
496 if os.name == 'nt':
493 # Windows binary file versions for exe/dll files must have the
497 # Windows binary file versions for exe/dll files must have the
494 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
498 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
495 setupversion = version.split('+', 1)[0]
499 setupversion = version.split('+', 1)[0]
496
500
497 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
501 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
498 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
502 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
499 # distutils.sysconfig
503 # distutils.sysconfig
500 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
504 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
501 if version:
505 if version:
502 version = version[0]
506 version = version[0]
503 xcode4 = (version.startswith('Xcode') and
507 xcode4 = (version.startswith('Xcode') and
504 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
508 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
505 else:
509 else:
506 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
510 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
507 # installed, but instead with only command-line tools. Assume
511 # installed, but instead with only command-line tools. Assume
508 # that only happens on >= Lion, thus no PPC support.
512 # that only happens on >= Lion, thus no PPC support.
509 xcode4 = True
513 xcode4 = True
510
514
511 if xcode4:
515 if xcode4:
512 os.environ['ARCHFLAGS'] = ''
516 os.environ['ARCHFLAGS'] = ''
513
517
514 setup(name='mercurial',
518 setup(name='mercurial',
515 version=setupversion,
519 version=setupversion,
516 author='Matt Mackall',
520 author='Matt Mackall',
517 author_email='mpm@selenic.com',
521 author_email='mpm@selenic.com',
518 url='http://mercurial.selenic.com/',
522 url='http://mercurial.selenic.com/',
519 description='Scalable distributed SCM',
523 description='Scalable distributed SCM',
520 license='GNU GPLv2+',
524 license='GNU GPLv2+',
521 scripts=scripts,
525 scripts=scripts,
522 packages=packages,
526 packages=packages,
523 py_modules=pymodules,
527 py_modules=pymodules,
524 ext_modules=extmodules,
528 ext_modules=extmodules,
525 data_files=datafiles,
529 data_files=datafiles,
526 package_data=packagedata,
530 package_data=packagedata,
527 cmdclass=cmdclass,
531 cmdclass=cmdclass,
528 distclass=hgdist,
532 distclass=hgdist,
529 options=dict(py2exe=dict(packages=['hgext', 'email']),
533 options=dict(py2exe=dict(packages=['hgext', 'email']),
530 bdist_mpkg=dict(zipdist=True,
534 bdist_mpkg=dict(zipdist=True,
531 license='COPYING',
535 license='COPYING',
532 readme='contrib/macosx/Readme.html',
536 readme='contrib/macosx/Readme.html',
533 welcome='contrib/macosx/Welcome.html')),
537 welcome='contrib/macosx/Welcome.html')),
534 **extra)
538 **extra)
General Comments 0
You need to be logged in to leave comments. Login now