/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: Jelmer Vernooij
  • Date: 2017-09-01 07:15:43 UTC
  • mfrom: (6770.3.2 py3_test_cleanup)
  • Revision ID: jelmer@jelmer.uk-20170901071543-1t83321xkog9qrxh
Merge lp:~gz/brz/py3_test_cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#! /usr/bin/env python
2
2
 
3
 
# This is an installation script for bzr.  Run it with
4
 
# './setup.py install', or
5
 
# './setup.py --help' for more options
6
 
 
7
 
# Reinvocation stolen from bzr, we need python2.4 by virtue of bzr_man
8
 
# including bzrlib.help
9
 
 
10
 
import os, sys
11
 
 
12
 
try:
13
 
    version_info = sys.version_info
14
 
except AttributeError:
15
 
    version_info = 1, 5 # 1.5 or older
16
 
 
17
 
REINVOKE = "__BZR_REINVOKE"
18
 
NEED_VERS = (2, 4)
19
 
KNOWN_PYTHONS = ('python2.4',)
20
 
 
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:
26
 
            try:
27
 
                os.execvp(python, [python] + sys.argv)
28
 
            except OSError:
29
 
                pass
30
 
    print >>sys.stderr, "bzr: error: cannot find a suitable python interpreter"
31
 
    print >>sys.stderr, "  (need %d.%d or later)" % NEED_VERS
 
3
"""Installation script for brz.
 
4
Run it with
 
5
 './setup.py install', or
 
6
 './setup.py --help' for more options
 
7
"""
 
8
 
 
9
import os
 
10
import os.path
 
11
import sys
 
12
import copy
 
13
import glob
 
14
 
 
15
if sys.version_info < (2, 7):
 
16
    sys.stderr.write("[ERROR] Not a supported Python version. Need 2.7+\n")
32
17
    sys.exit(1)
33
 
if hasattr(os, "unsetenv"):
34
 
    os.unsetenv(REINVOKE)
35
 
 
36
 
 
 
18
 
 
19
# NOTE: The directory containing setup.py, whether run by 'python setup.py' or
 
20
# './setup.py' or the equivalent with another path, should always be at the
 
21
# start of the path, so this should find the right one...
 
22
import breezy
 
23
 
 
24
def get_long_description():
 
25
    dirname = os.path.dirname(__file__)
 
26
    readme = os.path.join(dirname, 'README')
 
27
    f = open(readme, 'rb')
 
28
    try:
 
29
        return f.read()
 
30
    finally:
 
31
        f.close()
 
32
 
 
33
 
 
34
##
 
35
# META INFORMATION FOR SETUP
 
36
# see http://docs.python.org/dist/meta-data.html
 
37
META_INFO = {
 
38
    'name':         'brz',
 
39
    'version':      breezy.__version__,
 
40
    'author':       'Canonical Ltd',
 
41
    'author_email': 'bazaar@lists.canonical.com',
 
42
    'maintainer':   'Breezy Developers',
 
43
    'url':          'https://www.breezy-vcs.org/',
 
44
    'description':  'Friendly distributed version control system',
 
45
    'license':      'GNU GPL v2',
 
46
    'download_url': 'https://launchpad.net/brz/+download',
 
47
    'long_description': get_long_description(),
 
48
    'classifiers': [
 
49
        'Development Status :: 6 - Mature',
 
50
        'Environment :: Console',
 
51
        'Intended Audience :: Developers',
 
52
        'Intended Audience :: System Administrators',
 
53
        'License :: OSI Approved :: GNU General Public License (GPL)',
 
54
        'Operating System :: Microsoft :: Windows',
 
55
        'Operating System :: OS Independent',
 
56
        'Operating System :: POSIX',
 
57
        'Programming Language :: Python',
 
58
        'Programming Language :: C',
 
59
        'Topic :: Software Development :: Version Control',
 
60
        ],
 
61
    }
 
62
 
 
63
# The list of packages is automatically generated later. Add other things
 
64
# that are part of BZRLIB here.
 
65
BZRLIB = {}
 
66
 
 
67
PKG_DATA = {# install files from selftest suite
 
68
            'package_data': {'breezy': ['doc/api/*.txt',
 
69
                                        'tests/test_patches_data/*',
 
70
                                        'help_topics/en/*.txt',
 
71
                                        'tests/ssl_certs/ca.crt',
 
72
                                        'tests/ssl_certs/server_without_pass.key',
 
73
                                        'tests/ssl_certs/server_with_pass.key',
 
74
                                        'tests/ssl_certs/server.crt',
 
75
                                       ]},
 
76
           }
 
77
I18N_FILES = []
 
78
for filepath in glob.glob("breezy/locale/*/LC_MESSAGES/*.mo"):
 
79
    langfile = filepath[len("breezy/locale/"):]
 
80
    targetpath = os.path.dirname(os.path.join("share/locale", langfile))
 
81
    I18N_FILES.append((targetpath, [filepath]))
 
82
 
 
83
def get_breezy_packages():
 
84
    """Recurse through the breezy directory, and extract the package names"""
 
85
 
 
86
    packages = []
 
87
    base_path = os.path.dirname(os.path.abspath(breezy.__file__))
 
88
    for root, dirs, files in os.walk(base_path):
 
89
        if '__init__.py' in files:
 
90
            assert root.startswith(base_path)
 
91
            # Get just the path below breezy
 
92
            package_path = root[len(base_path):]
 
93
            # Remove leading and trailing slashes
 
94
            package_path = package_path.strip('\\/')
 
95
            if not package_path:
 
96
                package_name = 'breezy'
 
97
            else:
 
98
                package_name = ('breezy.' +
 
99
                            package_path.replace('/', '.').replace('\\', '.'))
 
100
            packages.append(package_name)
 
101
    return sorted(packages)
 
102
 
 
103
 
 
104
BZRLIB['packages'] = get_breezy_packages()
 
105
 
 
106
 
 
107
from distutils import log
37
108
from distutils.core import setup
 
109
from distutils.version import LooseVersion
38
110
from distutils.command.install_scripts import install_scripts
 
111
from distutils.command.install_data import install_data
39
112
from distutils.command.build import build
40
113
 
41
114
###############################
44
117
 
45
118
class my_install_scripts(install_scripts):
46
119
    """ Customized install_scripts distutils action.
47
 
    Create bzr.bat for win32.
 
120
    Create brz.bat for win32.
48
121
    """
49
122
    def run(self):
50
 
        import os
51
 
        import sys
52
 
 
53
123
        install_scripts.run(self)   # standard action
54
124
 
55
125
        if sys.platform == "win32":
56
126
            try:
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"
 
127
                scripts_dir = os.path.join(sys.prefix, 'Scripts')
 
128
                script_path = self._quoted_path(os.path.join(scripts_dir,
 
129
                                                             "brz"))
 
130
                python_exe = self._quoted_path(sys.executable)
 
131
                args = self._win_batch_args()
 
132
                batch_str = "@%s %s %s" % (python_exe, script_path, args)
 
133
                batch_path = os.path.join(self.install_dir, "brz.bat")
61
134
                f = file(batch_path, "w")
62
135
                f.write(batch_str)
63
136
                f.close()
64
 
                print "Created:", batch_path
65
 
            except Exception, e:
66
 
                print "ERROR: Unable to create %s: %s" % (batch_path, e)
 
137
                print(("Created: %s" % batch_path))
 
138
            except Exception:
 
139
                e = sys.exc_info()[1]
 
140
                print(("ERROR: Unable to create %s: %s" % (batch_path, e)))
 
141
 
 
142
    def _quoted_path(self, path):
 
143
        if ' ' in path:
 
144
            return '"' + path + '"'
 
145
        else:
 
146
            return path
 
147
 
 
148
    def _win_batch_args(self):
 
149
        from breezy.win32utils import winver
 
150
        if winver == 'Windows NT':
 
151
            return '%*'
 
152
        else:
 
153
            return '%1 %2 %3 %4 %5 %6 %7 %8 %9'
 
154
#/class my_install_scripts
67
155
 
68
156
 
69
157
class bzr_build(build):
70
158
    """Customized build distutils action.
71
 
    Generate bzr.1.
 
159
    Generate brz.1.
72
160
    """
 
161
 
 
162
    sub_commands = build.sub_commands + [
 
163
            ('build_mo', lambda _: True),
 
164
            ]
 
165
 
73
166
    def run(self):
74
167
        build.run(self)
75
168
 
76
 
        import generate_docs
77
 
        generate_docs.main(argv=["bzr", "man"])
 
169
        from tools import generate_docs
 
170
        generate_docs.main(argv=["brz", "man"])
 
171
 
78
172
 
79
173
########################
80
174
## Setup
81
175
########################
82
176
 
83
 
setup(name='bzr',
84
 
      version='0.8pre',
85
 
      author='Martin Pool',
86
 
      author_email='mbp@sourcefrog.net',
87
 
      url='http://www.bazaar-ng.org/',
88
 
      description='Friendly distributed version control system',
89
 
      license='GNU GPL v2',
90
 
      packages=['bzrlib',
91
 
                'bzrlib.doc',
92
 
                'bzrlib.doc.api',
93
 
                'bzrlib.export',
94
 
                'bzrlib.plugins',
95
 
                'bzrlib.store',
96
 
                'bzrlib.store.revision',
97
 
                'bzrlib.store.versioned',
98
 
                'bzrlib.tests',
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',
107
 
                'bzrlib.transport',
108
 
                'bzrlib.transport.http',
109
 
                'bzrlib.ui',
110
 
                'bzrlib.util',
111
 
                'bzrlib.util.elementtree',
112
 
                'bzrlib.util.effbot.org',
113
 
                'bzrlib.util.configobj',
114
 
                ],
115
 
      scripts=['bzr'],
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.
119
 
     )
 
177
from breezy.bzr_distutils import build_mo
 
178
 
 
179
command_classes = {'install_scripts': my_install_scripts,
 
180
                   'build': bzr_build,
 
181
                   'build_mo': build_mo,
 
182
                   }
 
183
from distutils import log
 
184
from distutils.errors import CCompilerError, DistutilsPlatformError
 
185
from distutils.extension import Extension
 
186
ext_modules = []
 
187
try:
 
188
    from Cython.Distutils import build_ext
 
189
    from Cython.Compiler.Version import version as cython_version
 
190
except ImportError:
 
191
    have_cython = False
 
192
    # try to build the extension from the prior generated source.
 
193
    print("")
 
194
    print("The python package 'Cython' is not available."
 
195
          " If the .c files are available,")
 
196
    print("they will be built,"
 
197
          " but modifying the .pyx files will not rebuild them.")
 
198
    print("")
 
199
    from distutils.command.build_ext import build_ext
 
200
else:
 
201
    have_cython = True
 
202
    cython_version_info = LooseVersion(cython_version)
 
203
 
 
204
 
 
205
class build_ext_if_possible(build_ext):
 
206
 
 
207
    user_options = build_ext.user_options + [
 
208
        ('allow-python-fallback', None,
 
209
         "When an extension cannot be built, allow falling"
 
210
         " back to the pure-python implementation.")
 
211
        ]
 
212
 
 
213
    def initialize_options(self):
 
214
        build_ext.initialize_options(self)
 
215
        self.allow_python_fallback = False
 
216
 
 
217
    def run(self):
 
218
        try:
 
219
            build_ext.run(self)
 
220
        except DistutilsPlatformError:
 
221
            e = sys.exc_info()[1]
 
222
            if not self.allow_python_fallback:
 
223
                log.warn('\n  Cannot build extensions.\n'
 
224
                         '  Use "build_ext --allow-python-fallback" to use'
 
225
                         ' slower python implementations instead.\n')
 
226
                raise
 
227
            log.warn(str(e))
 
228
            log.warn('\n  Extensions cannot be built.\n'
 
229
                     '  Using the slower Python implementations instead.\n')
 
230
 
 
231
    def build_extension(self, ext):
 
232
        try:
 
233
            build_ext.build_extension(self, ext)
 
234
        except CCompilerError:
 
235
            if not self.allow_python_fallback:
 
236
                log.warn('\n  Cannot build extension "%s".\n'
 
237
                         '  Use "build_ext --allow-python-fallback" to use'
 
238
                         ' slower python implementations instead.\n'
 
239
                         % (ext.name,))
 
240
                raise
 
241
            log.warn('\n  Building of "%s" extension failed.\n'
 
242
                     '  Using the slower Python implementation instead.'
 
243
                     % (ext.name,))
 
244
 
 
245
 
 
246
# Override the build_ext if we have Cython available
 
247
command_classes['build_ext'] = build_ext_if_possible
 
248
unavailable_files = []
 
249
 
 
250
 
 
251
def add_cython_extension(module_name, libraries=None, extra_source=[]):
 
252
    """Add a cython module to build.
 
253
 
 
254
    This will use Cython to auto-generate the .c file if it is available.
 
255
    Otherwise it will fall back on the .c file. If the .c file is not
 
256
    available, it will warn, and not add anything.
 
257
 
 
258
    You can pass any extra options to Extension through kwargs. One example is
 
259
    'libraries = []'.
 
260
 
 
261
    :param module_name: The python path to the module. This will be used to
 
262
        determine the .pyx and .c files to use.
 
263
    """
 
264
    path = module_name.replace('.', '/')
 
265
    cython_name = path + '.pyx'
 
266
    c_name = path + '.c'
 
267
    define_macros = []
 
268
    if sys.platform == 'win32':
 
269
        # cython uses the macro WIN32 to detect the platform, even though it
 
270
        # should be using something like _WIN32 or MS_WINDOWS, oh well, we can
 
271
        # give it the right value.
 
272
        define_macros.append(('WIN32', None))
 
273
    if have_cython:
 
274
        source = [cython_name]
 
275
    else:
 
276
        if not os.path.isfile(c_name):
 
277
            unavailable_files.append(c_name)
 
278
            return
 
279
        else:
 
280
            source = [c_name]
 
281
    source.extend(extra_source)
 
282
    include_dirs = ['breezy']
 
283
    ext_modules.append(Extension(module_name, source,
 
284
        define_macros=define_macros, libraries=libraries,
 
285
        include_dirs=include_dirs))
 
286
 
 
287
 
 
288
add_cython_extension('breezy._simple_set_pyx')
 
289
ext_modules.append(Extension('breezy._static_tuple_c',
 
290
                             ['breezy/_static_tuple_c.c']))
 
291
add_cython_extension('breezy._annotator_pyx')
 
292
add_cython_extension('breezy._bencode_pyx')
 
293
add_cython_extension('breezy._chunks_to_lines_pyx')
 
294
add_cython_extension('breezy.bzr._groupcompress_pyx',
 
295
                    extra_source=['breezy/bzr/diff-delta.c'])
 
296
add_cython_extension('breezy.bzr._knit_load_data_pyx')
 
297
add_cython_extension('breezy._known_graph_pyx')
 
298
add_cython_extension('breezy._rio_pyx')
 
299
if sys.platform == 'win32':
 
300
    add_cython_extension('breezy.bzr._dirstate_helpers_pyx',
 
301
                        libraries=['Ws2_32'])
 
302
    add_cython_extension('breezy._walkdirs_win32')
 
303
else:
 
304
    add_cython_extension('breezy.bzr._dirstate_helpers_pyx')
 
305
    add_cython_extension('breezy._readdir_pyx')
 
306
add_cython_extension('breezy.bzr._chk_map_pyx')
 
307
ext_modules.append(Extension('breezy._patiencediff_c',
 
308
                             ['breezy/_patiencediff_c.c']))
 
309
add_cython_extension('breezy.bzr._btree_serializer_pyx')
 
310
 
 
311
 
 
312
if unavailable_files:
 
313
    print('C extension(s) not found:')
 
314
    print(('   %s' % ('\n  '.join(unavailable_files),)))
 
315
    print('The python versions will be used instead.')
 
316
    print("")
 
317
 
 
318
 
 
319
def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
 
320
                         gui_targets, data_files):
 
321
    packages.append('tbzrcommands')
 
322
 
 
323
    # ModuleFinder can't handle runtime changes to __path__, but
 
324
    # win32com uses them.  Hook this in so win32com.shell is found.
 
325
    import modulefinder
 
326
    import win32com
 
327
    import cPickle as pickle
 
328
    for p in win32com.__path__[1:]:
 
329
        modulefinder.AddPackagePath("win32com", p)
 
330
    for extra in ["win32com.shell"]:
 
331
        __import__(extra)
 
332
        m = sys.modules[extra]
 
333
        for p in m.__path__[1:]:
 
334
            modulefinder.AddPackagePath(extra, p)
 
335
 
 
336
    # TBZR points to the TBZR directory
 
337
    tbzr_root = os.environ["TBZR"]
 
338
 
 
339
    # Ensure tbreezy itself is on sys.path
 
340
    sys.path.append(tbzr_root)
 
341
 
 
342
    packages.append("tbreezy")
 
343
 
 
344
    # collect up our icons.
 
345
    cwd = os.getcwd()
 
346
    ico_root = os.path.join(tbzr_root, 'tbreezy', 'resources')
 
347
    icos = [] # list of (path_root, relative_ico_path)
 
348
    # First always brz's icon and its in the root of the brz tree.
 
349
    icos.append(('', 'brz.ico'))
 
350
    for root, dirs, files in os.walk(ico_root):
 
351
        icos.extend([(ico_root, os.path.join(root, f)[len(ico_root)+1:])
 
352
                     for f in files if f.endswith('.ico')])
 
353
    # allocate an icon ID for each file and the full path to the ico
 
354
    icon_resources = [(rid, os.path.join(ico_dir, ico_name))
 
355
                      for rid, (ico_dir, ico_name) in enumerate(icos)]
 
356
    # create a string resource with the mapping.  Might as well save the
 
357
    # runtime some effort and write a pickle.
 
358
    # Runtime expects unicode objects with forward-slash seps.
 
359
    fse = sys.getfilesystemencoding()
 
360
    map_items = [(f.replace('\\', '/').decode(fse), rid)
 
361
                 for rid, (_, f) in enumerate(icos)]
 
362
    ico_map = dict(map_items)
 
363
    # Create a new resource type of 'ICON_MAP', and use ID=1
 
364
    other_resources = [ ("ICON_MAP", 1, pickle.dumps(ico_map))]
 
365
 
 
366
    excludes.extend("""pywin pywin.dialogs pywin.dialogs.list
 
367
                       win32ui crawler.Crawler""".split())
 
368
 
 
369
    # tbzrcache executables - a "console" version for debugging and a
 
370
    # GUI version that is generally used.
 
371
    tbzrcache = dict(
 
372
        script = os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
 
373
        icon_resources = icon_resources,
 
374
        other_resources = other_resources,
 
375
    )
 
376
    console_targets.append(tbzrcache)
 
377
 
 
378
    # Make a windows version which is the same except for the base name.
 
379
    tbzrcachew = tbzrcache.copy()
 
380
    tbzrcachew["dest_base"]="tbzrcachew"
 
381
    gui_targets.append(tbzrcachew)
 
382
 
 
383
    # ditto for the tbzrcommand tool
 
384
    tbzrcommand = dict(
 
385
        script = os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
 
386
        icon_resources = icon_resources,
 
387
        other_resources = other_resources,
 
388
    )
 
389
    console_targets.append(tbzrcommand)
 
390
    tbzrcommandw = tbzrcommand.copy()
 
391
    tbzrcommandw["dest_base"]="tbzrcommandw"
 
392
    gui_targets.append(tbzrcommandw)
 
393
    
 
394
    # A utility to see python output from both C++ and Python based shell
 
395
    # extensions
 
396
    tracer = dict(script=os.path.join(tbzr_root, "scripts", "tbzrtrace.py"))
 
397
    console_targets.append(tracer)
 
398
 
 
399
    # The C++ implemented shell extensions.
 
400
    dist_dir = os.path.join(tbzr_root, "shellext", "build")
 
401
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x86.dll')]))
 
402
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x64.dll')]))
 
403
 
 
404
 
 
405
def get_qbzr_py2exe_info(includes, excludes, packages, data_files):
 
406
    # PyQt4 itself still escapes the plugin detection code for some reason...
 
407
    includes.append('PyQt4.QtCore')
 
408
    includes.append('PyQt4.QtGui')
 
409
    includes.append('PyQt4.QtTest')
 
410
    includes.append('sip') # extension module required for Qt.
 
411
    packages.append('pygments') # colorizer for qbzr
 
412
    packages.append('docutils') # html formatting
 
413
    includes.append('win32event')  # for qsubprocess stuff
 
414
    # the qt binaries might not be on PATH...
 
415
    # They seem to install to a place like C:\Python25\PyQt4\*
 
416
    # Which is not the same as C:\Python25\Lib\site-packages\PyQt4
 
417
    pyqt_dir = os.path.join(sys.prefix, "PyQt4")
 
418
    pyqt_bin_dir = os.path.join(pyqt_dir, "bin")
 
419
    if os.path.isdir(pyqt_bin_dir):
 
420
        path = os.environ.get("PATH", "")
 
421
        if pyqt_bin_dir.lower() not in [p.lower() for p in path.split(os.pathsep)]:
 
422
            os.environ["PATH"] = path + os.pathsep + pyqt_bin_dir
 
423
    # also add all imageformat plugins to distribution
 
424
    # We will look in 2 places, dirname(PyQt4.__file__) and pyqt_dir
 
425
    base_dirs_to_check = []
 
426
    if os.path.isdir(pyqt_dir):
 
427
        base_dirs_to_check.append(pyqt_dir)
 
428
    try:
 
429
        import PyQt4
 
430
    except ImportError:
 
431
        pass
 
432
    else:
 
433
        pyqt4_base_dir = os.path.dirname(PyQt4.__file__)
 
434
        if pyqt4_base_dir != pyqt_dir:
 
435
            base_dirs_to_check.append(pyqt4_base_dir)
 
436
    if not base_dirs_to_check:
 
437
        log.warn("Can't find PyQt4 installation -> not including imageformat"
 
438
                 " plugins")
 
439
    else:
 
440
        files = []
 
441
        for base_dir in base_dirs_to_check:
 
442
            plug_dir = os.path.join(base_dir, 'plugins', 'imageformats')
 
443
            if os.path.isdir(plug_dir):
 
444
                for fname in os.listdir(plug_dir):
 
445
                    # Include plugin dlls, but not debugging dlls
 
446
                    fullpath = os.path.join(plug_dir, fname)
 
447
                    if fname.endswith('.dll') and not fname.endswith('d4.dll'):
 
448
                        files.append(fullpath)
 
449
        if files:
 
450
            data_files.append(('imageformats', files))
 
451
        else:
 
452
            log.warn('PyQt4 was found, but we could not find any imageformat'
 
453
                     ' plugins. Are you sure your configuration is correct?')
 
454
 
 
455
 
 
456
def get_svn_py2exe_info(includes, excludes, packages):
 
457
    packages.append('subvertpy')
 
458
    packages.append('sqlite3')
 
459
 
 
460
 
 
461
def get_git_py2exe_info(includes, excludes, packages):
 
462
    packages.append('dulwich')
 
463
 
 
464
 
 
465
def get_fastimport_py2exe_info(includes, excludes, packages):
 
466
    # This is the python-fastimport package, not to be confused with the
 
467
    # brz-fastimport plugin.
 
468
    packages.append('fastimport')
 
469
 
 
470
 
 
471
if 'bdist_wininst' in sys.argv:
 
472
    def find_docs():
 
473
        docs = []
 
474
        for root, dirs, files in os.walk('doc'):
 
475
            r = []
 
476
            for f in files:
 
477
                if (os.path.splitext(f)[1] in ('.html','.css','.png','.pdf')
 
478
                    or f == 'quick-start-summary.svg'):
 
479
                    r.append(os.path.join(root, f))
 
480
            if r:
 
481
                relative = root[4:]
 
482
                if relative:
 
483
                    target = os.path.join('Doc\\Breezy', relative)
 
484
                else:
 
485
                    target = 'Doc\\Breezy'
 
486
                docs.append((target, r))
 
487
        return docs
 
488
 
 
489
    # python's distutils-based win32 installer
 
490
    ARGS = {'scripts': ['brz', 'tools/win32/brz-win32-bdist-postinstall.py'],
 
491
            'ext_modules': ext_modules,
 
492
            # help pages
 
493
            'data_files': find_docs(),
 
494
            # for building cython extensions
 
495
            'cmdclass': command_classes,
 
496
           }
 
497
 
 
498
    ARGS.update(META_INFO)
 
499
    ARGS.update(BZRLIB)
 
500
    PKG_DATA['package_data']['breezy'].append('locale/*/LC_MESSAGES/*.mo')
 
501
    ARGS.update(PKG_DATA)
 
502
 
 
503
    setup(**ARGS)
 
504
 
 
505
elif 'py2exe' in sys.argv:
 
506
    # py2exe setup
 
507
    import py2exe
 
508
 
 
509
    # pick real brz version
 
510
    import breezy
 
511
 
 
512
    version_number = []
 
513
    for i in breezy.version_info[:4]:
 
514
        try:
 
515
            i = int(i)
 
516
        except ValueError:
 
517
            i = 0
 
518
        version_number.append(str(i))
 
519
    version_str = '.'.join(version_number)
 
520
 
 
521
    # An override to install_data used only by py2exe builds, which arranges
 
522
    # to byte-compile any .py files in data_files (eg, our plugins)
 
523
    # Necessary as we can't rely on the user having the relevant permissions
 
524
    # to the "Program Files" directory to generate them on the fly.
 
525
    class install_data_with_bytecompile(install_data):
 
526
        def run(self):
 
527
            from distutils.util import byte_compile
 
528
 
 
529
            install_data.run(self)
 
530
 
 
531
            py2exe = self.distribution.get_command_obj('py2exe', False)
 
532
            # GZ 2010-04-19: Setup has py2exe.optimize as 2, but give plugins
 
533
            #                time before living with docstring stripping
 
534
            optimize = 1
 
535
            compile_names = [f for f in self.outfiles if f.endswith('.py')]
 
536
            # Round mtime to nearest even second so that installing on a FAT
 
537
            # filesystem bytecode internal and script timestamps will match
 
538
            for f in compile_names:
 
539
                mtime = os.stat(f).st_mtime
 
540
                remainder = mtime % 2
 
541
                if remainder:
 
542
                    mtime -= remainder
 
543
                    os.utime(f, (mtime, mtime))
 
544
            byte_compile(compile_names,
 
545
                         optimize=optimize,
 
546
                         force=self.force, prefix=self.install_dir,
 
547
                         dry_run=self.dry_run)
 
548
            self.outfiles.extend([f + 'o' for f in compile_names])
 
549
    # end of class install_data_with_bytecompile
 
550
 
 
551
    target = py2exe.build_exe.Target(script = "brz",
 
552
                                     dest_base = "brz",
 
553
                                     icon_resources = [(0,'brz.ico')],
 
554
                                     name = META_INFO['name'],
 
555
                                     version = version_str,
 
556
                                     description = META_INFO['description'],
 
557
                                     author = META_INFO['author'],
 
558
                                     copyright = "(c) Canonical Ltd, 2005-2010",
 
559
                                     company_name = "Canonical Ltd.",
 
560
                                     comments = META_INFO['description'],
 
561
                                    )
 
562
    gui_target = copy.copy(target)
 
563
    gui_target.dest_base = "bzrw"
 
564
 
 
565
    packages = BZRLIB['packages']
 
566
    packages.remove('breezy')
 
567
    packages = [i for i in packages if not i.startswith('breezy.plugins')]
 
568
    includes = []
 
569
    for i in glob.glob('breezy\\*.py'):
 
570
        module = i[:-3].replace('\\', '.')
 
571
        if module.endswith('__init__'):
 
572
            module = module[:-len('__init__')]
 
573
        includes.append(module)
 
574
 
 
575
    additional_packages = set()
 
576
    if sys.version.startswith('2.7'):
 
577
        additional_packages.add('xml.etree')
 
578
    else:
 
579
        import warnings
 
580
        warnings.warn('Unknown Python version.\n'
 
581
                      'Please check setup.py script for compatibility.')
 
582
 
 
583
    # Although we currently can't enforce it, we consider it an error for
 
584
    # py2exe to report any files are "missing".  Such modules we know aren't
 
585
    # used should be listed here.
 
586
    excludes = """Tkinter psyco ElementPath r_hmac
 
587
                  ImaginaryModule cElementTree elementtree.ElementTree
 
588
                  Crypto.PublicKey._fastmath
 
589
                  tools
 
590
                  resource validate""".split()
 
591
    dll_excludes = []
 
592
 
 
593
    # email package from std python library use lazy import,
 
594
    # so we need to explicitly add all package
 
595
    additional_packages.add('email')
 
596
    # And it uses funky mappings to conver to 'Oldname' to 'newname'.  As
 
597
    # a result, packages like 'email.Parser' show as missing.  Tell py2exe
 
598
    # to exclude them.
 
599
    import email
 
600
    for oldname in getattr(email, '_LOWERNAMES', []):
 
601
        excludes.append("email." + oldname)
 
602
    for oldname in getattr(email, '_MIMENAMES', []):
 
603
        excludes.append("email.MIME" + oldname)
 
604
 
 
605
    # text files for help topis
 
606
    text_topics = glob.glob('breezy/help_topics/en/*.txt')
 
607
    topics_files = [('lib/help_topics/en', text_topics)]
 
608
 
 
609
    # built-in plugins
 
610
    plugins_files = []
 
611
    # XXX - should we consider having the concept of an 'official' build,
 
612
    # which hard-codes the list of plugins, gets more upset if modules are
 
613
    # missing, etc?
 
614
    plugins = None # will be a set after plugin sniffing...
 
615
    for root, dirs, files in os.walk('breezy/plugins'):
 
616
        if root == 'breezy/plugins':
 
617
            plugins = set(dirs)
 
618
            # We ship plugins as normal files on the file-system - however,
 
619
            # the build process can cause *some* of these plugin files to end
 
620
            # up in library.zip. Thus, we saw (eg) "plugins/svn/test" in
 
621
            # library.zip, and then saw import errors related to that as the
 
622
            # rest of the svn plugin wasn't. So we tell py2exe to leave the
 
623
            # plugins out of the .zip file
 
624
            excludes.extend(["breezy.plugins." + d for d in dirs])
 
625
        x = []
 
626
        for i in files:
 
627
            # Throw away files we don't want packaged. Note that plugins may
 
628
            # have data files with all sorts of extensions so we need to
 
629
            # be conservative here about what we ditch.
 
630
            ext = os.path.splitext(i)[1]
 
631
            if ext.endswith('~') or ext in [".pyc", ".swp"]:
 
632
                continue
 
633
            if i == '__init__.py' and root == 'breezy/plugins':
 
634
                continue
 
635
            x.append(os.path.join(root, i))
 
636
        if x:
 
637
            target_dir = root[len('breezy/'):]  # install to 'plugins/...'
 
638
            plugins_files.append((target_dir, x))
 
639
    # find modules for built-in plugins
 
640
    import tools.package_mf
 
641
    mf = tools.package_mf.CustomModuleFinder()
 
642
    mf.run_package('breezy/plugins')
 
643
    packs, mods = mf.get_result()
 
644
    additional_packages.update(packs)
 
645
    includes.extend(mods)
 
646
 
 
647
    console_targets = [target,
 
648
                       'tools/win32/bzr_postinstall.py',
 
649
                       ]
 
650
    gui_targets = [gui_target]
 
651
    data_files = topics_files + plugins_files + I18N_FILES
 
652
 
 
653
    if 'qbzr' in plugins:
 
654
        get_qbzr_py2exe_info(includes, excludes, packages, data_files)
 
655
 
 
656
    if 'svn' in plugins:
 
657
        get_svn_py2exe_info(includes, excludes, packages)
 
658
 
 
659
    if 'git' in plugins:
 
660
        get_git_py2exe_info(includes, excludes, packages)
 
661
 
 
662
    if 'fastimport' in plugins:
 
663
        get_fastimport_py2exe_info(includes, excludes, packages)
 
664
 
 
665
    if "TBZR" in os.environ:
 
666
        # TORTOISE_OVERLAYS_MSI_WIN32 must be set to the location of the
 
667
        # TortoiseOverlays MSI installer file. It is in the TSVN svn repo and
 
668
        # can be downloaded from (username=guest, blank password):
 
669
        # http://tortoisesvn.tigris.org/svn/tortoisesvn/TortoiseOverlays
 
670
        # look for: version-1.0.4/bin/TortoiseOverlays-1.0.4.11886-win32.msi
 
671
        # Ditto for TORTOISE_OVERLAYS_MSI_X64, pointing at *-x64.msi.
 
672
        for needed in ('TORTOISE_OVERLAYS_MSI_WIN32',
 
673
                       'TORTOISE_OVERLAYS_MSI_X64'):
 
674
            url = ('http://guest:@tortoisesvn.tigris.org/svn/tortoisesvn'
 
675
                   '/TortoiseOverlays')
 
676
            if not os.path.isfile(os.environ.get(needed, '<nofile>')):
 
677
                raise RuntimeError(
 
678
                    "\nPlease set %s to the location of the relevant"
 
679
                    "\nTortoiseOverlays .msi installer file."
 
680
                    " The installers can be found at"
 
681
                    "\n  %s"
 
682
                    "\ncheck in the version-X.Y.Z/bin/ subdir" % (needed, url))
 
683
        get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
 
684
                             gui_targets, data_files)
 
685
    else:
 
686
        # print this warning to stderr as output is redirected, so it is seen
 
687
        # at build time.  Also to stdout so it appears in the log
 
688
        for f in (sys.stderr, sys.stdout):
 
689
            f.write("Skipping TBZR binaries - "
 
690
                "please set TBZR to a directory to enable\n")
 
691
 
 
692
    # MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
 
693
    # in on Vista.
 
694
    dll_excludes.extend(["MSWSOCK.dll",
 
695
                         "MSVCP60.dll",
 
696
                         "MSVCP90.dll",
 
697
                         "powrprof.dll",
 
698
                         "SHFOLDER.dll"])
 
699
    options_list = {"py2exe": {"packages": packages + list(additional_packages),
 
700
                               "includes": includes,
 
701
                               "excludes": excludes,
 
702
                               "dll_excludes": dll_excludes,
 
703
                               "dist_dir": "win32_bzr.exe",
 
704
                               "optimize": 2,
 
705
                               "custom_boot_script":
 
706
                                        "tools/win32/py2exe_boot_common.py",
 
707
                              },
 
708
                   }
 
709
 
 
710
    # We want the libaray.zip to have optimize = 2, but the exe to have
 
711
    # optimize = 1, so that .py files that get compilied at run time
 
712
    # (e.g. user installed plugins) dont have their doc strings removed.
 
713
    class py2exe_no_oo_exe(py2exe.build_exe.py2exe):
 
714
        def build_executable(self, *args, **kwargs):
 
715
            self.optimize = 1
 
716
            py2exe.build_exe.py2exe.build_executable(self, *args, **kwargs)
 
717
            self.optimize = 2
 
718
 
 
719
    if __name__ == '__main__':
 
720
        command_classes['install_data'] = install_data_with_bytecompile
 
721
        command_classes['py2exe'] = py2exe_no_oo_exe
 
722
        setup(options=options_list,
 
723
              console=console_targets,
 
724
              windows=gui_targets,
 
725
              zipfile='lib/library.zip',
 
726
              data_files=data_files,
 
727
              cmdclass=command_classes,
 
728
              )
 
729
 
 
730
else:
 
731
    # ad-hoc for easy_install
 
732
    DATA_FILES = []
 
733
    if not 'bdist_egg' in sys.argv:
 
734
        # generate and install brz.1 only with plain install, not the
 
735
        # easy_install one
 
736
        DATA_FILES = [('man/man1', ['brz.1'])]
 
737
 
 
738
    DATA_FILES = DATA_FILES + I18N_FILES
 
739
    # std setup
 
740
    ARGS = {'scripts': ['brz'],
 
741
            'data_files': DATA_FILES,
 
742
            'cmdclass': command_classes,
 
743
            'ext_modules': ext_modules,
 
744
           }
 
745
 
 
746
    ARGS.update(META_INFO)
 
747
    ARGS.update(BZRLIB)
 
748
    ARGS.update(PKG_DATA)
 
749
 
 
750
    if __name__ == '__main__':
 
751
        setup(**ARGS)