/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-12-24 02:20:45 UTC
  • mto: (1185.50.57 bzr-jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1550.
  • Revision ID: robertc@robertcollins.net-20051224022045-14efc8dfa0e1a4e9
Start tests for api usage.

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