##// END OF EJS Templates
setup: remove support for 2to3...
Gregory Szorc -
r28398:71229894 default
parent child Browse files
Show More
@@ -1,707 +1,680 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, 6, 0, 'final'):
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 6, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.6 or later.")
9 raise SystemExit("Mercurial requires Python 2.6 or later.")
10
10
11 if sys.version_info[0] >= 3:
11 if sys.version_info[0] >= 3:
12 printf = eval('print')
12 printf = eval('print')
13 libdir_escape = 'unicode_escape'
13 libdir_escape = 'unicode_escape'
14 else:
14 else:
15 libdir_escape = 'string_escape'
15 libdir_escape = 'string_escape'
16 def printf(*args, **kwargs):
16 def printf(*args, **kwargs):
17 f = kwargs.get('file', sys.stdout)
17 f = kwargs.get('file', sys.stdout)
18 end = kwargs.get('end', '\n')
18 end = kwargs.get('end', '\n')
19 f.write(b' '.join(args) + end)
19 f.write(b' '.join(args) + end)
20
20
21 # Solaris Python packaging brain damage
21 # Solaris Python packaging brain damage
22 try:
22 try:
23 import hashlib
23 import hashlib
24 sha = hashlib.sha1()
24 sha = hashlib.sha1()
25 except ImportError:
25 except ImportError:
26 try:
26 try:
27 import sha
27 import sha
28 sha.sha # silence unused import warning
28 sha.sha # silence unused import warning
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 zlib.compressobj # silence unused import warning
35 zlib.compressobj # silence unused import warning
36 except ImportError:
36 except ImportError:
37 raise SystemExit(
37 raise SystemExit(
38 "Couldn't import standard zlib (incomplete Python install).")
38 "Couldn't import standard zlib (incomplete Python install).")
39
39
40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
41 isironpython = False
41 isironpython = False
42 try:
42 try:
43 isironpython = (platform.python_implementation()
43 isironpython = (platform.python_implementation()
44 .lower().find("ironpython") != -1)
44 .lower().find("ironpython") != -1)
45 except AttributeError:
45 except AttributeError:
46 pass
46 pass
47
47
48 if isironpython:
48 if isironpython:
49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
50 else:
50 else:
51 try:
51 try:
52 import bz2
52 import bz2
53 bz2.BZ2Compressor # silence unused import warning
53 bz2.BZ2Compressor # silence unused import warning
54 except ImportError:
54 except ImportError:
55 raise SystemExit(
55 raise SystemExit(
56 "Couldn't import standard bz2 (incomplete Python install).")
56 "Couldn't import standard bz2 (incomplete Python install).")
57
57
58 ispypy = "PyPy" in sys.version
58 ispypy = "PyPy" in sys.version
59
59
60 import os, stat, subprocess, time
60 import os, stat, subprocess, time
61 import re
61 import re
62 import shutil
62 import shutil
63 import tempfile
63 import tempfile
64 from distutils import log
64 from distutils import log
65 if 'FORCE_SETUPTOOLS' in os.environ:
65 if 'FORCE_SETUPTOOLS' in os.environ:
66 from setuptools import setup
66 from setuptools import setup
67 else:
67 else:
68 from distutils.core import setup
68 from distutils.core import setup
69 from distutils.core import Command, Extension
69 from distutils.core import Command, Extension
70 from distutils.dist import Distribution
70 from distutils.dist import Distribution
71 from distutils.command.build import build
71 from distutils.command.build import build
72 from distutils.command.build_ext import build_ext
72 from distutils.command.build_ext import build_ext
73 from distutils.command.build_py import build_py
73 from distutils.command.build_py import build_py
74 from distutils.command.build_scripts import build_scripts
74 from distutils.command.build_scripts import build_scripts
75 from distutils.command.install_lib import install_lib
75 from distutils.command.install_lib import install_lib
76 from distutils.command.install_scripts import install_scripts
76 from distutils.command.install_scripts import install_scripts
77 from distutils.spawn import spawn, find_executable
77 from distutils.spawn import spawn, find_executable
78 from distutils import file_util
78 from distutils import file_util
79 from distutils.errors import (
79 from distutils.errors import (
80 CCompilerError,
80 CCompilerError,
81 DistutilsError,
81 DistutilsError,
82 DistutilsExecError,
82 DistutilsExecError,
83 )
83 )
84 from distutils.sysconfig import get_python_inc, get_config_var
84 from distutils.sysconfig import get_python_inc, get_config_var
85 from distutils.version import StrictVersion
85 from distutils.version import StrictVersion
86
86
87 convert2to3 = '--c2to3' in sys.argv
88 if convert2to3:
89 try:
90 from distutils.command.build_py import build_py_2to3 as build_py
91 from lib2to3.refactor import get_fixers_from_package as getfixers
92 except ImportError:
93 if sys.version_info[0] < 3:
94 raise SystemExit("--c2to3 is only compatible with python3.")
95 raise
96 sys.path.append('contrib')
97 elif sys.version_info[0] >= 3:
98 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
99
100 scripts = ['hg']
87 scripts = ['hg']
101 if os.name == 'nt':
88 if os.name == 'nt':
102 # We remove hg.bat if we are able to build hg.exe.
89 # We remove hg.bat if we are able to build hg.exe.
103 scripts.append('contrib/win32/hg.bat')
90 scripts.append('contrib/win32/hg.bat')
104
91
105 # simplified version of distutils.ccompiler.CCompiler.has_function
92 # simplified version of distutils.ccompiler.CCompiler.has_function
106 # that actually removes its temporary files.
93 # that actually removes its temporary files.
107 def hasfunction(cc, funcname):
94 def hasfunction(cc, funcname):
108 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
95 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
109 devnull = oldstderr = None
96 devnull = oldstderr = None
110 try:
97 try:
111 fname = os.path.join(tmpdir, 'funcname.c')
98 fname = os.path.join(tmpdir, 'funcname.c')
112 f = open(fname, 'w')
99 f = open(fname, 'w')
113 f.write('int main(void) {\n')
100 f.write('int main(void) {\n')
114 f.write(' %s();\n' % funcname)
101 f.write(' %s();\n' % funcname)
115 f.write('}\n')
102 f.write('}\n')
116 f.close()
103 f.close()
117 # Redirect stderr to /dev/null to hide any error messages
104 # Redirect stderr to /dev/null to hide any error messages
118 # from the compiler.
105 # from the compiler.
119 # This will have to be changed if we ever have to check
106 # This will have to be changed if we ever have to check
120 # for a function on Windows.
107 # for a function on Windows.
121 devnull = open('/dev/null', 'w')
108 devnull = open('/dev/null', 'w')
122 oldstderr = os.dup(sys.stderr.fileno())
109 oldstderr = os.dup(sys.stderr.fileno())
123 os.dup2(devnull.fileno(), sys.stderr.fileno())
110 os.dup2(devnull.fileno(), sys.stderr.fileno())
124 objects = cc.compile([fname], output_dir=tmpdir)
111 objects = cc.compile([fname], output_dir=tmpdir)
125 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
112 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
126 return True
113 return True
127 except Exception:
114 except Exception:
128 return False
115 return False
129 finally:
116 finally:
130 if oldstderr is not None:
117 if oldstderr is not None:
131 os.dup2(oldstderr, sys.stderr.fileno())
118 os.dup2(oldstderr, sys.stderr.fileno())
132 if devnull is not None:
119 if devnull is not None:
133 devnull.close()
120 devnull.close()
134 shutil.rmtree(tmpdir)
121 shutil.rmtree(tmpdir)
135
122
136 # py2exe needs to be installed to work
123 # py2exe needs to be installed to work
137 try:
124 try:
138 import py2exe
125 import py2exe
139 py2exe.Distribution # silence unused import warning
126 py2exe.Distribution # silence unused import warning
140 py2exeloaded = True
127 py2exeloaded = True
141 # import py2exe's patched Distribution class
128 # import py2exe's patched Distribution class
142 from distutils.core import Distribution
129 from distutils.core import Distribution
143 except ImportError:
130 except ImportError:
144 py2exeloaded = False
131 py2exeloaded = False
145
132
146 def runcmd(cmd, env):
133 def runcmd(cmd, env):
147 if (sys.platform == 'plan9'
134 if (sys.platform == 'plan9'
148 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
135 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
149 # subprocess kludge to work around issues in half-baked Python
136 # subprocess kludge to work around issues in half-baked Python
150 # ports, notably bichued/python:
137 # ports, notably bichued/python:
151 _, out, err = os.popen3(cmd)
138 _, out, err = os.popen3(cmd)
152 return str(out), str(err)
139 return str(out), str(err)
153 else:
140 else:
154 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
141 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
155 stderr=subprocess.PIPE, env=env)
142 stderr=subprocess.PIPE, env=env)
156 out, err = p.communicate()
143 out, err = p.communicate()
157 return out, err
144 return out, err
158
145
159 def runhg(cmd, env):
146 def runhg(cmd, env):
160 out, err = runcmd(cmd, env)
147 out, err = runcmd(cmd, env)
161 # If root is executing setup.py, but the repository is owned by
148 # If root is executing setup.py, but the repository is owned by
162 # another user (as in "sudo python setup.py install") we will get
149 # another user (as in "sudo python setup.py install") we will get
163 # trust warnings since the .hg/hgrc file is untrusted. That is
150 # trust warnings since the .hg/hgrc file is untrusted. That is
164 # fine, we don't want to load it anyway. Python may warn about
151 # fine, we don't want to load it anyway. Python may warn about
165 # a missing __init__.py in mercurial/locale, we also ignore that.
152 # a missing __init__.py in mercurial/locale, we also ignore that.
166 err = [e for e in err.splitlines()
153 err = [e for e in err.splitlines()
167 if not e.startswith(b'not trusting file') \
154 if not e.startswith(b'not trusting file') \
168 and not e.startswith(b'warning: Not importing') \
155 and not e.startswith(b'warning: Not importing') \
169 and not e.startswith(b'obsolete feature not enabled')]
156 and not e.startswith(b'obsolete feature not enabled')]
170 if err:
157 if err:
171 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
158 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
172 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
159 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
173 return ''
160 return ''
174 return out
161 return out
175
162
176 version = ''
163 version = ''
177
164
178 # Execute hg out of this directory with a custom environment which takes care
165 # Execute hg out of this directory with a custom environment which takes care
179 # to not use any hgrc files and do no localization.
166 # to not use any hgrc files and do no localization.
180 env = {'HGMODULEPOLICY': 'py',
167 env = {'HGMODULEPOLICY': 'py',
181 'HGRCPATH': '',
168 'HGRCPATH': '',
182 'LANGUAGE': 'C'}
169 'LANGUAGE': 'C'}
183 if 'LD_LIBRARY_PATH' in os.environ:
170 if 'LD_LIBRARY_PATH' in os.environ:
184 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
171 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
185 if 'SystemRoot' in os.environ:
172 if 'SystemRoot' in os.environ:
186 # Copy SystemRoot into the custom environment for Python 2.6
173 # Copy SystemRoot into the custom environment for Python 2.6
187 # under Windows. Otherwise, the subprocess will fail with
174 # under Windows. Otherwise, the subprocess will fail with
188 # error 0xc0150004. See: http://bugs.python.org/issue3440
175 # error 0xc0150004. See: http://bugs.python.org/issue3440
189 env['SystemRoot'] = os.environ['SystemRoot']
176 env['SystemRoot'] = os.environ['SystemRoot']
190
177
191 if os.path.isdir('.hg'):
178 if os.path.isdir('.hg'):
192 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
179 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
193 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
180 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
194 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
181 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
195 if numerictags: # tag(s) found
182 if numerictags: # tag(s) found
196 version = numerictags[-1]
183 version = numerictags[-1]
197 if hgid.endswith('+'): # propagate the dirty status to the tag
184 if hgid.endswith('+'): # propagate the dirty status to the tag
198 version += '+'
185 version += '+'
199 else: # no tag found
186 else: # no tag found
200 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
187 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
201 '{latesttag}']
188 '{latesttag}']
202 ltag = runhg(ltagcmd, env)
189 ltag = runhg(ltagcmd, env)
203 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
190 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
204 "only(.,'%s')" % ltag]
191 "only(.,'%s')" % ltag]
205 changessince = len(runhg(changessincecmd, env).splitlines())
192 changessince = len(runhg(changessincecmd, env).splitlines())
206 version = '%s+%s-%s' % (ltag, changessince, hgid)
193 version = '%s+%s-%s' % (ltag, changessince, hgid)
207 if version.endswith('+'):
194 if version.endswith('+'):
208 version += time.strftime('%Y%m%d')
195 version += time.strftime('%Y%m%d')
209 elif os.path.exists('.hg_archival.txt'):
196 elif os.path.exists('.hg_archival.txt'):
210 kw = dict([[t.strip() for t in l.split(':', 1)]
197 kw = dict([[t.strip() for t in l.split(':', 1)]
211 for l in open('.hg_archival.txt')])
198 for l in open('.hg_archival.txt')])
212 if 'tag' in kw:
199 if 'tag' in kw:
213 version = kw['tag']
200 version = kw['tag']
214 elif 'latesttag' in kw:
201 elif 'latesttag' in kw:
215 if 'changessincelatesttag' in kw:
202 if 'changessincelatesttag' in kw:
216 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
203 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
217 else:
204 else:
218 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
205 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
219 else:
206 else:
220 version = kw.get('node', '')[:12]
207 version = kw.get('node', '')[:12]
221
208
222 if version:
209 if version:
223 f = open("mercurial/__version__.py", "w")
210 f = open("mercurial/__version__.py", "w")
224 f.write('# this file is autogenerated by setup.py\n')
211 f.write('# this file is autogenerated by setup.py\n')
225 f.write('version = "%s"\n' % version)
212 f.write('version = "%s"\n' % version)
226 f.close()
213 f.close()
227
214
228
215
229 try:
216 try:
230 from mercurial import __version__
217 from mercurial import __version__
231 version = __version__.version
218 version = __version__.version
232 except ImportError:
219 except ImportError:
233 version = 'unknown'
220 version = 'unknown'
234
221
235 class hgbuild(build):
222 class hgbuild(build):
236 # Insert hgbuildmo first so that files in mercurial/locale/ are found
223 # Insert hgbuildmo first so that files in mercurial/locale/ are found
237 # when build_py is run next.
224 # when build_py is run next.
238 sub_commands = [('build_mo', None),
225 sub_commands = [('build_mo', None)] + build.sub_commands
239
240 # We also need build_ext before build_py. Otherwise, when 2to3 is
241 # called (in build_py), it will not find osutil & friends,
242 # thinking that those modules are global and, consequently, making
243 # a mess, now that all module imports are global.
244
245 ('build_ext', build.has_ext_modules),
246 ] + build.sub_commands
247
226
248 class hgbuildmo(build):
227 class hgbuildmo(build):
249
228
250 description = "build translations (.mo files)"
229 description = "build translations (.mo files)"
251
230
252 def run(self):
231 def run(self):
253 if not find_executable('msgfmt'):
232 if not find_executable('msgfmt'):
254 self.warn("could not find msgfmt executable, no translations "
233 self.warn("could not find msgfmt executable, no translations "
255 "will be built")
234 "will be built")
256 return
235 return
257
236
258 podir = 'i18n'
237 podir = 'i18n'
259 if not os.path.isdir(podir):
238 if not os.path.isdir(podir):
260 self.warn("could not find %s/ directory" % podir)
239 self.warn("could not find %s/ directory" % podir)
261 return
240 return
262
241
263 join = os.path.join
242 join = os.path.join
264 for po in os.listdir(podir):
243 for po in os.listdir(podir):
265 if not po.endswith('.po'):
244 if not po.endswith('.po'):
266 continue
245 continue
267 pofile = join(podir, po)
246 pofile = join(podir, po)
268 modir = join('locale', po[:-3], 'LC_MESSAGES')
247 modir = join('locale', po[:-3], 'LC_MESSAGES')
269 mofile = join(modir, 'hg.mo')
248 mofile = join(modir, 'hg.mo')
270 mobuildfile = join('mercurial', mofile)
249 mobuildfile = join('mercurial', mofile)
271 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
250 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
272 if sys.platform != 'sunos5':
251 if sys.platform != 'sunos5':
273 # msgfmt on Solaris does not know about -c
252 # msgfmt on Solaris does not know about -c
274 cmd.append('-c')
253 cmd.append('-c')
275 self.mkpath(join('mercurial', modir))
254 self.mkpath(join('mercurial', modir))
276 self.make_file([pofile], mobuildfile, spawn, (cmd,))
255 self.make_file([pofile], mobuildfile, spawn, (cmd,))
277
256
278
257
279 class hgdist(Distribution):
258 class hgdist(Distribution):
280 pure = ispypy
259 pure = ispypy
281
260
282 global_options = Distribution.global_options + \
261 global_options = Distribution.global_options + \
283 [('pure', None, "use pure (slow) Python "
262 [('pure', None, "use pure (slow) Python "
284 "code instead of C extensions"),
263 "code instead of C extensions"),
285 ('c2to3', None, "(experimental!) convert "
286 "code with 2to3"),
287 ]
264 ]
288
265
289 def has_ext_modules(self):
266 def has_ext_modules(self):
290 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
267 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
291 # too late for some cases
268 # too late for some cases
292 return not self.pure and Distribution.has_ext_modules(self)
269 return not self.pure and Distribution.has_ext_modules(self)
293
270
294 class hgbuildext(build_ext):
271 class hgbuildext(build_ext):
295
272
296 def build_extension(self, ext):
273 def build_extension(self, ext):
297 try:
274 try:
298 build_ext.build_extension(self, ext)
275 build_ext.build_extension(self, ext)
299 except CCompilerError:
276 except CCompilerError:
300 if not getattr(ext, 'optional', False):
277 if not getattr(ext, 'optional', False):
301 raise
278 raise
302 log.warn("Failed to build optional extension '%s' (skipping)",
279 log.warn("Failed to build optional extension '%s' (skipping)",
303 ext.name)
280 ext.name)
304
281
305 class hgbuildscripts(build_scripts):
282 class hgbuildscripts(build_scripts):
306 def run(self):
283 def run(self):
307 if os.name != 'nt' or self.distribution.pure:
284 if os.name != 'nt' or self.distribution.pure:
308 return build_scripts.run(self)
285 return build_scripts.run(self)
309
286
310 exebuilt = False
287 exebuilt = False
311 try:
288 try:
312 self.run_command('build_hgexe')
289 self.run_command('build_hgexe')
313 exebuilt = True
290 exebuilt = True
314 except (DistutilsError, CCompilerError):
291 except (DistutilsError, CCompilerError):
315 log.warn('failed to build optional hg.exe')
292 log.warn('failed to build optional hg.exe')
316
293
317 if exebuilt:
294 if exebuilt:
318 # Copying hg.exe to the scripts build directory ensures it is
295 # Copying hg.exe to the scripts build directory ensures it is
319 # installed by the install_scripts command.
296 # installed by the install_scripts command.
320 hgexecommand = self.get_finalized_command('build_hgexe')
297 hgexecommand = self.get_finalized_command('build_hgexe')
321 dest = os.path.join(self.build_dir, 'hg.exe')
298 dest = os.path.join(self.build_dir, 'hg.exe')
322 self.mkpath(self.build_dir)
299 self.mkpath(self.build_dir)
323 self.copy_file(hgexecommand.hgexepath, dest)
300 self.copy_file(hgexecommand.hgexepath, dest)
324
301
325 # Remove hg.bat because it is redundant with hg.exe.
302 # Remove hg.bat because it is redundant with hg.exe.
326 self.scripts.remove('contrib/win32/hg.bat')
303 self.scripts.remove('contrib/win32/hg.bat')
327
304
328 return build_scripts.run(self)
305 return build_scripts.run(self)
329
306
330 class hgbuildpy(build_py):
307 class hgbuildpy(build_py):
331 if convert2to3:
332 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
333 getfixers("hgfixes")))
334
335 def finalize_options(self):
308 def finalize_options(self):
336 build_py.finalize_options(self)
309 build_py.finalize_options(self)
337
310
338 if self.distribution.pure:
311 if self.distribution.pure:
339 self.distribution.ext_modules = []
312 self.distribution.ext_modules = []
340 else:
313 else:
341 h = os.path.join(get_python_inc(), 'Python.h')
314 h = os.path.join(get_python_inc(), 'Python.h')
342 if not os.path.exists(h):
315 if not os.path.exists(h):
343 raise SystemExit('Python headers are required to build '
316 raise SystemExit('Python headers are required to build '
344 'Mercurial but weren\'t found in %s' % h)
317 'Mercurial but weren\'t found in %s' % h)
345
318
346 def copy_file(self, *args, **kwargs):
319 def copy_file(self, *args, **kwargs):
347 dst, copied = build_py.copy_file(self, *args, **kwargs)
320 dst, copied = build_py.copy_file(self, *args, **kwargs)
348
321
349 if copied and dst.endswith('__init__.py'):
322 if copied and dst.endswith('__init__.py'):
350 if self.distribution.pure:
323 if self.distribution.pure:
351 modulepolicy = 'py'
324 modulepolicy = 'py'
352 else:
325 else:
353 modulepolicy = 'c'
326 modulepolicy = 'c'
354 content = open(dst, 'rb').read()
327 content = open(dst, 'rb').read()
355 content = content.replace(b'@MODULELOADPOLICY@',
328 content = content.replace(b'@MODULELOADPOLICY@',
356 modulepolicy.encode(libdir_escape))
329 modulepolicy.encode(libdir_escape))
357 with open(dst, 'wb') as fh:
330 with open(dst, 'wb') as fh:
358 fh.write(content)
331 fh.write(content)
359
332
360 return dst, copied
333 return dst, copied
361
334
362 class buildhgextindex(Command):
335 class buildhgextindex(Command):
363 description = 'generate prebuilt index of hgext (for frozen package)'
336 description = 'generate prebuilt index of hgext (for frozen package)'
364 user_options = []
337 user_options = []
365 _indexfilename = 'hgext/__index__.py'
338 _indexfilename = 'hgext/__index__.py'
366
339
367 def initialize_options(self):
340 def initialize_options(self):
368 pass
341 pass
369
342
370 def finalize_options(self):
343 def finalize_options(self):
371 pass
344 pass
372
345
373 def run(self):
346 def run(self):
374 if os.path.exists(self._indexfilename):
347 if os.path.exists(self._indexfilename):
375 f = open(self._indexfilename, 'w')
348 f = open(self._indexfilename, 'w')
376 f.write('# empty\n')
349 f.write('# empty\n')
377 f.close()
350 f.close()
378
351
379 # here no extension enabled, disabled() lists up everything
352 # here no extension enabled, disabled() lists up everything
380 code = ('import pprint; from mercurial import extensions; '
353 code = ('import pprint; from mercurial import extensions; '
381 'pprint.pprint(extensions.disabled())')
354 'pprint.pprint(extensions.disabled())')
382 out, err = runcmd([sys.executable, '-c', code], env)
355 out, err = runcmd([sys.executable, '-c', code], env)
383 if err:
356 if err:
384 raise DistutilsExecError(err)
357 raise DistutilsExecError(err)
385
358
386 f = open(self._indexfilename, 'w')
359 f = open(self._indexfilename, 'w')
387 f.write('# this file is autogenerated by setup.py\n')
360 f.write('# this file is autogenerated by setup.py\n')
388 f.write('docs = ')
361 f.write('docs = ')
389 f.write(out)
362 f.write(out)
390 f.close()
363 f.close()
391
364
392 class buildhgexe(build_ext):
365 class buildhgexe(build_ext):
393 description = 'compile hg.exe from mercurial/exewrapper.c'
366 description = 'compile hg.exe from mercurial/exewrapper.c'
394
367
395 def build_extensions(self):
368 def build_extensions(self):
396 if os.name != 'nt':
369 if os.name != 'nt':
397 return
370 return
398 if isinstance(self.compiler, HackedMingw32CCompiler):
371 if isinstance(self.compiler, HackedMingw32CCompiler):
399 self.compiler.compiler_so = self.compiler.compiler # no -mdll
372 self.compiler.compiler_so = self.compiler.compiler # no -mdll
400 self.compiler.dll_libraries = [] # no -lmsrvc90
373 self.compiler.dll_libraries = [] # no -lmsrvc90
401 hv = sys.hexversion
374 hv = sys.hexversion
402 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
375 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
403 f = open('mercurial/hgpythonlib.h', 'wb')
376 f = open('mercurial/hgpythonlib.h', 'wb')
404 f.write('/* this file is autogenerated by setup.py */\n')
377 f.write('/* this file is autogenerated by setup.py */\n')
405 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
378 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
406 f.close()
379 f.close()
407 objects = self.compiler.compile(['mercurial/exewrapper.c'],
380 objects = self.compiler.compile(['mercurial/exewrapper.c'],
408 output_dir=self.build_temp)
381 output_dir=self.build_temp)
409 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
382 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
410 target = os.path.join(dir, 'hg')
383 target = os.path.join(dir, 'hg')
411 self.compiler.link_executable(objects, target,
384 self.compiler.link_executable(objects, target,
412 libraries=[],
385 libraries=[],
413 output_dir=self.build_temp)
386 output_dir=self.build_temp)
414
387
415 @property
388 @property
416 def hgexepath(self):
389 def hgexepath(self):
417 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
390 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
418 return os.path.join(self.build_temp, dir, 'hg.exe')
391 return os.path.join(self.build_temp, dir, 'hg.exe')
419
392
420 class hginstalllib(install_lib):
393 class hginstalllib(install_lib):
421 '''
394 '''
422 This is a specialization of install_lib that replaces the copy_file used
395 This is a specialization of install_lib that replaces the copy_file used
423 there so that it supports setting the mode of files after copying them,
396 there so that it supports setting the mode of files after copying them,
424 instead of just preserving the mode that the files originally had. If your
397 instead of just preserving the mode that the files originally had. If your
425 system has a umask of something like 027, preserving the permissions when
398 system has a umask of something like 027, preserving the permissions when
426 copying will lead to a broken install.
399 copying will lead to a broken install.
427
400
428 Note that just passing keep_permissions=False to copy_file would be
401 Note that just passing keep_permissions=False to copy_file would be
429 insufficient, as it might still be applying a umask.
402 insufficient, as it might still be applying a umask.
430 '''
403 '''
431
404
432 def run(self):
405 def run(self):
433 realcopyfile = file_util.copy_file
406 realcopyfile = file_util.copy_file
434 def copyfileandsetmode(*args, **kwargs):
407 def copyfileandsetmode(*args, **kwargs):
435 src, dst = args[0], args[1]
408 src, dst = args[0], args[1]
436 dst, copied = realcopyfile(*args, **kwargs)
409 dst, copied = realcopyfile(*args, **kwargs)
437 if copied:
410 if copied:
438 st = os.stat(src)
411 st = os.stat(src)
439 # Persist executable bit (apply it to group and other if user
412 # Persist executable bit (apply it to group and other if user
440 # has it)
413 # has it)
441 if st[stat.ST_MODE] & stat.S_IXUSR:
414 if st[stat.ST_MODE] & stat.S_IXUSR:
442 setmode = int('0755', 8)
415 setmode = int('0755', 8)
443 else:
416 else:
444 setmode = int('0644', 8)
417 setmode = int('0644', 8)
445 m = stat.S_IMODE(st[stat.ST_MODE])
418 m = stat.S_IMODE(st[stat.ST_MODE])
446 m = (m & ~int('0777', 8)) | setmode
419 m = (m & ~int('0777', 8)) | setmode
447 os.chmod(dst, m)
420 os.chmod(dst, m)
448 file_util.copy_file = copyfileandsetmode
421 file_util.copy_file = copyfileandsetmode
449 try:
422 try:
450 install_lib.run(self)
423 install_lib.run(self)
451 finally:
424 finally:
452 file_util.copy_file = realcopyfile
425 file_util.copy_file = realcopyfile
453
426
454 class hginstallscripts(install_scripts):
427 class hginstallscripts(install_scripts):
455 '''
428 '''
456 This is a specialization of install_scripts that replaces the @LIBDIR@ with
429 This is a specialization of install_scripts that replaces the @LIBDIR@ with
457 the configured directory for modules. If possible, the path is made relative
430 the configured directory for modules. If possible, the path is made relative
458 to the directory for scripts.
431 to the directory for scripts.
459 '''
432 '''
460
433
461 def initialize_options(self):
434 def initialize_options(self):
462 install_scripts.initialize_options(self)
435 install_scripts.initialize_options(self)
463
436
464 self.install_lib = None
437 self.install_lib = None
465
438
466 def finalize_options(self):
439 def finalize_options(self):
467 install_scripts.finalize_options(self)
440 install_scripts.finalize_options(self)
468 self.set_undefined_options('install',
441 self.set_undefined_options('install',
469 ('install_lib', 'install_lib'))
442 ('install_lib', 'install_lib'))
470
443
471 def run(self):
444 def run(self):
472 install_scripts.run(self)
445 install_scripts.run(self)
473
446
474 # It only makes sense to replace @LIBDIR@ with the install path if
447 # It only makes sense to replace @LIBDIR@ with the install path if
475 # the install path is known. For wheels, the logic below calculates
448 # the install path is known. For wheels, the logic below calculates
476 # the libdir to be "../..". This is because the internal layout of a
449 # the libdir to be "../..". This is because the internal layout of a
477 # wheel archive looks like:
450 # wheel archive looks like:
478 #
451 #
479 # mercurial-3.6.1.data/scripts/hg
452 # mercurial-3.6.1.data/scripts/hg
480 # mercurial/__init__.py
453 # mercurial/__init__.py
481 #
454 #
482 # When installing wheels, the subdirectories of the "<pkg>.data"
455 # When installing wheels, the subdirectories of the "<pkg>.data"
483 # directory are translated to system local paths and files therein
456 # directory are translated to system local paths and files therein
484 # are copied in place. The mercurial/* files are installed into the
457 # are copied in place. The mercurial/* files are installed into the
485 # site-packages directory. However, the site-packages directory
458 # site-packages directory. However, the site-packages directory
486 # isn't known until wheel install time. This means we have no clue
459 # isn't known until wheel install time. This means we have no clue
487 # at wheel generation time what the installed site-packages directory
460 # at wheel generation time what the installed site-packages directory
488 # will be. And, wheels don't appear to provide the ability to register
461 # will be. And, wheels don't appear to provide the ability to register
489 # custom code to run during wheel installation. This all means that
462 # custom code to run during wheel installation. This all means that
490 # we can't reliably set the libdir in wheels: the default behavior
463 # we can't reliably set the libdir in wheels: the default behavior
491 # of looking in sys.path must do.
464 # of looking in sys.path must do.
492
465
493 if (os.path.splitdrive(self.install_dir)[0] !=
466 if (os.path.splitdrive(self.install_dir)[0] !=
494 os.path.splitdrive(self.install_lib)[0]):
467 os.path.splitdrive(self.install_lib)[0]):
495 # can't make relative paths from one drive to another, so use an
468 # can't make relative paths from one drive to another, so use an
496 # absolute path instead
469 # absolute path instead
497 libdir = self.install_lib
470 libdir = self.install_lib
498 else:
471 else:
499 common = os.path.commonprefix((self.install_dir, self.install_lib))
472 common = os.path.commonprefix((self.install_dir, self.install_lib))
500 rest = self.install_dir[len(common):]
473 rest = self.install_dir[len(common):]
501 uplevel = len([n for n in os.path.split(rest) if n])
474 uplevel = len([n for n in os.path.split(rest) if n])
502
475
503 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
476 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
504
477
505 for outfile in self.outfiles:
478 for outfile in self.outfiles:
506 fp = open(outfile, 'rb')
479 fp = open(outfile, 'rb')
507 data = fp.read()
480 data = fp.read()
508 fp.close()
481 fp.close()
509
482
510 # skip binary files
483 # skip binary files
511 if b'\0' in data:
484 if b'\0' in data:
512 continue
485 continue
513
486
514 # During local installs, the shebang will be rewritten to the final
487 # During local installs, the shebang will be rewritten to the final
515 # install path. During wheel packaging, the shebang has a special
488 # install path. During wheel packaging, the shebang has a special
516 # value.
489 # value.
517 if data.startswith(b'#!python'):
490 if data.startswith(b'#!python'):
518 log.info('not rewriting @LIBDIR@ in %s because install path '
491 log.info('not rewriting @LIBDIR@ in %s because install path '
519 'not known' % outfile)
492 'not known' % outfile)
520 continue
493 continue
521
494
522 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
495 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
523 fp = open(outfile, 'wb')
496 fp = open(outfile, 'wb')
524 fp.write(data)
497 fp.write(data)
525 fp.close()
498 fp.close()
526
499
527 cmdclass = {'build': hgbuild,
500 cmdclass = {'build': hgbuild,
528 'build_mo': hgbuildmo,
501 'build_mo': hgbuildmo,
529 'build_ext': hgbuildext,
502 'build_ext': hgbuildext,
530 'build_py': hgbuildpy,
503 'build_py': hgbuildpy,
531 'build_scripts': hgbuildscripts,
504 'build_scripts': hgbuildscripts,
532 'build_hgextindex': buildhgextindex,
505 'build_hgextindex': buildhgextindex,
533 'install_lib': hginstalllib,
506 'install_lib': hginstalllib,
534 'install_scripts': hginstallscripts,
507 'install_scripts': hginstallscripts,
535 'build_hgexe': buildhgexe,
508 'build_hgexe': buildhgexe,
536 }
509 }
537
510
538 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
511 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
539 'mercurial.pure',
512 'mercurial.pure',
540 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
513 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
541 'hgext.largefiles']
514 'hgext.largefiles']
542
515
543 common_depends = ['mercurial/util.h']
516 common_depends = ['mercurial/util.h']
544
517
545 osutil_ldflags = []
518 osutil_ldflags = []
546
519
547 if sys.platform == 'darwin':
520 if sys.platform == 'darwin':
548 osutil_ldflags += ['-framework', 'ApplicationServices']
521 osutil_ldflags += ['-framework', 'ApplicationServices']
549
522
550 extmodules = [
523 extmodules = [
551 Extension('mercurial.base85', ['mercurial/base85.c'],
524 Extension('mercurial.base85', ['mercurial/base85.c'],
552 depends=common_depends),
525 depends=common_depends),
553 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
526 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
554 depends=common_depends),
527 depends=common_depends),
555 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
528 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
556 depends=common_depends),
529 depends=common_depends),
557 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
530 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
558 depends=common_depends),
531 depends=common_depends),
559 Extension('mercurial.parsers', ['mercurial/dirs.c',
532 Extension('mercurial.parsers', ['mercurial/dirs.c',
560 'mercurial/manifest.c',
533 'mercurial/manifest.c',
561 'mercurial/parsers.c',
534 'mercurial/parsers.c',
562 'mercurial/pathencode.c'],
535 'mercurial/pathencode.c'],
563 depends=common_depends),
536 depends=common_depends),
564 Extension('mercurial.osutil', ['mercurial/osutil.c'],
537 Extension('mercurial.osutil', ['mercurial/osutil.c'],
565 extra_link_args=osutil_ldflags,
538 extra_link_args=osutil_ldflags,
566 depends=common_depends),
539 depends=common_depends),
567 ]
540 ]
568
541
569 try:
542 try:
570 from distutils import cygwinccompiler
543 from distutils import cygwinccompiler
571
544
572 # the -mno-cygwin option has been deprecated for years
545 # the -mno-cygwin option has been deprecated for years
573 compiler = cygwinccompiler.Mingw32CCompiler
546 compiler = cygwinccompiler.Mingw32CCompiler
574
547
575 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
548 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
576 def __init__(self, *args, **kwargs):
549 def __init__(self, *args, **kwargs):
577 compiler.__init__(self, *args, **kwargs)
550 compiler.__init__(self, *args, **kwargs)
578 for i in 'compiler compiler_so linker_exe linker_so'.split():
551 for i in 'compiler compiler_so linker_exe linker_so'.split():
579 try:
552 try:
580 getattr(self, i).remove('-mno-cygwin')
553 getattr(self, i).remove('-mno-cygwin')
581 except ValueError:
554 except ValueError:
582 pass
555 pass
583
556
584 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
557 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
585 except ImportError:
558 except ImportError:
586 # the cygwinccompiler package is not available on some Python
559 # the cygwinccompiler package is not available on some Python
587 # distributions like the ones from the optware project for Synology
560 # distributions like the ones from the optware project for Synology
588 # DiskStation boxes
561 # DiskStation boxes
589 class HackedMingw32CCompiler(object):
562 class HackedMingw32CCompiler(object):
590 pass
563 pass
591
564
592 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
565 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
593 'help/*.txt',
566 'help/*.txt',
594 'help/internals/*.txt',
567 'help/internals/*.txt',
595 'default.d/*.rc',
568 'default.d/*.rc',
596 'dummycert.pem']}
569 'dummycert.pem']}
597
570
598 def ordinarypath(p):
571 def ordinarypath(p):
599 return p and p[0] != '.' and p[-1] != '~'
572 return p and p[0] != '.' and p[-1] != '~'
600
573
601 for root in ('templates',):
574 for root in ('templates',):
602 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
575 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
603 curdir = curdir.split(os.sep, 1)[1]
576 curdir = curdir.split(os.sep, 1)[1]
604 dirs[:] = filter(ordinarypath, dirs)
577 dirs[:] = filter(ordinarypath, dirs)
605 for f in filter(ordinarypath, files):
578 for f in filter(ordinarypath, files):
606 f = os.path.join(curdir, f)
579 f = os.path.join(curdir, f)
607 packagedata['mercurial'].append(f)
580 packagedata['mercurial'].append(f)
608
581
609 datafiles = []
582 datafiles = []
610 setupversion = version
583 setupversion = version
611 extra = {}
584 extra = {}
612
585
613 if py2exeloaded:
586 if py2exeloaded:
614 extra['console'] = [
587 extra['console'] = [
615 {'script':'hg',
588 {'script':'hg',
616 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
589 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
617 'product_version':version}]
590 'product_version':version}]
618 # sub command of 'build' because 'py2exe' does not handle sub_commands
591 # sub command of 'build' because 'py2exe' does not handle sub_commands
619 build.sub_commands.insert(0, ('build_hgextindex', None))
592 build.sub_commands.insert(0, ('build_hgextindex', None))
620 # put dlls in sub directory so that they won't pollute PATH
593 # put dlls in sub directory so that they won't pollute PATH
621 extra['zipfile'] = 'lib/library.zip'
594 extra['zipfile'] = 'lib/library.zip'
622
595
623 if os.name == 'nt':
596 if os.name == 'nt':
624 # Windows binary file versions for exe/dll files must have the
597 # Windows binary file versions for exe/dll files must have the
625 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
598 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
626 setupversion = version.split('+', 1)[0]
599 setupversion = version.split('+', 1)[0]
627
600
628 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
601 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
629 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
602 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
630 if version:
603 if version:
631 version = version[0]
604 version = version[0]
632 if sys.version_info[0] == 3:
605 if sys.version_info[0] == 3:
633 version = version.decode('utf-8')
606 version = version.decode('utf-8')
634 xcode4 = (version.startswith('Xcode') and
607 xcode4 = (version.startswith('Xcode') and
635 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
608 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
636 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
609 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
637 else:
610 else:
638 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
611 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
639 # installed, but instead with only command-line tools. Assume
612 # installed, but instead with only command-line tools. Assume
640 # that only happens on >= Lion, thus no PPC support.
613 # that only happens on >= Lion, thus no PPC support.
641 xcode4 = True
614 xcode4 = True
642 xcode51 = False
615 xcode51 = False
643
616
644 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
617 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
645 # distutils.sysconfig
618 # distutils.sysconfig
646 if xcode4:
619 if xcode4:
647 os.environ['ARCHFLAGS'] = ''
620 os.environ['ARCHFLAGS'] = ''
648
621
649 # XCode 5.1 changes clang such that it now fails to compile if the
622 # XCode 5.1 changes clang such that it now fails to compile if the
650 # -mno-fused-madd flag is passed, but the version of Python shipped with
623 # -mno-fused-madd flag is passed, but the version of Python shipped with
651 # OS X 10.9 Mavericks includes this flag. This causes problems in all
624 # OS X 10.9 Mavericks includes this flag. This causes problems in all
652 # C extension modules, and a bug has been filed upstream at
625 # C extension modules, and a bug has been filed upstream at
653 # http://bugs.python.org/issue21244. We also need to patch this here
626 # http://bugs.python.org/issue21244. We also need to patch this here
654 # so Mercurial can continue to compile in the meantime.
627 # so Mercurial can continue to compile in the meantime.
655 if xcode51:
628 if xcode51:
656 cflags = get_config_var('CFLAGS')
629 cflags = get_config_var('CFLAGS')
657 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
630 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
658 os.environ['CFLAGS'] = (
631 os.environ['CFLAGS'] = (
659 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
632 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
660
633
661 setup(name='mercurial',
634 setup(name='mercurial',
662 version=setupversion,
635 version=setupversion,
663 author='Matt Mackall and many others',
636 author='Matt Mackall and many others',
664 author_email='mercurial@selenic.com',
637 author_email='mercurial@selenic.com',
665 url='https://mercurial-scm.org/',
638 url='https://mercurial-scm.org/',
666 download_url='https://mercurial-scm.org/release/',
639 download_url='https://mercurial-scm.org/release/',
667 description=('Fast scalable distributed SCM (revision control, version '
640 description=('Fast scalable distributed SCM (revision control, version '
668 'control) system'),
641 'control) system'),
669 long_description=('Mercurial is a distributed SCM tool written in Python.'
642 long_description=('Mercurial is a distributed SCM tool written in Python.'
670 ' It is used by a number of large projects that require'
643 ' It is used by a number of large projects that require'
671 ' fast, reliable distributed revision control, such as '
644 ' fast, reliable distributed revision control, such as '
672 'Mozilla.'),
645 'Mozilla.'),
673 license='GNU GPLv2 or any later version',
646 license='GNU GPLv2 or any later version',
674 classifiers=[
647 classifiers=[
675 'Development Status :: 6 - Mature',
648 'Development Status :: 6 - Mature',
676 'Environment :: Console',
649 'Environment :: Console',
677 'Intended Audience :: Developers',
650 'Intended Audience :: Developers',
678 'Intended Audience :: System Administrators',
651 'Intended Audience :: System Administrators',
679 'License :: OSI Approved :: GNU General Public License (GPL)',
652 'License :: OSI Approved :: GNU General Public License (GPL)',
680 'Natural Language :: Danish',
653 'Natural Language :: Danish',
681 'Natural Language :: English',
654 'Natural Language :: English',
682 'Natural Language :: German',
655 'Natural Language :: German',
683 'Natural Language :: Italian',
656 'Natural Language :: Italian',
684 'Natural Language :: Japanese',
657 'Natural Language :: Japanese',
685 'Natural Language :: Portuguese (Brazilian)',
658 'Natural Language :: Portuguese (Brazilian)',
686 'Operating System :: Microsoft :: Windows',
659 'Operating System :: Microsoft :: Windows',
687 'Operating System :: OS Independent',
660 'Operating System :: OS Independent',
688 'Operating System :: POSIX',
661 'Operating System :: POSIX',
689 'Programming Language :: C',
662 'Programming Language :: C',
690 'Programming Language :: Python',
663 'Programming Language :: Python',
691 'Topic :: Software Development :: Version Control',
664 'Topic :: Software Development :: Version Control',
692 ],
665 ],
693 scripts=scripts,
666 scripts=scripts,
694 packages=packages,
667 packages=packages,
695 ext_modules=extmodules,
668 ext_modules=extmodules,
696 data_files=datafiles,
669 data_files=datafiles,
697 package_data=packagedata,
670 package_data=packagedata,
698 cmdclass=cmdclass,
671 cmdclass=cmdclass,
699 distclass=hgdist,
672 distclass=hgdist,
700 options={'py2exe': {'packages': ['hgext', 'email']},
673 options={'py2exe': {'packages': ['hgext', 'email']},
701 'bdist_mpkg': {'zipdist': False,
674 'bdist_mpkg': {'zipdist': False,
702 'license': 'COPYING',
675 'license': 'COPYING',
703 'readme': 'contrib/macosx/Readme.html',
676 'readme': 'contrib/macosx/Readme.html',
704 'welcome': 'contrib/macosx/Welcome.html',
677 'welcome': 'contrib/macosx/Welcome.html',
705 },
678 },
706 },
679 },
707 **extra)
680 **extra)
General Comments 0
You need to be logged in to leave comments. Login now