##// END OF EJS Templates
setup3k: use getattr instead of hasattr...
Augie Fackler -
r14972:bcba68e8 default
parent child Browse files
Show More
@@ -1,373 +1,373 b''
1 #
1 #
2 # This is an experimental py3k-enabled mercurial setup script.
2 # This is an experimental py3k-enabled 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 from distutils.command.build_py import build_py_2to3
7 from distutils.command.build_py import build_py_2to3
8 from lib2to3.refactor import get_fixers_from_package as getfixers
8 from lib2to3.refactor import get_fixers_from_package as getfixers
9
9
10 import sys
10 import sys
11 if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'):
11 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
12 raise SystemExit("Mercurial requires Python 2.4 or later.")
12 raise SystemExit("Mercurial requires Python 2.4 or later.")
13
13
14 if sys.version_info[0] >= 3:
14 if sys.version_info[0] >= 3:
15 def b(s):
15 def b(s):
16 '''A helper function to emulate 2.6+ bytes literals using string
16 '''A helper function to emulate 2.6+ bytes literals using string
17 literals.'''
17 literals.'''
18 return s.encode('latin1')
18 return s.encode('latin1')
19 else:
19 else:
20 def b(s):
20 def b(s):
21 '''A helper function to emulate 2.6+ bytes literals using string
21 '''A helper function to emulate 2.6+ bytes literals using string
22 literals.'''
22 literals.'''
23 return s
23 return s
24
24
25 # Solaris Python packaging brain damage
25 # Solaris Python packaging brain damage
26 try:
26 try:
27 import hashlib
27 import hashlib
28 sha = hashlib.sha1()
28 sha = hashlib.sha1()
29 except:
29 except:
30 try:
30 try:
31 import sha
31 import sha
32 except:
32 except:
33 raise SystemExit(
33 raise SystemExit(
34 "Couldn't import standard hashlib (incomplete Python install).")
34 "Couldn't import standard hashlib (incomplete Python install).")
35
35
36 try:
36 try:
37 import zlib
37 import zlib
38 except:
38 except:
39 raise SystemExit(
39 raise SystemExit(
40 "Couldn't import standard zlib (incomplete Python install).")
40 "Couldn't import standard zlib (incomplete Python install).")
41
41
42 try:
42 try:
43 import bz2
43 import bz2
44 except:
44 except:
45 raise SystemExit(
45 raise SystemExit(
46 "Couldn't import standard bz2 (incomplete Python install).")
46 "Couldn't import standard bz2 (incomplete Python install).")
47
47
48 import os, subprocess, time
48 import os, subprocess, time
49 import shutil
49 import shutil
50 import tempfile
50 import tempfile
51 from distutils import log
51 from distutils import log
52 from distutils.core import setup, Extension
52 from distutils.core import setup, Extension
53 from distutils.dist import Distribution
53 from distutils.dist import Distribution
54 from distutils.command.build import build
54 from distutils.command.build import build
55 from distutils.command.build_ext import build_ext
55 from distutils.command.build_ext import build_ext
56 from distutils.command.build_py import build_py
56 from distutils.command.build_py import build_py
57 from distutils.spawn import spawn, find_executable
57 from distutils.spawn import spawn, find_executable
58 from distutils.ccompiler import new_compiler
58 from distutils.ccompiler import new_compiler
59 from distutils.errors import CCompilerError
59 from distutils.errors import CCompilerError
60
60
61 scripts = ['hg']
61 scripts = ['hg']
62 if os.name == 'nt':
62 if os.name == 'nt':
63 scripts.append('contrib/win32/hg.bat')
63 scripts.append('contrib/win32/hg.bat')
64
64
65 # simplified version of distutils.ccompiler.CCompiler.has_function
65 # simplified version of distutils.ccompiler.CCompiler.has_function
66 # that actually removes its temporary files.
66 # that actually removes its temporary files.
67 def hasfunction(cc, funcname):
67 def hasfunction(cc, funcname):
68 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
68 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
69 devnull = oldstderr = None
69 devnull = oldstderr = None
70 try:
70 try:
71 try:
71 try:
72 fname = os.path.join(tmpdir, 'funcname.c')
72 fname = os.path.join(tmpdir, 'funcname.c')
73 f = open(fname, 'w')
73 f = open(fname, 'w')
74 f.write('int main(void) {\n')
74 f.write('int main(void) {\n')
75 f.write(' %s();\n' % funcname)
75 f.write(' %s();\n' % funcname)
76 f.write('}\n')
76 f.write('}\n')
77 f.close()
77 f.close()
78 # Redirect stderr to /dev/null to hide any error messages
78 # Redirect stderr to /dev/null to hide any error messages
79 # from the compiler.
79 # from the compiler.
80 # This will have to be changed if we ever have to check
80 # This will have to be changed if we ever have to check
81 # for a function on Windows.
81 # for a function on Windows.
82 devnull = open('/dev/null', 'w')
82 devnull = open('/dev/null', 'w')
83 oldstderr = os.dup(sys.stderr.fileno())
83 oldstderr = os.dup(sys.stderr.fileno())
84 os.dup2(devnull.fileno(), sys.stderr.fileno())
84 os.dup2(devnull.fileno(), sys.stderr.fileno())
85 objects = cc.compile([fname], output_dir=tmpdir)
85 objects = cc.compile([fname], output_dir=tmpdir)
86 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
86 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
87 except:
87 except:
88 return False
88 return False
89 return True
89 return True
90 finally:
90 finally:
91 if oldstderr is not None:
91 if oldstderr is not None:
92 os.dup2(oldstderr, sys.stderr.fileno())
92 os.dup2(oldstderr, sys.stderr.fileno())
93 if devnull is not None:
93 if devnull is not None:
94 devnull.close()
94 devnull.close()
95 shutil.rmtree(tmpdir)
95 shutil.rmtree(tmpdir)
96
96
97 # py2exe needs to be installed to work
97 # py2exe needs to be installed to work
98 try:
98 try:
99 import py2exe
99 import py2exe
100 py2exeloaded = True
100 py2exeloaded = True
101
101
102 # Help py2exe to find win32com.shell
102 # Help py2exe to find win32com.shell
103 try:
103 try:
104 import modulefinder
104 import modulefinder
105 import win32com
105 import win32com
106 for p in win32com.__path__[1:]: # Take the path to win32comext
106 for p in win32com.__path__[1:]: # Take the path to win32comext
107 modulefinder.AddPackagePath("win32com", p)
107 modulefinder.AddPackagePath("win32com", p)
108 pn = "win32com.shell"
108 pn = "win32com.shell"
109 __import__(pn)
109 __import__(pn)
110 m = sys.modules[pn]
110 m = sys.modules[pn]
111 for p in m.__path__[1:]:
111 for p in m.__path__[1:]:
112 modulefinder.AddPackagePath(pn, p)
112 modulefinder.AddPackagePath(pn, p)
113 except ImportError:
113 except ImportError:
114 pass
114 pass
115
115
116 except ImportError:
116 except ImportError:
117 py2exeloaded = False
117 py2exeloaded = False
118 pass
118 pass
119
119
120 def runcmd(cmd, env):
120 def runcmd(cmd, env):
121 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
121 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
122 stderr=subprocess.PIPE, env=env)
122 stderr=subprocess.PIPE, env=env)
123 out, err = p.communicate()
123 out, err = p.communicate()
124 # If root is executing setup.py, but the repository is owned by
124 # If root is executing setup.py, but the repository is owned by
125 # another user (as in "sudo python setup.py install") we will get
125 # another user (as in "sudo python setup.py install") we will get
126 # trust warnings since the .hg/hgrc file is untrusted. That is
126 # trust warnings since the .hg/hgrc file is untrusted. That is
127 # fine, we don't want to load it anyway. Python may warn about
127 # fine, we don't want to load it anyway. Python may warn about
128 # a missing __init__.py in mercurial/locale, we also ignore that.
128 # a missing __init__.py in mercurial/locale, we also ignore that.
129 err = [e for e in err.splitlines()
129 err = [e for e in err.splitlines()
130 if not e.startswith(b('Not trusting file')) \
130 if not e.startswith(b('Not trusting file')) \
131 and not e.startswith(b('warning: Not importing'))]
131 and not e.startswith(b('warning: Not importing'))]
132 if err:
132 if err:
133 return ''
133 return ''
134 return out
134 return out
135
135
136 version = ''
136 version = ''
137
137
138 if os.path.isdir('.hg'):
138 if os.path.isdir('.hg'):
139 # Execute hg out of this directory with a custom environment which
139 # Execute hg out of this directory with a custom environment which
140 # includes the pure Python modules in mercurial/pure. We also take
140 # includes the pure Python modules in mercurial/pure. We also take
141 # care to not use any hgrc files and do no localization.
141 # care to not use any hgrc files and do no localization.
142 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
142 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
143 env = {'PYTHONPATH': os.pathsep.join(pypath),
143 env = {'PYTHONPATH': os.pathsep.join(pypath),
144 'HGRCPATH': '',
144 'HGRCPATH': '',
145 'LANGUAGE': 'C'}
145 'LANGUAGE': 'C'}
146 if 'LD_LIBRARY_PATH' in os.environ:
146 if 'LD_LIBRARY_PATH' in os.environ:
147 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
147 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
148 if 'SystemRoot' in os.environ:
148 if 'SystemRoot' in os.environ:
149 # Copy SystemRoot into the custom environment for Python 2.6
149 # Copy SystemRoot into the custom environment for Python 2.6
150 # under Windows. Otherwise, the subprocess will fail with
150 # under Windows. Otherwise, the subprocess will fail with
151 # error 0xc0150004. See: http://bugs.python.org/issue3440
151 # error 0xc0150004. See: http://bugs.python.org/issue3440
152 env['SystemRoot'] = os.environ['SystemRoot']
152 env['SystemRoot'] = os.environ['SystemRoot']
153 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
153 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
154 l = runcmd(cmd, env).split()
154 l = runcmd(cmd, env).split()
155 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
155 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
156 l.pop()
156 l.pop()
157 if len(l) > 1: # tag found
157 if len(l) > 1: # tag found
158 version = l[-1]
158 version = l[-1]
159 if l[0].endswith('+'): # propagate the dirty status to the tag
159 if l[0].endswith('+'): # propagate the dirty status to the tag
160 version += '+'
160 version += '+'
161 elif len(l) == 1: # no tag found
161 elif len(l) == 1: # no tag found
162 cmd = [sys.executable, 'hg', 'parents', '--template',
162 cmd = [sys.executable, 'hg', 'parents', '--template',
163 '{latesttag}+{latesttagdistance}-']
163 '{latesttag}+{latesttagdistance}-']
164 version = runcmd(cmd, env) + l[0]
164 version = runcmd(cmd, env) + l[0]
165 if version.endswith('+'):
165 if version.endswith('+'):
166 version += time.strftime('%Y%m%d')
166 version += time.strftime('%Y%m%d')
167 elif os.path.exists('.hg_archival.txt'):
167 elif os.path.exists('.hg_archival.txt'):
168 kw = dict([[t.strip() for t in l.split(':', 1)]
168 kw = dict([[t.strip() for t in l.split(':', 1)]
169 for l in open('.hg_archival.txt')])
169 for l in open('.hg_archival.txt')])
170 if 'tag' in kw:
170 if 'tag' in kw:
171 version = kw['tag']
171 version = kw['tag']
172 elif 'latesttag' in kw:
172 elif 'latesttag' in kw:
173 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
173 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
174 else:
174 else:
175 version = kw.get('node', '')[:12]
175 version = kw.get('node', '')[:12]
176
176
177 if version:
177 if version:
178 f = open("mercurial/__version__.py", "w")
178 f = open("mercurial/__version__.py", "w")
179 f.write('# this file is autogenerated by setup.py\n')
179 f.write('# this file is autogenerated by setup.py\n')
180 f.write('version = "%s"\n' % version)
180 f.write('version = "%s"\n' % version)
181 f.close()
181 f.close()
182
182
183
183
184 try:
184 try:
185 from mercurial import __version__
185 from mercurial import __version__
186 version = __version__.version
186 version = __version__.version
187 except ImportError:
187 except ImportError:
188 version = 'unknown'
188 version = 'unknown'
189
189
190 class hgbuildmo(build):
190 class hgbuildmo(build):
191
191
192 description = "build translations (.mo files)"
192 description = "build translations (.mo files)"
193
193
194 def run(self):
194 def run(self):
195 if not find_executable('msgfmt'):
195 if not find_executable('msgfmt'):
196 self.warn("could not find msgfmt executable, no translations "
196 self.warn("could not find msgfmt executable, no translations "
197 "will be built")
197 "will be built")
198 return
198 return
199
199
200 podir = 'i18n'
200 podir = 'i18n'
201 if not os.path.isdir(podir):
201 if not os.path.isdir(podir):
202 self.warn("could not find %s/ directory" % podir)
202 self.warn("could not find %s/ directory" % podir)
203 return
203 return
204
204
205 join = os.path.join
205 join = os.path.join
206 for po in os.listdir(podir):
206 for po in os.listdir(podir):
207 if not po.endswith('.po'):
207 if not po.endswith('.po'):
208 continue
208 continue
209 pofile = join(podir, po)
209 pofile = join(podir, po)
210 modir = join('locale', po[:-3], 'LC_MESSAGES')
210 modir = join('locale', po[:-3], 'LC_MESSAGES')
211 mofile = join(modir, 'hg.mo')
211 mofile = join(modir, 'hg.mo')
212 mobuildfile = join('mercurial', mofile)
212 mobuildfile = join('mercurial', mofile)
213 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
213 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
214 if sys.platform != 'sunos5':
214 if sys.platform != 'sunos5':
215 # msgfmt on Solaris does not know about -c
215 # msgfmt on Solaris does not know about -c
216 cmd.append('-c')
216 cmd.append('-c')
217 self.mkpath(join('mercurial', modir))
217 self.mkpath(join('mercurial', modir))
218 self.make_file([pofile], mobuildfile, spawn, (cmd,))
218 self.make_file([pofile], mobuildfile, spawn, (cmd,))
219
219
220 # Insert hgbuildmo first so that files in mercurial/locale/ are found
220 # Insert hgbuildmo first so that files in mercurial/locale/ are found
221 # when build_py is run next.
221 # when build_py is run next.
222 build.sub_commands.insert(0, ('build_mo', None))
222 build.sub_commands.insert(0, ('build_mo', None))
223 # We also need build_ext before build_py. Otherwise, when 2to3 is called (in
223 # We also need build_ext before build_py. Otherwise, when 2to3 is called (in
224 # build_py), it will not find osutil & friends, thinking that those modules are
224 # build_py), it will not find osutil & friends, thinking that those modules are
225 # global and, consequently, making a mess, now that all module imports are
225 # global and, consequently, making a mess, now that all module imports are
226 # global.
226 # global.
227 build.sub_commands.insert(1, ('build_ext', None))
227 build.sub_commands.insert(1, ('build_ext', None))
228
228
229 Distribution.pure = 0
229 Distribution.pure = 0
230 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
230 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
231 "code instead of C extensions"))
231 "code instead of C extensions"))
232
232
233 class hgbuildext(build_ext):
233 class hgbuildext(build_ext):
234
234
235 def build_extension(self, ext):
235 def build_extension(self, ext):
236 try:
236 try:
237 build_ext.build_extension(self, ext)
237 build_ext.build_extension(self, ext)
238 except CCompilerError:
238 except CCompilerError:
239 if not hasattr(ext, 'optional') or not ext.optional:
239 if getattr(ext, 'optional', False):
240 raise
240 raise
241 log.warn("Failed to build optional extension '%s' (skipping)",
241 log.warn("Failed to build optional extension '%s' (skipping)",
242 ext.name)
242 ext.name)
243
243
244 class hgbuildpy(build_py_2to3):
244 class hgbuildpy(build_py_2to3):
245 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
245 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
246 getfixers("hgfixes")))
246 getfixers("hgfixes")))
247
247
248 def finalize_options(self):
248 def finalize_options(self):
249 build_py.finalize_options(self)
249 build_py.finalize_options(self)
250
250
251 if self.distribution.pure:
251 if self.distribution.pure:
252 if self.py_modules is None:
252 if self.py_modules is None:
253 self.py_modules = []
253 self.py_modules = []
254 for ext in self.distribution.ext_modules:
254 for ext in self.distribution.ext_modules:
255 if ext.name.startswith("mercurial."):
255 if ext.name.startswith("mercurial."):
256 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
256 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
257 self.distribution.ext_modules = []
257 self.distribution.ext_modules = []
258
258
259 def find_modules(self):
259 def find_modules(self):
260 modules = build_py.find_modules(self)
260 modules = build_py.find_modules(self)
261 for module in modules:
261 for module in modules:
262 if module[0] == "mercurial.pure":
262 if module[0] == "mercurial.pure":
263 if module[1] != "__init__":
263 if module[1] != "__init__":
264 yield ("mercurial", module[1], module[2])
264 yield ("mercurial", module[1], module[2])
265 else:
265 else:
266 yield module
266 yield module
267
267
268 def run(self):
268 def run(self):
269 # In the build_py_2to3 class, self.updated_files = [], but I couldn't
269 # In the build_py_2to3 class, self.updated_files = [], but I couldn't
270 # see when that variable was updated to point to the updated files, as
270 # see when that variable was updated to point to the updated files, as
271 # its names suggests. Thus, I decided to just find_all_modules and feed
271 # its names suggests. Thus, I decided to just find_all_modules and feed
272 # them to 2to3. Unfortunately, subsequent calls to setup3k.py will
272 # them to 2to3. Unfortunately, subsequent calls to setup3k.py will
273 # incur in 2to3 analysis overhead.
273 # incur in 2to3 analysis overhead.
274 self.updated_files = [i[2] for i in self.find_all_modules()]
274 self.updated_files = [i[2] for i in self.find_all_modules()]
275
275
276 # Base class code
276 # Base class code
277 if self.py_modules:
277 if self.py_modules:
278 self.build_modules()
278 self.build_modules()
279 if self.packages:
279 if self.packages:
280 self.build_packages()
280 self.build_packages()
281 self.build_package_data()
281 self.build_package_data()
282
282
283 # 2to3
283 # 2to3
284 self.run_2to3(self.updated_files)
284 self.run_2to3(self.updated_files)
285
285
286 # Remaining base class code
286 # Remaining base class code
287 self.byte_compile(self.get_outputs(include_bytecode=0))
287 self.byte_compile(self.get_outputs(include_bytecode=0))
288
288
289 cmdclass = {'build_mo': hgbuildmo,
289 cmdclass = {'build_mo': hgbuildmo,
290 'build_ext': hgbuildext,
290 'build_ext': hgbuildext,
291 'build_py': hgbuildpy}
291 'build_py': hgbuildpy}
292
292
293 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
293 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
294 'hgext.highlight', 'hgext.zeroconf']
294 'hgext.highlight', 'hgext.zeroconf']
295
295
296 pymodules = []
296 pymodules = []
297
297
298 extmodules = [
298 extmodules = [
299 Extension('mercurial.base85', ['mercurial/base85.c']),
299 Extension('mercurial.base85', ['mercurial/base85.c']),
300 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
300 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
301 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
301 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
302 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
302 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
303 Extension('mercurial.parsers', ['mercurial/parsers.c']),
303 Extension('mercurial.parsers', ['mercurial/parsers.c']),
304 ]
304 ]
305
305
306 # disable osutil.c under windows + python 2.4 (issue1364)
306 # disable osutil.c under windows + python 2.4 (issue1364)
307 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
307 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
308 pymodules.append('mercurial.pure.osutil')
308 pymodules.append('mercurial.pure.osutil')
309 else:
309 else:
310 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
310 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
311
311
312 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
312 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
313 # The inotify extension is only usable with Linux 2.6 kernels.
313 # The inotify extension is only usable with Linux 2.6 kernels.
314 # You also need a reasonably recent C library.
314 # You also need a reasonably recent C library.
315 # In any case, if it fails to build the error will be skipped ('optional').
315 # In any case, if it fails to build the error will be skipped ('optional').
316 cc = new_compiler()
316 cc = new_compiler()
317 if hasfunction(cc, 'inotify_add_watch'):
317 if hasfunction(cc, 'inotify_add_watch'):
318 inotify = Extension('hgext.inotify.linux._inotify',
318 inotify = Extension('hgext.inotify.linux._inotify',
319 ['hgext/inotify/linux/_inotify.c'],
319 ['hgext/inotify/linux/_inotify.c'],
320 ['mercurial'])
320 ['mercurial'])
321 inotify.optional = True
321 inotify.optional = True
322 extmodules.append(inotify)
322 extmodules.append(inotify)
323 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
323 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
324
324
325 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
325 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
326 'help/*.txt']}
326 'help/*.txt']}
327
327
328 def ordinarypath(p):
328 def ordinarypath(p):
329 return p and p[0] != '.' and p[-1] != '~'
329 return p and p[0] != '.' and p[-1] != '~'
330
330
331 for root in ('templates',):
331 for root in ('templates',):
332 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
332 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
333 curdir = curdir.split(os.sep, 1)[1]
333 curdir = curdir.split(os.sep, 1)[1]
334 dirs[:] = filter(ordinarypath, dirs)
334 dirs[:] = filter(ordinarypath, dirs)
335 for f in filter(ordinarypath, files):
335 for f in filter(ordinarypath, files):
336 f = os.path.join(curdir, f)
336 f = os.path.join(curdir, f)
337 packagedata['mercurial'].append(f)
337 packagedata['mercurial'].append(f)
338
338
339 datafiles = []
339 datafiles = []
340 setupversion = version
340 setupversion = version
341 extra = {}
341 extra = {}
342
342
343 if py2exeloaded:
343 if py2exeloaded:
344 extra['console'] = [
344 extra['console'] = [
345 {'script':'hg',
345 {'script':'hg',
346 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
346 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
347 'product_version':version}]
347 'product_version':version}]
348
348
349 if os.name == 'nt':
349 if os.name == 'nt':
350 # Windows binary file versions for exe/dll files must have the
350 # Windows binary file versions for exe/dll files must have the
351 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
351 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
352 setupversion = version.split('+', 1)[0]
352 setupversion = version.split('+', 1)[0]
353
353
354 setup(name='mercurial',
354 setup(name='mercurial',
355 version=setupversion,
355 version=setupversion,
356 author='Matt Mackall',
356 author='Matt Mackall',
357 author_email='mpm@selenic.com',
357 author_email='mpm@selenic.com',
358 url='http://mercurial.selenic.com/',
358 url='http://mercurial.selenic.com/',
359 description='Scalable distributed SCM',
359 description='Scalable distributed SCM',
360 license='GNU GPLv2+',
360 license='GNU GPLv2+',
361 scripts=scripts,
361 scripts=scripts,
362 packages=packages,
362 packages=packages,
363 py_modules=pymodules,
363 py_modules=pymodules,
364 ext_modules=extmodules,
364 ext_modules=extmodules,
365 data_files=datafiles,
365 data_files=datafiles,
366 package_data=packagedata,
366 package_data=packagedata,
367 cmdclass=cmdclass,
367 cmdclass=cmdclass,
368 options=dict(py2exe=dict(packages=['hgext', 'email']),
368 options=dict(py2exe=dict(packages=['hgext', 'email']),
369 bdist_mpkg=dict(zipdist=True,
369 bdist_mpkg=dict(zipdist=True,
370 license='COPYING',
370 license='COPYING',
371 readme='contrib/macosx/Readme.html',
371 readme='contrib/macosx/Readme.html',
372 welcome='contrib/macosx/Welcome.html')),
372 welcome='contrib/macosx/Welcome.html')),
373 **extra)
373 **extra)
General Comments 0
You need to be logged in to leave comments. Login now