##// END OF EJS Templates
setup: set mode 644 or 755 on installed files
Kyle Lippincott -
r22640:e88a634e default
parent child Browse files
Show More
@@ -1,593 +1,628 b''
1 1 #
2 2 # This is the mercurial setup script.
3 3 #
4 4 # 'python setup.py install', or
5 5 # 'python setup.py --help' for more options
6 6
7 7 import sys, platform
8 8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10 10
11 11 if sys.version_info[0] >= 3:
12 12 def b(s):
13 13 '''A helper function to emulate 2.6+ bytes literals using string
14 14 literals.'''
15 15 return s.encode('latin1')
16 16 printf = eval('print')
17 17 libdir_escape = 'unicode_escape'
18 18 else:
19 19 libdir_escape = 'string_escape'
20 20 def b(s):
21 21 '''A helper function to emulate 2.6+ bytes literals using string
22 22 literals.'''
23 23 return s
24 24 def printf(*args, **kwargs):
25 25 f = kwargs.get('file', sys.stdout)
26 26 end = kwargs.get('end', '\n')
27 27 f.write(b(' ').join(args) + end)
28 28
29 29 # Solaris Python packaging brain damage
30 30 try:
31 31 import hashlib
32 32 sha = hashlib.sha1()
33 33 except ImportError:
34 34 try:
35 35 import sha
36 36 sha.sha # silence unused import warning
37 37 except ImportError:
38 38 raise SystemExit(
39 39 "Couldn't import standard hashlib (incomplete Python install).")
40 40
41 41 try:
42 42 import zlib
43 43 zlib.compressobj # silence unused import warning
44 44 except ImportError:
45 45 raise SystemExit(
46 46 "Couldn't import standard zlib (incomplete Python install).")
47 47
48 48 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
49 49 isironpython = False
50 50 try:
51 51 isironpython = (platform.python_implementation()
52 52 .lower().find("ironpython") != -1)
53 53 except AttributeError:
54 54 pass
55 55
56 56 if isironpython:
57 57 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
58 58 else:
59 59 try:
60 60 import bz2
61 61 bz2.BZ2Compressor # silence unused import warning
62 62 except ImportError:
63 63 raise SystemExit(
64 64 "Couldn't import standard bz2 (incomplete Python install).")
65 65
66 import os, subprocess, time
66 import os, stat, subprocess, time
67 67 import re
68 68 import shutil
69 69 import tempfile
70 70 from distutils import log
71 71 from distutils.core import setup, Command, Extension
72 72 from distutils.dist import Distribution
73 73 from distutils.command.build import build
74 74 from distutils.command.build_ext import build_ext
75 75 from distutils.command.build_py import build_py
76 from distutils.command.install_lib import install_lib
76 77 from distutils.command.install_scripts import install_scripts
77 78 from distutils.spawn import spawn, find_executable
78 from distutils import cygwinccompiler
79 from distutils import cygwinccompiler, file_util
79 80 from distutils.errors import CCompilerError, DistutilsExecError
80 81 from distutils.sysconfig import get_python_inc, get_config_var
81 82 from distutils.version import StrictVersion
82 83
83 84 convert2to3 = '--c2to3' in sys.argv
84 85 if convert2to3:
85 86 try:
86 87 from distutils.command.build_py import build_py_2to3 as build_py
87 88 from lib2to3.refactor import get_fixers_from_package as getfixers
88 89 except ImportError:
89 90 if sys.version_info[0] < 3:
90 91 raise SystemExit("--c2to3 is only compatible with python3.")
91 92 raise
92 93 sys.path.append('contrib')
93 94 elif sys.version_info[0] >= 3:
94 95 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
95 96
96 97 scripts = ['hg']
97 98 if os.name == 'nt':
98 99 scripts.append('contrib/win32/hg.bat')
99 100
100 101 # simplified version of distutils.ccompiler.CCompiler.has_function
101 102 # that actually removes its temporary files.
102 103 def hasfunction(cc, funcname):
103 104 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
104 105 devnull = oldstderr = None
105 106 try:
106 107 try:
107 108 fname = os.path.join(tmpdir, 'funcname.c')
108 109 f = open(fname, 'w')
109 110 f.write('int main(void) {\n')
110 111 f.write(' %s();\n' % funcname)
111 112 f.write('}\n')
112 113 f.close()
113 114 # Redirect stderr to /dev/null to hide any error messages
114 115 # from the compiler.
115 116 # This will have to be changed if we ever have to check
116 117 # for a function on Windows.
117 118 devnull = open('/dev/null', 'w')
118 119 oldstderr = os.dup(sys.stderr.fileno())
119 120 os.dup2(devnull.fileno(), sys.stderr.fileno())
120 121 objects = cc.compile([fname], output_dir=tmpdir)
121 122 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
122 123 except Exception:
123 124 return False
124 125 return True
125 126 finally:
126 127 if oldstderr is not None:
127 128 os.dup2(oldstderr, sys.stderr.fileno())
128 129 if devnull is not None:
129 130 devnull.close()
130 131 shutil.rmtree(tmpdir)
131 132
132 133 # py2exe needs to be installed to work
133 134 try:
134 135 import py2exe
135 136 py2exe.Distribution # silence unused import warning
136 137 py2exeloaded = True
137 138 # import py2exe's patched Distribution class
138 139 from distutils.core import Distribution
139 140 except ImportError:
140 141 py2exeloaded = False
141 142
142 143 def runcmd(cmd, env):
143 144 if sys.platform == 'plan9':
144 145 # subprocess kludge to work around issues in half-baked Python
145 146 # ports, notably bichued/python:
146 147 _, out, err = os.popen3(cmd)
147 148 return str(out), str(err)
148 149 else:
149 150 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
150 151 stderr=subprocess.PIPE, env=env)
151 152 out, err = p.communicate()
152 153 return out, err
153 154
154 155 def runhg(cmd, env):
155 156 out, err = runcmd(cmd, env)
156 157 # If root is executing setup.py, but the repository is owned by
157 158 # another user (as in "sudo python setup.py install") we will get
158 159 # trust warnings since the .hg/hgrc file is untrusted. That is
159 160 # fine, we don't want to load it anyway. Python may warn about
160 161 # a missing __init__.py in mercurial/locale, we also ignore that.
161 162 err = [e for e in err.splitlines()
162 163 if not e.startswith(b('not trusting file')) \
163 164 and not e.startswith(b('warning: Not importing')) \
164 165 and not e.startswith(b('obsolete feature not enabled'))]
165 166 if err:
166 167 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
167 168 printf(b('\n').join([b(' ') + e for e in err]), file=sys.stderr)
168 169 return ''
169 170 return out
170 171
171 172 version = ''
172 173
173 174 # Execute hg out of this directory with a custom environment which
174 175 # includes the pure Python modules in mercurial/pure. We also take
175 176 # care to not use any hgrc files and do no localization.
176 177 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
177 178 env = {'PYTHONPATH': os.pathsep.join(pypath),
178 179 'HGRCPATH': '',
179 180 'LANGUAGE': 'C'}
180 181 if 'LD_LIBRARY_PATH' in os.environ:
181 182 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
182 183 if 'SystemRoot' in os.environ:
183 184 # Copy SystemRoot into the custom environment for Python 2.6
184 185 # under Windows. Otherwise, the subprocess will fail with
185 186 # error 0xc0150004. See: http://bugs.python.org/issue3440
186 187 env['SystemRoot'] = os.environ['SystemRoot']
187 188
188 189 if os.path.isdir('.hg'):
189 190 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
190 191 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
191 192 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
192 193 if numerictags: # tag(s) found
193 194 version = numerictags[-1]
194 195 if hgid.endswith('+'): # propagate the dirty status to the tag
195 196 version += '+'
196 197 else: # no tag found
197 198 cmd = [sys.executable, 'hg', 'parents', '--template',
198 199 '{latesttag}+{latesttagdistance}-']
199 200 version = runhg(cmd, env) + hgid
200 201 if version.endswith('+'):
201 202 version += time.strftime('%Y%m%d')
202 203 elif os.path.exists('.hg_archival.txt'):
203 204 kw = dict([[t.strip() for t in l.split(':', 1)]
204 205 for l in open('.hg_archival.txt')])
205 206 if 'tag' in kw:
206 207 version = kw['tag']
207 208 elif 'latesttag' in kw:
208 209 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
209 210 else:
210 211 version = kw.get('node', '')[:12]
211 212
212 213 if version:
213 214 f = open("mercurial/__version__.py", "w")
214 215 f.write('# this file is autogenerated by setup.py\n')
215 216 f.write('version = "%s"\n' % version)
216 217 f.close()
217 218
218 219
219 220 try:
220 221 from mercurial import __version__
221 222 version = __version__.version
222 223 except ImportError:
223 224 version = 'unknown'
224 225
225 226 class hgbuild(build):
226 227 # Insert hgbuildmo first so that files in mercurial/locale/ are found
227 228 # when build_py is run next.
228 229 sub_commands = [('build_mo', None),
229 230
230 231 # We also need build_ext before build_py. Otherwise, when 2to3 is
231 232 # called (in build_py), it will not find osutil & friends,
232 233 # thinking that those modules are global and, consequently, making
233 234 # a mess, now that all module imports are global.
234 235
235 236 ('build_ext', build.has_ext_modules),
236 237 ] + build.sub_commands
237 238
238 239 class hgbuildmo(build):
239 240
240 241 description = "build translations (.mo files)"
241 242
242 243 def run(self):
243 244 if not find_executable('msgfmt'):
244 245 self.warn("could not find msgfmt executable, no translations "
245 246 "will be built")
246 247 return
247 248
248 249 podir = 'i18n'
249 250 if not os.path.isdir(podir):
250 251 self.warn("could not find %s/ directory" % podir)
251 252 return
252 253
253 254 join = os.path.join
254 255 for po in os.listdir(podir):
255 256 if not po.endswith('.po'):
256 257 continue
257 258 pofile = join(podir, po)
258 259 modir = join('locale', po[:-3], 'LC_MESSAGES')
259 260 mofile = join(modir, 'hg.mo')
260 261 mobuildfile = join('mercurial', mofile)
261 262 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
262 263 if sys.platform != 'sunos5':
263 264 # msgfmt on Solaris does not know about -c
264 265 cmd.append('-c')
265 266 self.mkpath(join('mercurial', modir))
266 267 self.make_file([pofile], mobuildfile, spawn, (cmd,))
267 268
268 269
269 270 class hgdist(Distribution):
270 271 pure = 0
271 272
272 273 global_options = Distribution.global_options + \
273 274 [('pure', None, "use pure (slow) Python "
274 275 "code instead of C extensions"),
275 276 ('c2to3', None, "(experimental!) convert "
276 277 "code with 2to3"),
277 278 ]
278 279
279 280 def has_ext_modules(self):
280 281 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
281 282 # too late for some cases
282 283 return not self.pure and Distribution.has_ext_modules(self)
283 284
284 285 class hgbuildext(build_ext):
285 286
286 287 def build_extension(self, ext):
287 288 try:
288 289 build_ext.build_extension(self, ext)
289 290 except CCompilerError:
290 291 if not getattr(ext, 'optional', False):
291 292 raise
292 293 log.warn("Failed to build optional extension '%s' (skipping)",
293 294 ext.name)
294 295
295 296 class hgbuildpy(build_py):
296 297 if convert2to3:
297 298 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
298 299 getfixers("hgfixes")))
299 300
300 301 def finalize_options(self):
301 302 build_py.finalize_options(self)
302 303
303 304 if self.distribution.pure:
304 305 if self.py_modules is None:
305 306 self.py_modules = []
306 307 for ext in self.distribution.ext_modules:
307 308 if ext.name.startswith("mercurial."):
308 309 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
309 310 self.distribution.ext_modules = []
310 311 else:
311 312 h = os.path.join(get_python_inc(), 'Python.h')
312 313 if not os.path.exists(h):
313 314 raise SystemExit('Python headers are required to build '
314 315 'Mercurial but weren\'t found in %s' % h)
315 316
316 317 def find_modules(self):
317 318 modules = build_py.find_modules(self)
318 319 for module in modules:
319 320 if module[0] == "mercurial.pure":
320 321 if module[1] != "__init__":
321 322 yield ("mercurial", module[1], module[2])
322 323 else:
323 324 yield module
324 325
325 326 class buildhgextindex(Command):
326 327 description = 'generate prebuilt index of hgext (for frozen package)'
327 328 user_options = []
328 329 _indexfilename = 'hgext/__index__.py'
329 330
330 331 def initialize_options(self):
331 332 pass
332 333
333 334 def finalize_options(self):
334 335 pass
335 336
336 337 def run(self):
337 338 if os.path.exists(self._indexfilename):
338 339 f = open(self._indexfilename, 'w')
339 340 f.write('# empty\n')
340 341 f.close()
341 342
342 343 # here no extension enabled, disabled() lists up everything
343 344 code = ('import pprint; from mercurial import extensions; '
344 345 'pprint.pprint(extensions.disabled())')
345 346 out, err = runcmd([sys.executable, '-c', code], env)
346 347 if err:
347 348 raise DistutilsExecError(err)
348 349
349 350 f = open(self._indexfilename, 'w')
350 351 f.write('# this file is autogenerated by setup.py\n')
351 352 f.write('docs = ')
352 353 f.write(out)
353 354 f.close()
354 355
355 356 class buildhgexe(build_ext):
356 357 description = 'compile hg.exe from mercurial/exewrapper.c'
357 358
358 359 def build_extensions(self):
359 360 if os.name != 'nt':
360 361 return
361 362 if isinstance(self.compiler, HackedMingw32CCompiler):
362 363 self.compiler.compiler_so = self.compiler.compiler # no -mdll
363 364 self.compiler.dll_libraries = [] # no -lmsrvc90
364 365 hv = sys.hexversion
365 366 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
366 367 f = open('mercurial/hgpythonlib.h', 'wb')
367 368 f.write('/* this file is autogenerated by setup.py */\n')
368 369 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
369 370 f.close()
370 371 objects = self.compiler.compile(['mercurial/exewrapper.c'],
371 372 output_dir=self.build_temp)
372 373 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
373 374 target = os.path.join(dir, 'hg')
374 375 self.compiler.link_executable(objects, target,
375 376 libraries=[],
376 377 output_dir=self.build_temp)
377 378
379 class hginstalllib(install_lib):
380 '''
381 This is a specialization of install_lib that replaces the copy_file used
382 there so that it supports setting the mode of files after copying them,
383 instead of just preserving the mode that the files originally had. If your
384 system has a umask of something like 027, preserving the permissions when
385 copying will lead to a broken install.
386
387 Note that just passing keep_permissions=False to copy_file would be
388 insufficient, as it might still be applying a umask.
389 '''
390
391 def run(self):
392 realcopyfile = file_util.copy_file
393 def copyfileandsetmode(*args, **kwargs):
394 src, dst = args[0], args[1]
395 dst, copied = realcopyfile(*args, **kwargs)
396 if copied:
397 st = os.stat(src)
398 # Persist executable bit (apply it to group and other if user
399 # has it)
400 if st[stat.ST_MODE] & stat.S_IXUSR:
401 setmode = 0755
402 else:
403 setmode = 0644
404 os.chmod(dst, (stat.S_IMODE(st[stat.ST_MODE]) & ~0777) |
405 setmode)
406 file_util.copy_file = copyfileandsetmode
407 try:
408 install_lib.run(self)
409 finally:
410 file_util.copy_file = realcopyfile
411
378 412 class hginstallscripts(install_scripts):
379 413 '''
380 414 This is a specialization of install_scripts that replaces the @LIBDIR@ with
381 415 the configured directory for modules. If possible, the path is made relative
382 416 to the directory for scripts.
383 417 '''
384 418
385 419 def initialize_options(self):
386 420 install_scripts.initialize_options(self)
387 421
388 422 self.install_lib = None
389 423
390 424 def finalize_options(self):
391 425 install_scripts.finalize_options(self)
392 426 self.set_undefined_options('install',
393 427 ('install_lib', 'install_lib'))
394 428
395 429 def run(self):
396 430 install_scripts.run(self)
397 431
398 432 if (os.path.splitdrive(self.install_dir)[0] !=
399 433 os.path.splitdrive(self.install_lib)[0]):
400 434 # can't make relative paths from one drive to another, so use an
401 435 # absolute path instead
402 436 libdir = self.install_lib
403 437 else:
404 438 common = os.path.commonprefix((self.install_dir, self.install_lib))
405 439 rest = self.install_dir[len(common):]
406 440 uplevel = len([n for n in os.path.split(rest) if n])
407 441
408 442 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
409 443
410 444 for outfile in self.outfiles:
411 445 fp = open(outfile, 'rb')
412 446 data = fp.read()
413 447 fp.close()
414 448
415 449 # skip binary files
416 450 if b('\0') in data:
417 451 continue
418 452
419 453 data = data.replace(b('@LIBDIR@'), libdir.encode(libdir_escape))
420 454 fp = open(outfile, 'wb')
421 455 fp.write(data)
422 456 fp.close()
423 457
424 458 cmdclass = {'build': hgbuild,
425 459 'build_mo': hgbuildmo,
426 460 'build_ext': hgbuildext,
427 461 'build_py': hgbuildpy,
428 462 'build_hgextindex': buildhgextindex,
463 'install_lib': hginstalllib,
429 464 'install_scripts': hginstallscripts,
430 465 'build_hgexe': buildhgexe,
431 466 }
432 467
433 468 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
434 469 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
435 470 'hgext.largefiles']
436 471
437 472 pymodules = []
438 473
439 474 common_depends = ['mercurial/util.h']
440 475
441 476 extmodules = [
442 477 Extension('mercurial.base85', ['mercurial/base85.c'],
443 478 depends=common_depends),
444 479 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
445 480 depends=common_depends),
446 481 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
447 482 depends=common_depends),
448 483 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
449 484 depends=common_depends),
450 485 Extension('mercurial.parsers', ['mercurial/dirs.c',
451 486 'mercurial/parsers.c',
452 487 'mercurial/pathencode.c'],
453 488 depends=common_depends),
454 489 ]
455 490
456 491 osutil_ldflags = []
457 492
458 493 if sys.platform == 'darwin':
459 494 osutil_ldflags += ['-framework', 'ApplicationServices']
460 495
461 496 # disable osutil.c under windows + python 2.4 (issue1364)
462 497 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
463 498 pymodules.append('mercurial.pure.osutil')
464 499 else:
465 500 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
466 501 extra_link_args=osutil_ldflags,
467 502 depends=common_depends))
468 503
469 504 # the -mno-cygwin option has been deprecated for years
470 505 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
471 506
472 507 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
473 508 def __init__(self, *args, **kwargs):
474 509 Mingw32CCompiler.__init__(self, *args, **kwargs)
475 510 for i in 'compiler compiler_so linker_exe linker_so'.split():
476 511 try:
477 512 getattr(self, i).remove('-mno-cygwin')
478 513 except ValueError:
479 514 pass
480 515
481 516 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
482 517
483 518 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
484 519 'help/*.txt',
485 520 'dummycert.pem']}
486 521
487 522 def ordinarypath(p):
488 523 return p and p[0] != '.' and p[-1] != '~'
489 524
490 525 for root in ('templates',):
491 526 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
492 527 curdir = curdir.split(os.sep, 1)[1]
493 528 dirs[:] = filter(ordinarypath, dirs)
494 529 for f in filter(ordinarypath, files):
495 530 f = os.path.join(curdir, f)
496 531 packagedata['mercurial'].append(f)
497 532
498 533 datafiles = []
499 534 setupversion = version
500 535 extra = {}
501 536
502 537 if py2exeloaded:
503 538 extra['console'] = [
504 539 {'script':'hg',
505 540 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
506 541 'product_version':version}]
507 542 # sub command of 'build' because 'py2exe' does not handle sub_commands
508 543 build.sub_commands.insert(0, ('build_hgextindex', None))
509 544
510 545 if os.name == 'nt':
511 546 # Windows binary file versions for exe/dll files must have the
512 547 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
513 548 setupversion = version.split('+', 1)[0]
514 549
515 550 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
516 551 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
517 552 if version:
518 553 version = version[0]
519 554 xcode4 = (version.startswith('Xcode') and
520 555 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
521 556 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
522 557 else:
523 558 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
524 559 # installed, but instead with only command-line tools. Assume
525 560 # that only happens on >= Lion, thus no PPC support.
526 561 xcode4 = True
527 562 xcode51 = False
528 563
529 564 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
530 565 # distutils.sysconfig
531 566 if xcode4:
532 567 os.environ['ARCHFLAGS'] = ''
533 568
534 569 # XCode 5.1 changes clang such that it now fails to compile if the
535 570 # -mno-fused-madd flag is passed, but the version of Python shipped with
536 571 # OS X 10.9 Mavericks includes this flag. This causes problems in all
537 572 # C extension modules, and a bug has been filed upstream at
538 573 # http://bugs.python.org/issue21244. We also need to patch this here
539 574 # so Mercurial can continue to compile in the meantime.
540 575 if xcode51:
541 576 cflags = get_config_var('CFLAGS')
542 577 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
543 578 os.environ['CFLAGS'] = (
544 579 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
545 580
546 581 setup(name='mercurial',
547 582 version=setupversion,
548 583 author='Matt Mackall and many others',
549 584 author_email='mercurial@selenic.com',
550 585 url='http://mercurial.selenic.com/',
551 586 download_url='http://mercurial.selenic.com/release/',
552 587 description=('Fast scalable distributed SCM (revision control, version '
553 588 'control) system'),
554 589 long_description=('Mercurial is a distributed SCM tool written in Python.'
555 590 ' It is used by a number of large projects that require'
556 591 ' fast, reliable distributed revision control, such as '
557 592 'Mozilla.'),
558 593 license='GNU GPLv2 or any later version',
559 594 classifiers=[
560 595 'Development Status :: 6 - Mature',
561 596 'Environment :: Console',
562 597 'Intended Audience :: Developers',
563 598 'Intended Audience :: System Administrators',
564 599 'License :: OSI Approved :: GNU General Public License (GPL)',
565 600 'Natural Language :: Danish',
566 601 'Natural Language :: English',
567 602 'Natural Language :: German',
568 603 'Natural Language :: Italian',
569 604 'Natural Language :: Japanese',
570 605 'Natural Language :: Portuguese (Brazilian)',
571 606 'Operating System :: Microsoft :: Windows',
572 607 'Operating System :: OS Independent',
573 608 'Operating System :: POSIX',
574 609 'Programming Language :: C',
575 610 'Programming Language :: Python',
576 611 'Topic :: Software Development :: Version Control',
577 612 ],
578 613 scripts=scripts,
579 614 packages=packages,
580 615 py_modules=pymodules,
581 616 ext_modules=extmodules,
582 617 data_files=datafiles,
583 618 package_data=packagedata,
584 619 cmdclass=cmdclass,
585 620 distclass=hgdist,
586 621 options={'py2exe': {'packages': ['hgext', 'email']},
587 622 'bdist_mpkg': {'zipdist': False,
588 623 'license': 'COPYING',
589 624 'readme': 'contrib/macosx/Readme.html',
590 625 'welcome': 'contrib/macosx/Welcome.html',
591 626 },
592 627 },
593 628 **extra)
General Comments 0
You need to be logged in to leave comments. Login now