##// END OF EJS Templates
setup: get version number using pure Python modules
Martin Geisler -
r7721:a1138f43 default
parent child Browse files
Show More
@@ -1,211 +1,218 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, 3, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
10 raise SystemExit("Mercurial requires python 2.3 or later.")
10 raise SystemExit("Mercurial requires python 2.3 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, time
29 import os, 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.command.install_data import install_data
33 from distutils.command.install_data import install_data
34 from distutils.command.build import build
34 from distutils.command.build import build
35 from distutils.spawn import spawn, find_executable
35 from distutils.spawn import spawn, find_executable
36 from distutils.ccompiler import new_compiler
36 from distutils.ccompiler import new_compiler
37
37
38 extra = {}
38 extra = {}
39 scripts = ['hg']
39 scripts = ['hg']
40 if os.name == 'nt':
40 if os.name == 'nt':
41 scripts.append('contrib/win32/hg.bat')
41 scripts.append('contrib/win32/hg.bat')
42
42
43 # simplified version of distutils.ccompiler.CCompiler.has_function
43 # simplified version of distutils.ccompiler.CCompiler.has_function
44 # that actually removes its temporary files.
44 # that actually removes its temporary files.
45 def has_function(cc, funcname):
45 def has_function(cc, funcname):
46 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
46 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
47 devnull = oldstderr = None
47 devnull = oldstderr = None
48 try:
48 try:
49 try:
49 try:
50 fname = os.path.join(tmpdir, 'funcname.c')
50 fname = os.path.join(tmpdir, 'funcname.c')
51 f = open(fname, 'w')
51 f = open(fname, 'w')
52 f.write('int main(void) {\n')
52 f.write('int main(void) {\n')
53 f.write(' %s();\n' % funcname)
53 f.write(' %s();\n' % funcname)
54 f.write('}\n')
54 f.write('}\n')
55 f.close()
55 f.close()
56 # Redirect stderr to /dev/null to hide any error messages
56 # Redirect stderr to /dev/null to hide any error messages
57 # from the compiler.
57 # from the compiler.
58 # This will have to be changed if we ever have to check
58 # This will have to be changed if we ever have to check
59 # for a function on Windows.
59 # for a function on Windows.
60 devnull = open('/dev/null', 'w')
60 devnull = open('/dev/null', 'w')
61 oldstderr = os.dup(sys.stderr.fileno())
61 oldstderr = os.dup(sys.stderr.fileno())
62 os.dup2(devnull.fileno(), sys.stderr.fileno())
62 os.dup2(devnull.fileno(), sys.stderr.fileno())
63 objects = cc.compile([fname])
63 objects = cc.compile([fname])
64 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
64 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
65 except:
65 except:
66 return False
66 return False
67 return True
67 return True
68 finally:
68 finally:
69 if oldstderr is not None:
69 if oldstderr is not None:
70 os.dup2(oldstderr, sys.stderr.fileno())
70 os.dup2(oldstderr, sys.stderr.fileno())
71 if devnull is not None:
71 if devnull is not None:
72 devnull.close()
72 devnull.close()
73 shutil.rmtree(tmpdir)
73 shutil.rmtree(tmpdir)
74
74
75 # py2exe needs to be installed to work
75 # py2exe needs to be installed to work
76 try:
76 try:
77 import py2exe
77 import py2exe
78
78
79 # Help py2exe to find win32com.shell
79 # Help py2exe to find win32com.shell
80 try:
80 try:
81 import modulefinder
81 import modulefinder
82 import win32com
82 import win32com
83 for p in win32com.__path__[1:]: # Take the path to win32comext
83 for p in win32com.__path__[1:]: # Take the path to win32comext
84 modulefinder.AddPackagePath("win32com", p)
84 modulefinder.AddPackagePath("win32com", p)
85 pn = "win32com.shell"
85 pn = "win32com.shell"
86 __import__(pn)
86 __import__(pn)
87 m = sys.modules[pn]
87 m = sys.modules[pn]
88 for p in m.__path__[1:]:
88 for p in m.__path__[1:]:
89 modulefinder.AddPackagePath(pn, p)
89 modulefinder.AddPackagePath(pn, p)
90 except ImportError:
90 except ImportError:
91 pass
91 pass
92
92
93 extra['console'] = ['hg']
93 extra['console'] = ['hg']
94
94
95 except ImportError:
95 except ImportError:
96 pass
96 pass
97
97
98 try:
98 try:
99 l = os.popen('hg id -it').read().split()
99 # execute hg out of this directory with a custom environment which
100 # includes the pure Python modules in mercurial/pure
101 pypath = os.environ.get('PYTHONPATH', '')
102 purepath = os.path.join('mercurial', 'pure')
103 os.environ['PYTHONPATH'] = os.pathsep.join(['mercurial', purepath, pypath])
104 cmd = '%s id -it' % os.path.join('.', 'hg')
105 l = os.popen(cmd).read().split()
106 os.environ['PYTHONPATH'] = pypath
100 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
107 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
101 l.pop()
108 l.pop()
102 version = l and l[-1] or 'unknown' # latest tag or revision number
109 version = l and l[-1] or 'unknown' # latest tag or revision number
103 if version.endswith('+'):
110 if version.endswith('+'):
104 version += time.strftime('%Y%m%d')
111 version += time.strftime('%Y%m%d')
105
112
106 except OSError:
113 except OSError:
107 version = "unknown"
114 version = "unknown"
108
115
109 f = file("mercurial/__version__.py", "w")
116 f = file("mercurial/__version__.py", "w")
110 f.write('# this file is autogenerated by setup.py\n')
117 f.write('# this file is autogenerated by setup.py\n')
111 f.write('version = "%s"\n' % version)
118 f.write('version = "%s"\n' % version)
112 f.close()
119 f.close()
113
120
114 class install_package_data(install_data):
121 class install_package_data(install_data):
115 def finalize_options(self):
122 def finalize_options(self):
116 self.set_undefined_options('install',
123 self.set_undefined_options('install',
117 ('install_lib', 'install_dir'))
124 ('install_lib', 'install_dir'))
118 install_data.finalize_options(self)
125 install_data.finalize_options(self)
119
126
120 class build_mo(build):
127 class build_mo(build):
121
128
122 description = "build translations (.mo files)"
129 description = "build translations (.mo files)"
123
130
124 def run(self):
131 def run(self):
125 if not find_executable('msgfmt'):
132 if not find_executable('msgfmt'):
126 self.warn("could not find msgfmt executable, no translations "
133 self.warn("could not find msgfmt executable, no translations "
127 "will be built")
134 "will be built")
128 return
135 return
129
136
130 podir = 'i18n'
137 podir = 'i18n'
131 if not os.path.isdir(podir):
138 if not os.path.isdir(podir):
132 self.warn("could not find %s/ directory" % podir)
139 self.warn("could not find %s/ directory" % podir)
133 return
140 return
134
141
135 join = os.path.join
142 join = os.path.join
136 for po in os.listdir(podir):
143 for po in os.listdir(podir):
137 if not po.endswith('.po'):
144 if not po.endswith('.po'):
138 continue
145 continue
139 pofile = join(podir, po)
146 pofile = join(podir, po)
140 modir = join('locale', po[:-3], 'LC_MESSAGES')
147 modir = join('locale', po[:-3], 'LC_MESSAGES')
141 mofile = join(modir, 'hg.mo')
148 mofile = join(modir, 'hg.mo')
142 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
149 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
143 if sys.platform != 'sunos5':
150 if sys.platform != 'sunos5':
144 # msgfmt on Solaris does not know about -c
151 # msgfmt on Solaris does not know about -c
145 cmd.append('-c')
152 cmd.append('-c')
146 self.mkpath(modir)
153 self.mkpath(modir)
147 self.make_file([pofile], mofile, spawn, (cmd,))
154 self.make_file([pofile], mofile, spawn, (cmd,))
148 self.distribution.data_files.append((join('mercurial', modir),
155 self.distribution.data_files.append((join('mercurial', modir),
149 [mofile]))
156 [mofile]))
150
157
151 build.sub_commands.append(('build_mo', None))
158 build.sub_commands.append(('build_mo', None))
152
159
153 cmdclass = {'install_data': install_package_data,
160 cmdclass = {'install_data': install_package_data,
154 'build_mo': build_mo}
161 'build_mo': build_mo}
155
162
156 ext_modules=[
163 ext_modules=[
157 Extension('mercurial.base85', ['mercurial/base85.c']),
164 Extension('mercurial.base85', ['mercurial/base85.c']),
158 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
165 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
159 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
166 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
160 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
167 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
161 Extension('mercurial.parsers', ['mercurial/parsers.c']),
168 Extension('mercurial.parsers', ['mercurial/parsers.c']),
162 ]
169 ]
163
170
164 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
171 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
165 'hgext.highlight', 'hgext.zeroconf', ]
172 'hgext.highlight', 'hgext.zeroconf', ]
166
173
167 try:
174 try:
168 import msvcrt
175 import msvcrt
169 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
176 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
170 except ImportError:
177 except ImportError:
171 pass
178 pass
172
179
173 try:
180 try:
174 import posix
181 import posix
175 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
182 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
176
183
177 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
184 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
178 # The inotify extension is only usable with Linux 2.6 kernels.
185 # The inotify extension is only usable with Linux 2.6 kernels.
179 # You also need a reasonably recent C library.
186 # You also need a reasonably recent C library.
180 cc = new_compiler()
187 cc = new_compiler()
181 if has_function(cc, 'inotify_add_watch'):
188 if has_function(cc, 'inotify_add_watch'):
182 ext_modules.append(Extension('hgext.inotify.linux._inotify',
189 ext_modules.append(Extension('hgext.inotify.linux._inotify',
183 ['hgext/inotify/linux/_inotify.c']))
190 ['hgext/inotify/linux/_inotify.c']))
184 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
191 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
185 except ImportError:
192 except ImportError:
186 pass
193 pass
187
194
188 datafiles = []
195 datafiles = []
189 for root in ('templates', 'i18n'):
196 for root in ('templates', 'i18n'):
190 for dir, dirs, files in os.walk(root):
197 for dir, dirs, files in os.walk(root):
191 datafiles.append((os.path.join('mercurial', dir),
198 datafiles.append((os.path.join('mercurial', dir),
192 [os.path.join(dir, file_) for file_ in files]))
199 [os.path.join(dir, file_) for file_ in files]))
193
200
194 setup(name='mercurial',
201 setup(name='mercurial',
195 version=version,
202 version=version,
196 author='Matt Mackall',
203 author='Matt Mackall',
197 author_email='mpm@selenic.com',
204 author_email='mpm@selenic.com',
198 url='http://selenic.com/mercurial',
205 url='http://selenic.com/mercurial',
199 description='Scalable distributed SCM',
206 description='Scalable distributed SCM',
200 license='GNU GPL',
207 license='GNU GPL',
201 scripts=scripts,
208 scripts=scripts,
202 packages=packages,
209 packages=packages,
203 ext_modules=ext_modules,
210 ext_modules=ext_modules,
204 data_files=datafiles,
211 data_files=datafiles,
205 cmdclass=cmdclass,
212 cmdclass=cmdclass,
206 options=dict(py2exe=dict(packages=['hgext', 'email']),
213 options=dict(py2exe=dict(packages=['hgext', 'email']),
207 bdist_mpkg=dict(zipdist=True,
214 bdist_mpkg=dict(zipdist=True,
208 license='COPYING',
215 license='COPYING',
209 readme='contrib/macosx/Readme.html',
216 readme='contrib/macosx/Readme.html',
210 welcome='contrib/macosx/Welcome.html')),
217 welcome='contrib/macosx/Welcome.html')),
211 **extra)
218 **extra)
General Comments 0
You need to be logged in to leave comments. Login now