/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: Robert Collins
  • Date: 2005-10-19 10:11:57 UTC
  • mfrom: (1185.16.78)
  • mto: This revision was merged to the branch mainline in revision 1470.
  • Revision ID: robertc@robertcollins.net-20051019101157-17438d311e746b4f
mergeĀ fromĀ upstream

Show diffs side-by-side

added added

removed removed

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