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