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