##// END OF EJS Templates
Don't copy hidden files/directories during `setup.py install`...
James Abbatiello <abbeyj at gmail.com> -
r9129:395b0e13 default
parent child Browse files
Show More
@@ -1,271 +1,273 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], output_dir=tmpdir)
65 objects = cc.compile([fname], output_dir=tmpdir)
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
100 version = None
101
101
102 if os.path.isdir('.hg'):
102 if os.path.isdir('.hg'):
103 # Execute hg out of this directory with a custom environment which
103 # Execute hg out of this directory with a custom environment which
104 # includes the pure Python modules in mercurial/pure. We also take
104 # includes the pure Python modules in mercurial/pure. We also take
105 # care to not use any hgrc files and do no localization.
105 # care to not use any hgrc files and do no localization.
106 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
106 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
107 env = {'PYTHONPATH': os.pathsep.join(pypath),
107 env = {'PYTHONPATH': os.pathsep.join(pypath),
108 'HGRCPATH': '',
108 'HGRCPATH': '',
109 'LANGUAGE': 'C'}
109 'LANGUAGE': 'C'}
110 if 'SystemRoot' in os.environ:
110 if 'SystemRoot' in os.environ:
111 # Copy SystemRoot into the custom environment for Python 2.6
111 # Copy SystemRoot into the custom environment for Python 2.6
112 # under Windows. Otherwise, the subprocess will fail with
112 # under Windows. Otherwise, the subprocess will fail with
113 # error 0xc0150004. See: http://bugs.python.org/issue3440
113 # error 0xc0150004. See: http://bugs.python.org/issue3440
114 env['SystemRoot'] = os.environ['SystemRoot']
114 env['SystemRoot'] = os.environ['SystemRoot']
115 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
115 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
116
116
117 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
117 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
118 stderr=subprocess.PIPE, env=env)
118 stderr=subprocess.PIPE, env=env)
119 out, err = p.communicate()
119 out, err = p.communicate()
120
120
121 # If root is executing setup.py, but the repository is owned by
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
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
123 # trust warnings since the .hg/hgrc file is untrusted. That is
124 # fine, we don't want to load it anyway.
124 # fine, we don't want to load it anyway.
125 err = [e for e in err.splitlines()
125 err = [e for e in err.splitlines()
126 if not e.startswith('Not trusting file')]
126 if not e.startswith('Not trusting file')]
127 if err:
127 if err:
128 sys.stderr.write('warning: could not establish Mercurial '
128 sys.stderr.write('warning: could not establish Mercurial '
129 'version:\n%s\n' % '\n'.join(err))
129 'version:\n%s\n' % '\n'.join(err))
130 else:
130 else:
131 l = out.split()
131 l = out.split()
132 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
132 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
133 l.pop()
133 l.pop()
134 if l:
134 if l:
135 version = l[-1] # latest tag or revision number
135 version = l[-1] # latest tag or revision number
136 if version.endswith('+'):
136 if version.endswith('+'):
137 version += time.strftime('%Y%m%d')
137 version += time.strftime('%Y%m%d')
138 elif os.path.exists('.hg_archival.txt'):
138 elif os.path.exists('.hg_archival.txt'):
139 hgarchival = open('.hg_archival.txt')
139 hgarchival = open('.hg_archival.txt')
140 for line in hgarchival:
140 for line in hgarchival:
141 if line.startswith('node:'):
141 if line.startswith('node:'):
142 version = line.split(':')[1].strip()[:12]
142 version = line.split(':')[1].strip()[:12]
143 break
143 break
144
144
145 if version:
145 if version:
146 f = file("mercurial/__version__.py", "w")
146 f = file("mercurial/__version__.py", "w")
147 f.write('# this file is autogenerated by setup.py\n')
147 f.write('# this file is autogenerated by setup.py\n')
148 f.write('version = "%s"\n' % version)
148 f.write('version = "%s"\n' % version)
149 f.close()
149 f.close()
150
150
151
151
152 try:
152 try:
153 from mercurial import __version__
153 from mercurial import __version__
154 version = __version__.version
154 version = __version__.version
155 except ImportError:
155 except ImportError:
156 version = 'unknown'
156 version = 'unknown'
157
157
158 class install_package_data(install_data):
158 class install_package_data(install_data):
159 def finalize_options(self):
159 def finalize_options(self):
160 self.set_undefined_options('install',
160 self.set_undefined_options('install',
161 ('install_lib', 'install_dir'))
161 ('install_lib', 'install_dir'))
162 install_data.finalize_options(self)
162 install_data.finalize_options(self)
163
163
164 class build_mo(build):
164 class build_mo(build):
165
165
166 description = "build translations (.mo files)"
166 description = "build translations (.mo files)"
167
167
168 def run(self):
168 def run(self):
169 if not find_executable('msgfmt'):
169 if not find_executable('msgfmt'):
170 self.warn("could not find msgfmt executable, no translations "
170 self.warn("could not find msgfmt executable, no translations "
171 "will be built")
171 "will be built")
172 return
172 return
173
173
174 podir = 'i18n'
174 podir = 'i18n'
175 if not os.path.isdir(podir):
175 if not os.path.isdir(podir):
176 self.warn("could not find %s/ directory" % podir)
176 self.warn("could not find %s/ directory" % podir)
177 return
177 return
178
178
179 join = os.path.join
179 join = os.path.join
180 for po in os.listdir(podir):
180 for po in os.listdir(podir):
181 if not po.endswith('.po'):
181 if not po.endswith('.po'):
182 continue
182 continue
183 pofile = join(podir, po)
183 pofile = join(podir, po)
184 modir = join('locale', po[:-3], 'LC_MESSAGES')
184 modir = join('locale', po[:-3], 'LC_MESSAGES')
185 mofile = join(modir, 'hg.mo')
185 mofile = join(modir, 'hg.mo')
186 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
186 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
187 if sys.platform != 'sunos5':
187 if sys.platform != 'sunos5':
188 # msgfmt on Solaris does not know about -c
188 # msgfmt on Solaris does not know about -c
189 cmd.append('-c')
189 cmd.append('-c')
190 self.mkpath(modir)
190 self.mkpath(modir)
191 self.make_file([pofile], mofile, spawn, (cmd,))
191 self.make_file([pofile], mofile, spawn, (cmd,))
192 self.distribution.data_files.append((join('mercurial', modir),
192 self.distribution.data_files.append((join('mercurial', modir),
193 [mofile]))
193 [mofile]))
194
194
195 build.sub_commands.append(('build_mo', None))
195 build.sub_commands.append(('build_mo', None))
196
196
197 Distribution.pure = 0
197 Distribution.pure = 0
198 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
198 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
199 "code instead of C extensions"))
199 "code instead of C extensions"))
200
200
201 class hg_build_py(build_py):
201 class hg_build_py(build_py):
202
202
203 def finalize_options(self):
203 def finalize_options(self):
204 build_py.finalize_options(self)
204 build_py.finalize_options(self)
205
205
206 if self.distribution.pure:
206 if self.distribution.pure:
207 if self.py_modules is None:
207 if self.py_modules is None:
208 self.py_modules = []
208 self.py_modules = []
209 for ext in self.distribution.ext_modules:
209 for ext in self.distribution.ext_modules:
210 if ext.name.startswith("mercurial."):
210 if ext.name.startswith("mercurial."):
211 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
211 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
212 self.distribution.ext_modules = []
212 self.distribution.ext_modules = []
213
213
214 def find_modules(self):
214 def find_modules(self):
215 modules = build_py.find_modules(self)
215 modules = build_py.find_modules(self)
216 for module in modules:
216 for module in modules:
217 if module[0] == "mercurial.pure":
217 if module[0] == "mercurial.pure":
218 if module[1] != "__init__":
218 if module[1] != "__init__":
219 yield ("mercurial", module[1], module[2])
219 yield ("mercurial", module[1], module[2])
220 else:
220 else:
221 yield module
221 yield module
222
222
223 cmdclass = {'install_data': install_package_data,
223 cmdclass = {'install_data': install_package_data,
224 'build_mo': build_mo,
224 'build_mo': build_mo,
225 'build_py': hg_build_py}
225 'build_py': hg_build_py}
226
226
227 ext_modules=[
227 ext_modules=[
228 Extension('mercurial.base85', ['mercurial/base85.c']),
228 Extension('mercurial.base85', ['mercurial/base85.c']),
229 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
229 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
230 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
230 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
231 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
231 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
232 Extension('mercurial.parsers', ['mercurial/parsers.c']),
232 Extension('mercurial.parsers', ['mercurial/parsers.c']),
233 Extension('mercurial.osutil', ['mercurial/osutil.c']),
233 Extension('mercurial.osutil', ['mercurial/osutil.c']),
234 ]
234 ]
235
235
236 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
236 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
237 'hgext.highlight', 'hgext.zeroconf', ]
237 'hgext.highlight', 'hgext.zeroconf', ]
238
238
239 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
239 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
240 # The inotify extension is only usable with Linux 2.6 kernels.
240 # The inotify extension is only usable with Linux 2.6 kernels.
241 # You also need a reasonably recent C library.
241 # You also need a reasonably recent C library.
242 cc = new_compiler()
242 cc = new_compiler()
243 if has_function(cc, 'inotify_add_watch'):
243 if has_function(cc, 'inotify_add_watch'):
244 ext_modules.append(Extension('hgext.inotify.linux._inotify',
244 ext_modules.append(Extension('hgext.inotify.linux._inotify',
245 ['hgext/inotify/linux/_inotify.c']))
245 ['hgext/inotify/linux/_inotify.c']))
246 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
246 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
247
247
248 datafiles = []
248 datafiles = []
249 for root in ('templates', 'i18n'):
249 for root in ('templates', 'i18n'):
250 for dir, dirs, files in os.walk(root):
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('.')]
251 datafiles.append((os.path.join('mercurial', dir),
253 datafiles.append((os.path.join('mercurial', dir),
252 [os.path.join(dir, file_) for file_ in files]))
254 [os.path.join(dir, file_) for file_ in files]))
253
255
254 setup(name='mercurial',
256 setup(name='mercurial',
255 version=version,
257 version=version,
256 author='Matt Mackall',
258 author='Matt Mackall',
257 author_email='mpm@selenic.com',
259 author_email='mpm@selenic.com',
258 url='http://mercurial.selenic.com/',
260 url='http://mercurial.selenic.com/',
259 description='Scalable distributed SCM',
261 description='Scalable distributed SCM',
260 license='GNU GPL',
262 license='GNU GPL',
261 scripts=scripts,
263 scripts=scripts,
262 packages=packages,
264 packages=packages,
263 ext_modules=ext_modules,
265 ext_modules=ext_modules,
264 data_files=datafiles,
266 data_files=datafiles,
265 cmdclass=cmdclass,
267 cmdclass=cmdclass,
266 options=dict(py2exe=dict(packages=['hgext', 'email']),
268 options=dict(py2exe=dict(packages=['hgext', 'email']),
267 bdist_mpkg=dict(zipdist=True,
269 bdist_mpkg=dict(zipdist=True,
268 license='COPYING',
270 license='COPYING',
269 readme='contrib/macosx/Readme.html',
271 readme='contrib/macosx/Readme.html',
270 welcome='contrib/macosx/Welcome.html')),
272 welcome='contrib/macosx/Welcome.html')),
271 **extra)
273 **extra)
General Comments 0
You need to be logged in to leave comments. Login now