3
# This is an installation script for bzr. Run it with
4
# './setup.py install', or
5
# './setup.py --help' for more options
7
# Reinvocation stolen from bzr, we need python2.4 by virtue of bzr_man
8
# including bzrlib.help
1
#! /usr/bin/env python3
3
"""Installation script for brz.
5
'./setup.py install', or
6
'./setup.py --help' for more options
15
if sys.version_info < (3, 5):
16
sys.stderr.write("[ERROR] Not a supported Python version. Need 3.5+\n")
13
version_info = sys.version_info
14
except AttributeError:
15
version_info = 1, 5 # 1.5 or older
17
REINVOKE = "__BZR_REINVOKE"
19
KNOWN_PYTHONS = ('python2.4',)
21
if version_info < NEED_VERS:
22
if not os.environ.has_key(REINVOKE):
23
# mutating os.environ doesn't work in old Pythons
24
os.putenv(REINVOKE, "1")
25
for python in KNOWN_PYTHONS:
27
os.execvp(python, [python] + sys.argv)
30
print >>sys.stderr, "bzr: error: cannot find a suitable python interpreter"
31
print >>sys.stderr, " (need %d.%d or later)" % NEED_VERS
23
sys.stderr.write("[ERROR] Please install setuptools\n")
33
if hasattr(os, "unsetenv"):
37
from distutils.core import setup
27
# NOTE: The directory containing setup.py, whether run by 'python setup.py' or
28
# './setup.py' or the equivalent with another path, should always be at the
29
# start of the path, so this should find the right one...
32
def get_long_description():
33
dirname = os.path.dirname(__file__)
34
readme = os.path.join(dirname, 'README.rst')
35
with open(readme, 'r') as f:
40
# META INFORMATION FOR SETUP
41
# see http://docs.python.org/dist/meta-data.html
44
'version': breezy.__version__,
45
'maintainer': 'Breezy Developers',
46
'maintainer_email': 'team@breezy-vcs.org',
47
'url': 'https://www.breezy-vcs.org/',
48
'description': 'Friendly distributed version control system',
49
'license': 'GNU GPL v2',
50
'download_url': 'https://launchpad.net/brz/+download',
51
'long_description': get_long_description(),
53
'Development Status :: 6 - Mature',
54
'Environment :: Console',
55
'Intended Audience :: Developers',
56
'Intended Audience :: System Administrators',
57
'License :: OSI Approved :: GNU General Public License (GPL)',
58
'Operating System :: Microsoft :: Windows',
59
'Operating System :: OS Independent',
60
'Operating System :: POSIX',
61
'Programming Language :: Python',
62
'Programming Language :: C',
63
'Topic :: Software Development :: Version Control',
68
# Technically, Breezy works without these two dependencies too. But there's
69
# no way to enable them by default and let users opt out.
76
'launchpad': ['launchpadlib>=1.6.3'],
83
# The list of packages is automatically generated later. Add other things
84
# that are part of BREEZY here.
88
# install files from selftest suite
89
'package_data': {'breezy': ['doc/api/*.txt',
90
'tests/test_patches_data/*',
91
'help_topics/en/*.txt',
92
'tests/ssl_certs/ca.crt',
93
'tests/ssl_certs/server_without_pass.key',
94
'tests/ssl_certs/server_with_pass.key',
95
'tests/ssl_certs/server.crt',
99
for filepath in glob.glob("breezy/locale/*/LC_MESSAGES/*.mo"):
100
langfile = filepath[len("breezy/locale/"):]
101
targetpath = os.path.dirname(os.path.join("share/locale", langfile))
102
I18N_FILES.append((targetpath, [filepath]))
104
def get_breezy_packages():
105
"""Recurse through the breezy directory, and extract the package names"""
108
base_path = os.path.dirname(os.path.abspath(breezy.__file__))
109
for root, dirs, files in os.walk(base_path):
110
if '__init__.py' in files:
111
assert root.startswith(base_path)
112
# Get just the path below breezy
113
package_path = root[len(base_path):]
114
# Remove leading and trailing slashes
115
package_path = package_path.strip('\\/')
117
package_name = 'breezy'
121
package_path.replace('/', '.').replace('\\', '.'))
122
packages.append(package_name)
123
return sorted(packages)
126
BREEZY['packages'] = get_breezy_packages()
129
from setuptools import setup
130
from distutils.version import LooseVersion
38
131
from distutils.command.install_scripts import install_scripts
132
from distutils.command.install_data import install_data
39
133
from distutils.command.build import build
41
135
###############################
45
139
class my_install_scripts(install_scripts):
46
140
""" Customized install_scripts distutils action.
47
Create bzr.bat for win32.
141
Create brz.bat for win32.
53
144
install_scripts.run(self) # standard action
55
146
if sys.platform == "win32":
57
scripts_dir = self.install_dir
58
script_path = os.path.join(scripts_dir, "bzr")
59
batch_str = "@%s %s %%*\n" % (sys.executable, script_path)
60
batch_path = script_path + ".bat"
61
f = file(batch_path, "w")
64
print "Created:", batch_path
66
print "ERROR: Unable to create %s: %s" % (batch_path, e)
148
scripts_dir = os.path.join(sys.prefix, 'Scripts')
149
script_path = self._quoted_path(os.path.join(scripts_dir,
151
python_exe = self._quoted_path(sys.executable)
152
batch_str = "@%s %s %%*" % (python_exe, script_path)
153
batch_path = os.path.join(self.install_dir, "brz.bat")
154
with open(batch_path, "w") as f:
156
print(("Created: %s" % batch_path))
158
e = sys.exc_info()[1]
159
print(("ERROR: Unable to create %s: %s" % (batch_path, e)))
161
def _quoted_path(self, path):
163
return '"' + path + '"'
166
#/class my_install_scripts
69
169
class bzr_build(build):
70
170
"""Customized build distutils action.
174
sub_commands = build.sub_commands + [
175
('build_mo', lambda _: True),
77
generate_docs.main(argv=["bzr", "man"])
181
from tools import generate_docs
182
generate_docs.main(argv=["brz", "man"])
79
185
########################
81
187
########################
86
author_email='mbp@sourcefrog.net',
87
url='http://www.bazaar-ng.org/',
88
description='Friendly distributed version control system',
96
'bzrlib.store.revision',
97
'bzrlib.store.versioned',
99
'bzrlib.tests.blackbox',
100
'bzrlib.tests.branch_implementations',
101
'bzrlib.tests.bzrdir_implementations',
102
'bzrlib.tests.interrepository_implementations',
103
'bzrlib.tests.interversionedfile_implementations',
104
'bzrlib.tests.repository_implementations',
105
'bzrlib.tests.revisionstore_implementations',
106
'bzrlib.tests.workingtree_implementations',
108
'bzrlib.transport.http',
111
'bzrlib.util.elementtree',
112
'bzrlib.util.effbot.org',
113
'bzrlib.util.configobj',
116
cmdclass={'install_scripts': my_install_scripts, 'build': bzr_build},
117
data_files=[('man/man1', ['bzr.1'])],
118
# todo: install the txt files from bzrlib.doc.api.
189
from breezy.bzr_distutils import build_mo
191
command_classes = {'install_scripts': my_install_scripts,
193
'build_mo': build_mo,
195
from distutils import log
196
from distutils.errors import CCompilerError, DistutilsPlatformError
197
from distutils.extension import Extension
200
from Cython.Distutils import build_ext
201
from Cython.Compiler.Version import version as cython_version
204
# try to build the extension from the prior generated source.
206
print("The python package 'Cython' is not available."
207
" If the .c files are available,")
208
print("they will be built,"
209
" but modifying the .pyx files will not rebuild them.")
211
from distutils.command.build_ext import build_ext
213
minimum_cython_version = '0.29'
214
cython_version_info = LooseVersion(cython_version)
215
if cython_version_info < LooseVersion(minimum_cython_version):
216
print("Version of Cython is too old. "
217
"Current is %s, need at least %s."
218
% (cython_version, minimum_cython_version))
219
print("If the .c files are available, they will be built,"
220
" but modifying the .pyx files will not rebuild them.")
226
class build_ext_if_possible(build_ext):
228
user_options = build_ext.user_options + [
229
('allow-python-fallback', None,
230
"When an extension cannot be built, allow falling"
231
" back to the pure-python implementation.")
234
def initialize_options(self):
235
build_ext.initialize_options(self)
236
self.allow_python_fallback = False
241
except DistutilsPlatformError:
242
e = sys.exc_info()[1]
243
if not self.allow_python_fallback:
244
log.warn('\n Cannot build extensions.\n'
245
' Use "build_ext --allow-python-fallback" to use'
246
' slower python implementations instead.\n')
249
log.warn('\n Extensions cannot be built.\n'
250
' Using the slower Python implementations instead.\n')
252
def build_extension(self, ext):
254
build_ext.build_extension(self, ext)
255
except CCompilerError:
256
if not self.allow_python_fallback:
257
log.warn('\n Cannot build extension "%s".\n'
258
' Use "build_ext --allow-python-fallback" to use'
259
' slower python implementations instead.\n'
262
log.warn('\n Building of "%s" extension failed.\n'
263
' Using the slower Python implementation instead.'
267
# Override the build_ext if we have Cython available
268
command_classes['build_ext'] = build_ext_if_possible
269
unavailable_files = []
272
def add_cython_extension(module_name, libraries=None, extra_source=[]):
273
"""Add a cython module to build.
275
This will use Cython to auto-generate the .c file if it is available.
276
Otherwise it will fall back on the .c file. If the .c file is not
277
available, it will warn, and not add anything.
279
You can pass any extra options to Extension through kwargs. One example is
282
:param module_name: The python path to the module. This will be used to
283
determine the .pyx and .c files to use.
285
path = module_name.replace('.', '/')
286
cython_name = path + '.pyx'
289
if sys.platform == 'win32':
290
# cython uses the macro WIN32 to detect the platform, even though it
291
# should be using something like _WIN32 or MS_WINDOWS, oh well, we can
292
# give it the right value.
293
define_macros.append(('WIN32', None))
295
source = [cython_name]
297
if not os.path.isfile(c_name):
298
unavailable_files.append(c_name)
302
source.extend(extra_source)
303
include_dirs = ['breezy']
306
module_name, source, define_macros=define_macros,
307
libraries=libraries, include_dirs=include_dirs))
310
add_cython_extension('breezy._simple_set_pyx')
311
ext_modules.append(Extension('breezy._static_tuple_c',
312
['breezy/_static_tuple_c.c']))
313
add_cython_extension('breezy._annotator_pyx')
314
add_cython_extension('breezy._bencode_pyx')
315
add_cython_extension('breezy._chunks_to_lines_pyx')
316
add_cython_extension('breezy.bzr._groupcompress_pyx',
317
extra_source=['breezy/bzr/diff-delta.c'])
318
add_cython_extension('breezy.bzr._knit_load_data_pyx')
319
add_cython_extension('breezy._known_graph_pyx')
320
add_cython_extension('breezy._rio_pyx')
321
if sys.platform == 'win32':
322
add_cython_extension('breezy.bzr._dirstate_helpers_pyx',
323
libraries=['Ws2_32'])
324
add_cython_extension('breezy._walkdirs_win32')
326
add_cython_extension('breezy.bzr._dirstate_helpers_pyx')
327
add_cython_extension('breezy._readdir_pyx')
328
add_cython_extension('breezy.bzr._chk_map_pyx')
329
add_cython_extension('breezy.bzr._btree_serializer_pyx')
332
if unavailable_files:
333
print('C extension(s) not found:')
334
print((' %s' % ('\n '.join(unavailable_files),)))
335
print('The python versions will be used instead.')
339
def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
340
gui_targets, data_files):
341
packages.append('tbzrcommands')
343
# ModuleFinder can't handle runtime changes to __path__, but
344
# win32com uses them. Hook this in so win32com.shell is found.
347
import cPickle as pickle
348
for p in win32com.__path__[1:]:
349
modulefinder.AddPackagePath("win32com", p)
350
for extra in ["win32com.shell"]:
352
m = sys.modules[extra]
353
for p in m.__path__[1:]:
354
modulefinder.AddPackagePath(extra, p)
356
# TBZR points to the TBZR directory
357
tbzr_root = os.environ["TBZR"]
359
# Ensure tbreezy itself is on sys.path
360
sys.path.append(tbzr_root)
362
packages.append("tbreezy")
364
# collect up our icons.
366
ico_root = os.path.join(tbzr_root, 'tbreezy', 'resources')
367
icos = [] # list of (path_root, relative_ico_path)
368
# First always brz's icon and its in the root of the brz tree.
369
icos.append(('', 'brz.ico'))
370
for root, dirs, files in os.walk(ico_root):
371
icos.extend([(ico_root, os.path.join(root, f)[len(ico_root) + 1:])
372
for f in files if f.endswith('.ico')])
373
# allocate an icon ID for each file and the full path to the ico
374
icon_resources = [(rid, os.path.join(ico_dir, ico_name))
375
for rid, (ico_dir, ico_name) in enumerate(icos)]
376
# create a string resource with the mapping. Might as well save the
377
# runtime some effort and write a pickle.
378
# Runtime expects unicode objects with forward-slash seps.
379
fse = sys.getfilesystemencoding()
380
map_items = [(f.replace('\\', '/').decode(fse), rid)
381
for rid, (_, f) in enumerate(icos)]
382
ico_map = dict(map_items)
383
# Create a new resource type of 'ICON_MAP', and use ID=1
384
other_resources = [("ICON_MAP", 1, pickle.dumps(ico_map))]
386
excludes.extend("""pywin pywin.dialogs pywin.dialogs.list
387
win32ui crawler.Crawler""".split())
389
# tbzrcache executables - a "console" version for debugging and a
390
# GUI version that is generally used.
392
script=os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
393
icon_resources=icon_resources,
394
other_resources=other_resources,
396
console_targets.append(tbzrcache)
398
# Make a windows version which is the same except for the base name.
399
tbzrcachew = tbzrcache.copy()
400
tbzrcachew["dest_base"] = "tbzrcachew"
401
gui_targets.append(tbzrcachew)
403
# ditto for the tbzrcommand tool
405
script=os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
406
icon_resources=icon_resources,
407
other_resources=other_resources,
409
console_targets.append(tbzrcommand)
410
tbzrcommandw = tbzrcommand.copy()
411
tbzrcommandw["dest_base"] = "tbzrcommandw"
412
gui_targets.append(tbzrcommandw)
414
# A utility to see python output from both C++ and Python based shell
416
tracer = dict(script=os.path.join(tbzr_root, "scripts", "tbzrtrace.py"))
417
console_targets.append(tracer)
419
# The C++ implemented shell extensions.
420
dist_dir = os.path.join(tbzr_root, "shellext", "build")
421
data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x86.dll')]))
422
data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x64.dll')]))
425
def get_qbzr_py2exe_info(includes, excludes, packages, data_files):
426
# PyQt4 itself still escapes the plugin detection code for some reason...
427
includes.append('PyQt4.QtCore')
428
includes.append('PyQt4.QtGui')
429
includes.append('PyQt4.QtTest')
430
includes.append('sip') # extension module required for Qt.
431
packages.append('pygments') # colorizer for qbzr
432
packages.append('docutils') # html formatting
433
includes.append('win32event') # for qsubprocess stuff
434
# the qt binaries might not be on PATH...
435
# They seem to install to a place like C:\Python25\PyQt4\*
436
# Which is not the same as C:\Python25\Lib\site-packages\PyQt4
437
pyqt_dir = os.path.join(sys.prefix, "PyQt4")
438
pyqt_bin_dir = os.path.join(pyqt_dir, "bin")
439
if os.path.isdir(pyqt_bin_dir):
440
path = os.environ.get("PATH", "")
441
if pyqt_bin_dir.lower() not in [p.lower() for p in path.split(os.pathsep)]:
442
os.environ["PATH"] = path + os.pathsep + pyqt_bin_dir
443
# also add all imageformat plugins to distribution
444
# We will look in 2 places, dirname(PyQt4.__file__) and pyqt_dir
445
base_dirs_to_check = []
446
if os.path.isdir(pyqt_dir):
447
base_dirs_to_check.append(pyqt_dir)
453
pyqt4_base_dir = os.path.dirname(PyQt4.__file__)
454
if pyqt4_base_dir != pyqt_dir:
455
base_dirs_to_check.append(pyqt4_base_dir)
456
if not base_dirs_to_check:
457
log.warn("Can't find PyQt4 installation -> not including imageformat"
461
for base_dir in base_dirs_to_check:
462
plug_dir = os.path.join(base_dir, 'plugins', 'imageformats')
463
if os.path.isdir(plug_dir):
464
for fname in os.listdir(plug_dir):
465
# Include plugin dlls, but not debugging dlls
466
fullpath = os.path.join(plug_dir, fname)
467
if fname.endswith('.dll') and not fname.endswith('d4.dll'):
468
files.append(fullpath)
470
data_files.append(('imageformats', files))
472
log.warn('PyQt4 was found, but we could not find any imageformat'
473
' plugins. Are you sure your configuration is correct?')
476
def get_svn_py2exe_info(includes, excludes, packages):
477
packages.append('subvertpy')
478
packages.append('sqlite3')
481
def get_git_py2exe_info(includes, excludes, packages):
482
packages.append('dulwich')
485
def get_fastimport_py2exe_info(includes, excludes, packages):
486
# This is the python-fastimport package, not to be confused with the
487
# brz-fastimport plugin.
488
packages.append('fastimport')
491
if 'bdist_wininst' in sys.argv:
494
for root, dirs, files in os.walk('doc'):
497
if (os.path.splitext(f)[1] in ('.html', '.css', '.png', '.pdf')
498
or f == 'quick-start-summary.svg'):
499
r.append(os.path.join(root, f))
503
target = os.path.join('Doc\\Breezy', relative)
505
target = 'Doc\\Breezy'
506
docs.append((target, r))
509
# python's distutils-based win32 installer
510
ARGS = {'scripts': ['brz', 'tools/win32/brz-win32-bdist-postinstall.py'],
511
'ext_modules': ext_modules,
513
'data_files': find_docs(),
514
# for building cython extensions
515
'cmdclass': command_classes,
518
ARGS.update(META_INFO)
520
PKG_DATA['package_data']['breezy'].append('locale/*/LC_MESSAGES/*.mo')
521
ARGS.update(PKG_DATA)
525
elif 'py2exe' in sys.argv:
529
# pick real brz version
533
for i in breezy.version_info[:4]:
538
version_number.append(str(i))
539
version_str = '.'.join(version_number)
541
# An override to install_data used only by py2exe builds, which arranges
542
# to byte-compile any .py files in data_files (eg, our plugins)
543
# Necessary as we can't rely on the user having the relevant permissions
544
# to the "Program Files" directory to generate them on the fly.
545
class install_data_with_bytecompile(install_data):
547
from distutils.util import byte_compile
549
install_data.run(self)
551
py2exe = self.distribution.get_command_obj('py2exe', False)
552
# GZ 2010-04-19: Setup has py2exe.optimize as 2, but give plugins
553
# time before living with docstring stripping
555
compile_names = [f for f in self.outfiles if f.endswith('.py')]
556
# Round mtime to nearest even second so that installing on a FAT
557
# filesystem bytecode internal and script timestamps will match
558
for f in compile_names:
559
mtime = os.stat(f).st_mtime
560
remainder = mtime % 2
563
os.utime(f, (mtime, mtime))
564
byte_compile(compile_names,
566
force=self.force, prefix=self.install_dir,
567
dry_run=self.dry_run)
568
self.outfiles.extend([f + 'o' for f in compile_names])
569
# end of class install_data_with_bytecompile
571
target = py2exe.build_exe.Target(
574
icon_resources=[(0, 'brz.ico')],
575
name=META_INFO['name'],
577
description=META_INFO['description'],
578
author=META_INFO['author'],
579
copyright="(c) Canonical Ltd, 2005-2010",
580
company_name="Canonical Ltd.",
581
comments=META_INFO['description'],
583
gui_target = copy.copy(target)
584
gui_target.dest_base = "bzrw"
586
packages = BREEZY['packages']
587
packages.remove('breezy')
588
packages = [i for i in packages if not i.startswith('breezy.plugins')]
590
for i in glob.glob('breezy\\*.py'):
591
module = i[:-3].replace('\\', '.')
592
if module.endswith('__init__'):
593
module = module[:-len('__init__')]
594
includes.append(module)
596
additional_packages = set()
598
# Although we currently can't enforce it, we consider it an error for
599
# py2exe to report any files are "missing". Such modules we know aren't
600
# used should be listed here.
601
excludes = """Tkinter psyco ElementPath r_hmac
602
ImaginaryModule cElementTree elementtree.ElementTree
603
Crypto.PublicKey._fastmath
605
resource validate""".split()
608
# email package from std python library use lazy import,
609
# so we need to explicitly add all package
610
additional_packages.add('email')
611
# And it uses funky mappings to conver to 'Oldname' to 'newname'. As
612
# a result, packages like 'email.Parser' show as missing. Tell py2exe
615
for oldname in getattr(email, '_LOWERNAMES', []):
616
excludes.append("email." + oldname)
617
for oldname in getattr(email, '_MIMENAMES', []):
618
excludes.append("email.MIME" + oldname)
620
# text files for help topis
621
text_topics = glob.glob('breezy/help_topics/en/*.txt')
622
topics_files = [('lib/help_topics/en', text_topics)]
626
# XXX - should we consider having the concept of an 'official' build,
627
# which hard-codes the list of plugins, gets more upset if modules are
629
plugins = None # will be a set after plugin sniffing...
630
for root, dirs, files in os.walk('breezy/plugins'):
631
if root == 'breezy/plugins':
633
# We ship plugins as normal files on the file-system - however,
634
# the build process can cause *some* of these plugin files to end
635
# up in library.zip. Thus, we saw (eg) "plugins/svn/test" in
636
# library.zip, and then saw import errors related to that as the
637
# rest of the svn plugin wasn't. So we tell py2exe to leave the
638
# plugins out of the .zip file
639
excludes.extend(["breezy.plugins." + d for d in dirs])
642
# Throw away files we don't want packaged. Note that plugins may
643
# have data files with all sorts of extensions so we need to
644
# be conservative here about what we ditch.
645
ext = os.path.splitext(i)[1]
646
if ext.endswith('~') or ext in [".pyc", ".swp"]:
648
if i == '__init__.py' and root == 'breezy/plugins':
650
x.append(os.path.join(root, i))
652
target_dir = root[len('breezy/'):] # install to 'plugins/...'
653
plugins_files.append((target_dir, x))
654
# find modules for built-in plugins
655
import tools.package_mf
656
mf = tools.package_mf.CustomModuleFinder()
657
mf.run_package('breezy/plugins')
658
packs, mods = mf.get_result()
659
additional_packages.update(packs)
660
includes.extend(mods)
662
console_targets = [target,
663
'tools/win32/bzr_postinstall.py',
665
gui_targets = [gui_target]
666
data_files = topics_files + plugins_files + I18N_FILES
668
if 'qbzr' in plugins:
669
get_qbzr_py2exe_info(includes, excludes, packages, data_files)
672
get_svn_py2exe_info(includes, excludes, packages)
675
get_git_py2exe_info(includes, excludes, packages)
677
if 'fastimport' in plugins:
678
get_fastimport_py2exe_info(includes, excludes, packages)
680
if "TBZR" in os.environ:
681
# TORTOISE_OVERLAYS_MSI_WIN32 must be set to the location of the
682
# TortoiseOverlays MSI installer file. It is in the TSVN svn repo and
683
# can be downloaded from (username=guest, blank password):
684
# http://tortoisesvn.tigris.org/svn/tortoisesvn/TortoiseOverlays
685
# look for: version-1.0.4/bin/TortoiseOverlays-1.0.4.11886-win32.msi
686
# Ditto for TORTOISE_OVERLAYS_MSI_X64, pointing at *-x64.msi.
687
for needed in ('TORTOISE_OVERLAYS_MSI_WIN32',
688
'TORTOISE_OVERLAYS_MSI_X64'):
689
url = ('http://guest:@tortoisesvn.tigris.org/svn/tortoisesvn'
691
if not os.path.isfile(os.environ.get(needed, '<nofile>')):
693
"\nPlease set %s to the location of the relevant"
694
"\nTortoiseOverlays .msi installer file."
695
" The installers can be found at"
697
"\ncheck in the version-X.Y.Z/bin/ subdir" % (needed, url))
698
get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
699
gui_targets, data_files)
701
# print this warning to stderr as output is redirected, so it is seen
702
# at build time. Also to stdout so it appears in the log
703
for f in (sys.stderr, sys.stdout):
704
f.write("Skipping TBZR binaries - "
705
"please set TBZR to a directory to enable\n")
707
# MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
709
dll_excludes.extend(["MSWSOCK.dll",
714
options_list = {"py2exe": {"packages": packages + list(additional_packages),
715
"includes": includes,
716
"excludes": excludes,
717
"dll_excludes": dll_excludes,
718
"dist_dir": "win32_bzr.exe",
720
"custom_boot_script":
721
"tools/win32/py2exe_boot_common.py",
725
# We want the libaray.zip to have optimize = 2, but the exe to have
726
# optimize = 1, so that .py files that get compilied at run time
727
# (e.g. user installed plugins) dont have their doc strings removed.
728
class py2exe_no_oo_exe(py2exe.build_exe.py2exe):
729
def build_executable(self, *args, **kwargs):
731
py2exe.build_exe.py2exe.build_executable(self, *args, **kwargs)
734
if __name__ == '__main__':
735
command_classes['install_data'] = install_data_with_bytecompile
736
command_classes['py2exe'] = py2exe_no_oo_exe
737
setup(options=options_list,
738
console=console_targets,
740
zipfile='lib/library.zip',
741
data_files=data_files,
742
cmdclass=command_classes,
746
# ad-hoc for easy_install
748
if 'bdist_egg' not in sys.argv:
749
# generate and install brz.1 only with plain install, not the
751
DATA_FILES = [('man/man1', ['brz.1', 'breezy/git/git-remote-bzr.1'])]
753
DATA_FILES = DATA_FILES + I18N_FILES
755
ARGS = {'scripts': ['brz',
756
# TODO(jelmer): Only install the git scripts if
758
'breezy/git/git-remote-bzr',
759
'breezy/git/bzr-receive-pack',
760
'breezy/git/bzr-upload-pack'],
761
'data_files': DATA_FILES,
762
'cmdclass': command_classes,
763
'ext_modules': ext_modules,
766
ARGS.update(META_INFO)
768
ARGS.update(PKG_DATA)
770
if __name__ == '__main__':