~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: John Arbash Meinel
  • Date: 2007-10-17 17:03:06 UTC
  • mto: This revision was merged to the branch mainline in revision 2918.
  • Revision ID: john@arbash-meinel.com-20071017170306-20w50sk1djh0i14k
Switch around to properly look up the executable bit in the basis.
We do this with a load-time switch around supports_executable(), rather than
a runtime if supports_executable() check.
It would be nice to inline the _is_executable_* check on platforms that support
executable, but we had a function call before, so we haven't degraded
performance.

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
 
3
"""Installation script for bzr.
 
4
Run it with
 
5
 './setup.py install', or
 
6
 './setup.py --help' for more options
 
7
"""
 
8
 
 
9
import os
 
10
import sys
 
11
 
 
12
import bzrlib
 
13
 
 
14
##
 
15
# META INFORMATION FOR SETUP
 
16
 
 
17
META_INFO = {'name':         'bzr',
 
18
             'version':      bzrlib.__version__,
 
19
             'author':       'Canonical Ltd',
 
20
             'author_email': 'bazaar@lists.canonical.com',
 
21
             'url':          'http://www.bazaar-vcs.org/',
 
22
             'description':  'Friendly distributed version control system',
 
23
             'license':      'GNU GPL v2',
 
24
            }
 
25
 
 
26
# The list of packages is automatically generated later. Add other things
 
27
# that are part of BZRLIB here.
 
28
BZRLIB = {}
 
29
 
 
30
PKG_DATA = {# install files from selftest suite
 
31
            'package_data': {'bzrlib': ['doc/api/*.txt',
 
32
                                        'tests/test_patches_data/*',
 
33
                                       ]},
 
34
           }
 
35
 
 
36
######################################################################
 
37
# Reinvocation stolen from bzr, we need python2.4 by virtue of bzr_man
 
38
# including bzrlib.help
 
39
 
 
40
try:
 
41
    version_info = sys.version_info
 
42
except AttributeError:
 
43
    version_info = 1, 5 # 1.5 or older
 
44
 
 
45
REINVOKE = "__BZR_REINVOKE"
 
46
NEED_VERS = (2, 4)
 
47
KNOWN_PYTHONS = ('python2.4',)
 
48
 
 
49
if version_info < NEED_VERS:
 
50
    if not os.environ.has_key(REINVOKE):
 
51
        # mutating os.environ doesn't work in old Pythons
 
52
        os.putenv(REINVOKE, "1")
 
53
        for python in KNOWN_PYTHONS:
 
54
            try:
 
55
                os.execvp(python, [python] + sys.argv)
 
56
            except OSError:
 
57
                pass
 
58
    print >>sys.stderr, "bzr: error: cannot find a suitable python interpreter"
 
59
    print >>sys.stderr, "  (need %d.%d or later)" % NEED_VERS
 
60
    sys.exit(1)
 
61
if getattr(os, "unsetenv", None) is not None:
 
62
    os.unsetenv(REINVOKE)
 
63
 
 
64
 
 
65
def get_bzrlib_packages():
 
66
    """Recurse through the bzrlib directory, and extract the package names"""
 
67
 
 
68
    packages = []
 
69
    base_path = os.path.dirname(os.path.abspath(bzrlib.__file__))
 
70
    for root, dirs, files in os.walk(base_path):
 
71
        if '__init__.py' in files:
 
72
            assert root.startswith(base_path)
 
73
            # Get just the path below bzrlib
 
74
            package_path = root[len(base_path):]
 
75
            # Remove leading and trailing slashes
 
76
            package_path = package_path.strip('\\/')
 
77
            if not package_path:
 
78
                package_name = 'bzrlib'
 
79
            else:
 
80
                package_name = ('bzrlib.' +
 
81
                            package_path.replace('/', '.').replace('\\', '.'))
 
82
            packages.append(package_name)
 
83
    return sorted(packages)
 
84
 
 
85
 
 
86
BZRLIB['packages'] = get_bzrlib_packages()
 
87
 
6
88
 
7
89
from distutils.core import setup
8
 
 
9
 
setup(name='bzr',
10
 
      version='0.0.0',
11
 
      author='Martin Pool',
12
 
      author_email='mbp@sourcefrog.net',
13
 
      url='http://www.bazaar-ng.org/',
14
 
      description='Friendly distributed version control system',
15
 
      license='GNU GPL v2',
16
 
      packages=['bzrlib',
17
 
                'bzrlib.plugins',
18
 
                'bzrlib.selftest',
19
 
                'bzrlib.util',
20
 
                'bzrlib.util.elementtree',
21
 
                'bzrlib.util.effbot.org',
22
 
                ],
23
 
      scripts=['bzr'])
 
90
from distutils.command.install_scripts import install_scripts
 
91
from distutils.command.build import build
 
92
 
 
93
###############################
 
94
# Overridden distutils actions
 
95
###############################
 
96
 
 
97
class my_install_scripts(install_scripts):
 
98
    """ Customized install_scripts distutils action.
 
99
    Create bzr.bat for win32.
 
100
    """
 
101
    def run(self):
 
102
        install_scripts.run(self)   # standard action
 
103
 
 
104
        if sys.platform == "win32":
 
105
            try:
 
106
                scripts_dir = os.path.join(sys.prefix, 'Scripts')
 
107
                script_path = self._quoted_path(os.path.join(scripts_dir,
 
108
                                                             "bzr"))
 
109
                python_exe = self._quoted_path(sys.executable)
 
110
                args = self._win_batch_args()
 
111
                batch_str = "@%s %s %s" % (python_exe, script_path, args)
 
112
                batch_path = os.path.join(self.install_dir, "bzr.bat")
 
113
                f = file(batch_path, "w")
 
114
                f.write(batch_str)
 
115
                f.close()
 
116
                print "Created:", batch_path
 
117
            except Exception, e:
 
118
                print "ERROR: Unable to create %s: %s" % (batch_path, e)
 
119
 
 
120
    def _quoted_path(self, path):
 
121
        if ' ' in path:
 
122
            return '"' + path + '"'
 
123
        else:
 
124
            return path
 
125
 
 
126
    def _win_batch_args(self):
 
127
        from bzrlib.win32utils import winver
 
128
        if winver == 'Windows NT':
 
129
            return '%*'
 
130
        else:
 
131
            return '%1 %2 %3 %4 %5 %6 %7 %8 %9'
 
132
#/class my_install_scripts
 
133
 
 
134
 
 
135
class bzr_build(build):
 
136
    """Customized build distutils action.
 
137
    Generate bzr.1.
 
138
    """
 
139
    def run(self):
 
140
        build.run(self)
 
141
 
 
142
        import generate_docs
 
143
        generate_docs.main(argv=["bzr", "man"])
 
144
 
 
145
 
 
146
########################
 
147
## Setup
 
148
########################
 
149
 
 
150
command_classes = {'install_scripts': my_install_scripts,
 
151
                   'build': bzr_build}
 
152
from distutils import log
 
153
from distutils.errors import CCompilerError, DistutilsPlatformError
 
154
from distutils.extension import Extension
 
155
ext_modules = []
 
156
try:
 
157
    from Pyrex.Distutils import build_ext
 
158
except ImportError:
 
159
    have_pyrex = False
 
160
    # try to build the extension from the prior generated source.
 
161
    print
 
162
    print ("The python package 'Pyrex' is not available."
 
163
           " If the .c files are available,")
 
164
    print ("they will be built,"
 
165
           " but modifying the .pyx files will not rebuild them.")
 
166
    print
 
167
    from distutils.command.build_ext import build_ext
 
168
else:
 
169
    have_pyrex = True
 
170
 
 
171
 
 
172
class build_ext_if_possible(build_ext):
 
173
 
 
174
    def run(self):
 
175
        try:
 
176
            build_ext.run(self)
 
177
        except DistutilsPlatformError, e:
 
178
            log.warn(str(e))
 
179
            log.warn('Extensions cannot be built, '
 
180
                     'will use the Python versions instead')
 
181
 
 
182
    def build_extension(self, ext):
 
183
        try:
 
184
            build_ext.build_extension(self, ext)
 
185
        except CCompilerError:
 
186
            log.warn('Building of "%s" extension failed, '
 
187
                     'will use the Python version instead' % (ext.name,))
 
188
 
 
189
 
 
190
# Override the build_ext if we have Pyrex available
 
191
command_classes['build_ext'] = build_ext_if_possible
 
192
unavailable_files = []
 
193
 
 
194
 
 
195
def add_pyrex_extension(module_name, **kwargs):
 
196
    """Add a pyrex module to build.
 
197
 
 
198
    This will use Pyrex to auto-generate the .c file if it is available.
 
199
    Otherwise it will fall back on the .c file. If the .c file is not
 
200
    available, it will warn, and not add anything.
 
201
 
 
202
    You can pass any extra options to Extension through kwargs. One example is
 
203
    'libraries = []'.
 
204
 
 
205
    :param module_name: The python path to the module. This will be used to
 
206
        determine the .pyx and .c files to use.
 
207
    """
 
208
    path = module_name.replace('.', '/')
 
209
    pyrex_name = path + '.pyx'
 
210
    c_name = path + '.c'
 
211
    if have_pyrex:
 
212
        ext_modules.append(Extension(module_name, [pyrex_name]))
 
213
    else:
 
214
        if not os.path.isfile(c_name):
 
215
            unavailable_files.append(c_name)
 
216
        else:
 
217
            ext_modules.append(Extension(module_name, [c_name]))
 
218
 
 
219
 
 
220
add_pyrex_extension('bzrlib._dirstate_helpers_c')
 
221
add_pyrex_extension('bzrlib._knit_load_data_c')
 
222
ext_modules.append(Extension('bzrlib._patiencediff_c', ['bzrlib/_patiencediff_c.c']))
 
223
 
 
224
 
 
225
if unavailable_files:
 
226
    print 'C extension(s) not found:'
 
227
    print '   %s' % ('\n  '.join(unavailable_files),)
 
228
    print 'The python versions will be used instead.'
 
229
    print
 
230
 
 
231
 
 
232
if 'bdist_wininst' in sys.argv:
 
233
    def find_docs():
 
234
        docs = []
 
235
        for root, dirs, files in os.walk('doc'):
 
236
            r = []
 
237
            for f in files:
 
238
                if os.path.splitext(f)[1] in ('.html', '.css'):
 
239
                    r.append(os.path.join(root, f))
 
240
            if r:
 
241
                relative = root[4:]
 
242
                if relative:
 
243
                    target = os.path.join('Doc\\Bazaar', relative)
 
244
                else:
 
245
                    target = 'Doc\\Bazaar'
 
246
                docs.append((target, r))
 
247
        return docs
 
248
 
 
249
    # python's distutils-based win32 installer
 
250
    ARGS = {'scripts': ['bzr', 'tools/win32/bzr-win32-bdist-postinstall.py'],
 
251
            'ext_modules': ext_modules,
 
252
            # help pages
 
253
            'data_files': find_docs(),
 
254
            # for building pyrex extensions
 
255
            'cmdclass': {'build_ext': build_ext_if_possible},
 
256
           }
 
257
 
 
258
    ARGS.update(META_INFO)
 
259
    ARGS.update(BZRLIB)
 
260
    ARGS.update(PKG_DATA)
 
261
    
 
262
    setup(**ARGS)
 
263
 
 
264
elif 'py2exe' in sys.argv:
 
265
    # py2exe setup
 
266
    import py2exe
 
267
 
 
268
    # pick real bzr version
 
269
    import bzrlib
 
270
 
 
271
    version_number = []
 
272
    for i in bzrlib.version_info[:4]:
 
273
        try:
 
274
            i = int(i)
 
275
        except ValueError:
 
276
            i = 0
 
277
        version_number.append(str(i))
 
278
    version_str = '.'.join(version_number)
 
279
 
 
280
    target = py2exe.build_exe.Target(script = "bzr",
 
281
                                     dest_base = "bzr",
 
282
                                     icon_resources = [(0,'bzr.ico')],
 
283
                                     name = META_INFO['name'],
 
284
                                     version = version_str,
 
285
                                     description = META_INFO['description'],
 
286
                                     author = META_INFO['author'],
 
287
                                     copyright = "(c) Canonical Ltd, 2005-2007",
 
288
                                     company_name = "Canonical Ltd.",
 
289
                                     comments = META_INFO['description'],
 
290
                                    )
 
291
 
 
292
    additional_packages =  []
 
293
    if sys.version.startswith('2.4'):
 
294
        # adding elementtree package
 
295
        additional_packages.append('elementtree')
 
296
    elif sys.version.startswith('2.5'):
 
297
        additional_packages.append('xml.etree')
 
298
    else:
 
299
        import warnings
 
300
        warnings.warn('Unknown Python version.\n'
 
301
                      'Please check setup.py script for compatibility.')
 
302
    # email package from std python library use lazy import,
 
303
    # so we need to explicitly add all package
 
304
    additional_packages.append('email')
 
305
 
 
306
    options_list = {"py2exe": {"packages": BZRLIB['packages'] +
 
307
                                           additional_packages,
 
308
                               "excludes": ["Tkinter", "medusa", "tools"],
 
309
                               "dist_dir": "win32_bzr.exe",
 
310
                              },
 
311
                   }
 
312
    setup(options=options_list,
 
313
          console=[target,
 
314
                   'tools/win32/bzr_postinstall.py',
 
315
                  ],
 
316
          zipfile='lib/library.zip')
 
317
 
 
318
else:
 
319
    # ad-hoc for easy_install
 
320
    DATA_FILES = []
 
321
    if not 'bdist_egg' in sys.argv:
 
322
        # generate and install bzr.1 only with plain install, not easy_install one
 
323
        DATA_FILES = [('man/man1', ['bzr.1'])]
 
324
 
 
325
    # std setup
 
326
    ARGS = {'scripts': ['bzr'],
 
327
            'data_files': DATA_FILES,
 
328
            'cmdclass': command_classes,
 
329
            'ext_modules': ext_modules,
 
330
           }
 
331
 
 
332
    ARGS.update(META_INFO)
 
333
    ARGS.update(BZRLIB)
 
334
    ARGS.update(PKG_DATA)
 
335
 
 
336
    setup(**ARGS)