##// END OF EJS Templates
setup: read .hg_archival.txt for version info (issue1670)...
Jeremy Whitlock -
r8548:3ccbe42f default
parent child Browse files
Show More
@@ -1,251 +1,259 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # 'python setup.py install', or
5 # 'python setup.py install', or
6 # 'python setup.py --help' for more options
6 # 'python setup.py --help' for more options
7
7
8 import sys
8 import sys
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'):
10 raise SystemExit("Mercurial requires Python 2.4 or later.")
10 raise SystemExit("Mercurial requires Python 2.4 or later.")
11
11
12 # Solaris Python packaging brain damage
12 # Solaris Python packaging brain damage
13 try:
13 try:
14 import hashlib
14 import hashlib
15 sha = hashlib.sha1()
15 sha = hashlib.sha1()
16 except:
16 except:
17 try:
17 try:
18 import sha
18 import sha
19 except:
19 except:
20 raise SystemExit(
20 raise SystemExit(
21 "Couldn't import standard hashlib (incomplete Python install).")
21 "Couldn't import standard hashlib (incomplete Python install).")
22
22
23 try:
23 try:
24 import zlib
24 import zlib
25 except:
25 except:
26 raise SystemExit(
26 raise SystemExit(
27 "Couldn't import standard zlib (incomplete Python install).")
27 "Couldn't import standard zlib (incomplete Python install).")
28
28
29 import os, subprocess, time
29 import os, subprocess, time
30 import shutil
30 import shutil
31 import tempfile
31 import tempfile
32 from distutils.core import setup, Extension
32 from distutils.core import setup, Extension
33 from distutils.dist import Distribution
33 from distutils.dist import Distribution
34 from distutils.command.install_data import install_data
34 from distutils.command.install_data import install_data
35 from distutils.command.build import build
35 from distutils.command.build import build
36 from distutils.command.build_py import build_py
36 from distutils.command.build_py import build_py
37 from distutils.spawn import spawn, find_executable
37 from distutils.spawn import spawn, find_executable
38 from distutils.ccompiler import new_compiler
38 from distutils.ccompiler import new_compiler
39
39
40 extra = {}
40 extra = {}
41 scripts = ['hg']
41 scripts = ['hg']
42 if os.name == 'nt':
42 if os.name == 'nt':
43 scripts.append('contrib/win32/hg.bat')
43 scripts.append('contrib/win32/hg.bat')
44
44
45 # simplified version of distutils.ccompiler.CCompiler.has_function
45 # simplified version of distutils.ccompiler.CCompiler.has_function
46 # that actually removes its temporary files.
46 # that actually removes its temporary files.
47 def has_function(cc, funcname):
47 def has_function(cc, funcname):
48 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
48 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
49 devnull = oldstderr = None
49 devnull = oldstderr = None
50 try:
50 try:
51 try:
51 try:
52 fname = os.path.join(tmpdir, 'funcname.c')
52 fname = os.path.join(tmpdir, 'funcname.c')
53 f = open(fname, 'w')
53 f = open(fname, 'w')
54 f.write('int main(void) {\n')
54 f.write('int main(void) {\n')
55 f.write(' %s();\n' % funcname)
55 f.write(' %s();\n' % funcname)
56 f.write('}\n')
56 f.write('}\n')
57 f.close()
57 f.close()
58 # Redirect stderr to /dev/null to hide any error messages
58 # Redirect stderr to /dev/null to hide any error messages
59 # from the compiler.
59 # from the compiler.
60 # This will have to be changed if we ever have to check
60 # This will have to be changed if we ever have to check
61 # for a function on Windows.
61 # for a function on Windows.
62 devnull = open('/dev/null', 'w')
62 devnull = open('/dev/null', 'w')
63 oldstderr = os.dup(sys.stderr.fileno())
63 oldstderr = os.dup(sys.stderr.fileno())
64 os.dup2(devnull.fileno(), sys.stderr.fileno())
64 os.dup2(devnull.fileno(), sys.stderr.fileno())
65 objects = cc.compile([fname])
65 objects = cc.compile([fname])
66 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
66 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
67 except:
67 except:
68 return False
68 return False
69 return True
69 return True
70 finally:
70 finally:
71 if oldstderr is not None:
71 if oldstderr is not None:
72 os.dup2(oldstderr, sys.stderr.fileno())
72 os.dup2(oldstderr, sys.stderr.fileno())
73 if devnull is not None:
73 if devnull is not None:
74 devnull.close()
74 devnull.close()
75 shutil.rmtree(tmpdir)
75 shutil.rmtree(tmpdir)
76
76
77 # py2exe needs to be installed to work
77 # py2exe needs to be installed to work
78 try:
78 try:
79 import py2exe
79 import py2exe
80
80
81 # Help py2exe to find win32com.shell
81 # Help py2exe to find win32com.shell
82 try:
82 try:
83 import modulefinder
83 import modulefinder
84 import win32com
84 import win32com
85 for p in win32com.__path__[1:]: # Take the path to win32comext
85 for p in win32com.__path__[1:]: # Take the path to win32comext
86 modulefinder.AddPackagePath("win32com", p)
86 modulefinder.AddPackagePath("win32com", p)
87 pn = "win32com.shell"
87 pn = "win32com.shell"
88 __import__(pn)
88 __import__(pn)
89 m = sys.modules[pn]
89 m = sys.modules[pn]
90 for p in m.__path__[1:]:
90 for p in m.__path__[1:]:
91 modulefinder.AddPackagePath(pn, p)
91 modulefinder.AddPackagePath(pn, p)
92 except ImportError:
92 except ImportError:
93 pass
93 pass
94
94
95 extra['console'] = ['hg']
95 extra['console'] = ['hg']
96
96
97 except ImportError:
97 except ImportError:
98 pass
98 pass
99
99
100 version = None
101
100 if os.path.isdir('.hg'):
102 if os.path.isdir('.hg'):
101 # execute hg out of this directory with a custom environment which
103 # execute hg out of this directory with a custom environment which
102 # includes the pure Python modules in mercurial/pure
104 # includes the pure Python modules in mercurial/pure
103 pypath = os.environ.get('PYTHONPATH', '')
105 pypath = os.environ.get('PYTHONPATH', '')
104 purepath = os.path.join('mercurial', 'pure')
106 purepath = os.path.join('mercurial', 'pure')
105 os.environ['PYTHONPATH'] = os.pathsep.join(['mercurial', purepath, pypath])
107 os.environ['PYTHONPATH'] = os.pathsep.join(['mercurial', purepath, pypath])
106 os.environ['HGRCPATH'] = '' # do not read any config file
108 os.environ['HGRCPATH'] = '' # do not read any config file
107 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
109 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
108 version = None
109
110
110 l, e = subprocess.Popen(cmd, stdout=subprocess.PIPE,
111 l, e = subprocess.Popen(cmd, stdout=subprocess.PIPE,
111 stderr=subprocess.PIPE).communicate()
112 stderr=subprocess.PIPE).communicate()
112 os.environ['PYTHONPATH'] = pypath
113 os.environ['PYTHONPATH'] = pypath
113
114
114 if e:
115 if e:
115 sys.stderr.write('warning: could not establish Mercurial version: %s'
116 sys.stderr.write('warning: could not establish Mercurial version: %s'
116 % e)
117 % e)
117 else:
118 else:
118 l = l.split()
119 l = l.split()
119 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
120 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
120 l.pop()
121 l.pop()
121 if l:
122 if l:
122 version = l[-1] # latest tag or revision number
123 version = l[-1] # latest tag or revision number
123 if version.endswith('+'):
124 if version.endswith('+'):
124 version += time.strftime('%Y%m%d')
125 version += time.strftime('%Y%m%d')
126 elif os.path.exists('.hg_archival.txt'):
127 hgarchival = open('.hg_archival.txt')
128 for line in hgarchival:
129 if line.startswith('node:'):
130 version = line.split(':')[1].strip()[:12]
131 break
125
132
126 if version:
133 if version:
127 f = file("mercurial/__version__.py", "w")
134 f = file("mercurial/__version__.py", "w")
128 f.write('# this file is autogenerated by setup.py\n')
135 f.write('# this file is autogenerated by setup.py\n')
129 f.write('version = "%s"\n' % version)
136 f.write('version = "%s"\n' % version)
130 f.close()
137 f.close()
138
131
139
132 try:
140 try:
133 from mercurial import __version__
141 from mercurial import __version__
134 version = __version__.version
142 version = __version__.version
135 except ImportError:
143 except ImportError:
136 version = 'unknown'
144 version = 'unknown'
137
145
138 class install_package_data(install_data):
146 class install_package_data(install_data):
139 def finalize_options(self):
147 def finalize_options(self):
140 self.set_undefined_options('install',
148 self.set_undefined_options('install',
141 ('install_lib', 'install_dir'))
149 ('install_lib', 'install_dir'))
142 install_data.finalize_options(self)
150 install_data.finalize_options(self)
143
151
144 class build_mo(build):
152 class build_mo(build):
145
153
146 description = "build translations (.mo files)"
154 description = "build translations (.mo files)"
147
155
148 def run(self):
156 def run(self):
149 if not find_executable('msgfmt'):
157 if not find_executable('msgfmt'):
150 self.warn("could not find msgfmt executable, no translations "
158 self.warn("could not find msgfmt executable, no translations "
151 "will be built")
159 "will be built")
152 return
160 return
153
161
154 podir = 'i18n'
162 podir = 'i18n'
155 if not os.path.isdir(podir):
163 if not os.path.isdir(podir):
156 self.warn("could not find %s/ directory" % podir)
164 self.warn("could not find %s/ directory" % podir)
157 return
165 return
158
166
159 join = os.path.join
167 join = os.path.join
160 for po in os.listdir(podir):
168 for po in os.listdir(podir):
161 if not po.endswith('.po'):
169 if not po.endswith('.po'):
162 continue
170 continue
163 pofile = join(podir, po)
171 pofile = join(podir, po)
164 modir = join('locale', po[:-3], 'LC_MESSAGES')
172 modir = join('locale', po[:-3], 'LC_MESSAGES')
165 mofile = join(modir, 'hg.mo')
173 mofile = join(modir, 'hg.mo')
166 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
174 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
167 if sys.platform != 'sunos5':
175 if sys.platform != 'sunos5':
168 # msgfmt on Solaris does not know about -c
176 # msgfmt on Solaris does not know about -c
169 cmd.append('-c')
177 cmd.append('-c')
170 self.mkpath(modir)
178 self.mkpath(modir)
171 self.make_file([pofile], mofile, spawn, (cmd,))
179 self.make_file([pofile], mofile, spawn, (cmd,))
172 self.distribution.data_files.append((join('mercurial', modir),
180 self.distribution.data_files.append((join('mercurial', modir),
173 [mofile]))
181 [mofile]))
174
182
175 build.sub_commands.append(('build_mo', None))
183 build.sub_commands.append(('build_mo', None))
176
184
177 Distribution.pure = 0
185 Distribution.pure = 0
178 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
186 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
179 "code instead of C extensions"))
187 "code instead of C extensions"))
180
188
181 class hg_build_py(build_py):
189 class hg_build_py(build_py):
182
190
183 def finalize_options(self):
191 def finalize_options(self):
184 build_py.finalize_options(self)
192 build_py.finalize_options(self)
185
193
186 if self.distribution.pure:
194 if self.distribution.pure:
187 if self.py_modules is None:
195 if self.py_modules is None:
188 self.py_modules = []
196 self.py_modules = []
189 for ext in self.distribution.ext_modules:
197 for ext in self.distribution.ext_modules:
190 if ext.name.startswith("mercurial."):
198 if ext.name.startswith("mercurial."):
191 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
199 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
192 self.distribution.ext_modules = []
200 self.distribution.ext_modules = []
193
201
194 def find_modules(self):
202 def find_modules(self):
195 modules = build_py.find_modules(self)
203 modules = build_py.find_modules(self)
196 for module in modules:
204 for module in modules:
197 if module[0] == "mercurial.pure":
205 if module[0] == "mercurial.pure":
198 if module[1] != "__init__":
206 if module[1] != "__init__":
199 yield ("mercurial", module[1], module[2])
207 yield ("mercurial", module[1], module[2])
200 else:
208 else:
201 yield module
209 yield module
202
210
203 cmdclass = {'install_data': install_package_data,
211 cmdclass = {'install_data': install_package_data,
204 'build_mo': build_mo,
212 'build_mo': build_mo,
205 'build_py': hg_build_py}
213 'build_py': hg_build_py}
206
214
207 ext_modules=[
215 ext_modules=[
208 Extension('mercurial.base85', ['mercurial/base85.c']),
216 Extension('mercurial.base85', ['mercurial/base85.c']),
209 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
217 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
210 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
218 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
211 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
219 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
212 Extension('mercurial.parsers', ['mercurial/parsers.c']),
220 Extension('mercurial.parsers', ['mercurial/parsers.c']),
213 Extension('mercurial.osutil', ['mercurial/osutil.c']),
221 Extension('mercurial.osutil', ['mercurial/osutil.c']),
214 ]
222 ]
215
223
216 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
224 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
217 'hgext.highlight', 'hgext.zeroconf', ]
225 'hgext.highlight', 'hgext.zeroconf', ]
218
226
219 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
227 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
220 # The inotify extension is only usable with Linux 2.6 kernels.
228 # The inotify extension is only usable with Linux 2.6 kernels.
221 # You also need a reasonably recent C library.
229 # You also need a reasonably recent C library.
222 cc = new_compiler()
230 cc = new_compiler()
223 if has_function(cc, 'inotify_add_watch'):
231 if has_function(cc, 'inotify_add_watch'):
224 ext_modules.append(Extension('hgext.inotify.linux._inotify',
232 ext_modules.append(Extension('hgext.inotify.linux._inotify',
225 ['hgext/inotify/linux/_inotify.c']))
233 ['hgext/inotify/linux/_inotify.c']))
226 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
234 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
227
235
228 datafiles = []
236 datafiles = []
229 for root in ('templates', 'i18n'):
237 for root in ('templates', 'i18n'):
230 for dir, dirs, files in os.walk(root):
238 for dir, dirs, files in os.walk(root):
231 datafiles.append((os.path.join('mercurial', dir),
239 datafiles.append((os.path.join('mercurial', dir),
232 [os.path.join(dir, file_) for file_ in files]))
240 [os.path.join(dir, file_) for file_ in files]))
233
241
234 setup(name='mercurial',
242 setup(name='mercurial',
235 version=version,
243 version=version,
236 author='Matt Mackall',
244 author='Matt Mackall',
237 author_email='mpm@selenic.com',
245 author_email='mpm@selenic.com',
238 url='http://selenic.com/mercurial',
246 url='http://selenic.com/mercurial',
239 description='Scalable distributed SCM',
247 description='Scalable distributed SCM',
240 license='GNU GPL',
248 license='GNU GPL',
241 scripts=scripts,
249 scripts=scripts,
242 packages=packages,
250 packages=packages,
243 ext_modules=ext_modules,
251 ext_modules=ext_modules,
244 data_files=datafiles,
252 data_files=datafiles,
245 cmdclass=cmdclass,
253 cmdclass=cmdclass,
246 options=dict(py2exe=dict(packages=['hgext', 'email']),
254 options=dict(py2exe=dict(packages=['hgext', 'email']),
247 bdist_mpkg=dict(zipdist=True,
255 bdist_mpkg=dict(zipdist=True,
248 license='COPYING',
256 license='COPYING',
249 readme='contrib/macosx/Readme.html',
257 readme='contrib/macosx/Readme.html',
250 welcome='contrib/macosx/Welcome.html')),
258 welcome='contrib/macosx/Welcome.html')),
251 **extra)
259 **extra)
General Comments 0
You need to be logged in to leave comments. Login now