/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: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2018-03-24 02:22:27 UTC
  • mfrom: (6883.13.2 rename-config-bzr-transform)
  • Revision ID: breezy.the.bot@gmail.com-20180324022227-3k2w06998irur1d7
Rename the ``brz.transform.orphan_policy`` flag to ``transform.orphan_policy``.

Merged from https://code.launchpad.net/~jelmer/brz/rename-config-brz-transform/+merge/341279

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