15
if sys.version_info < (2, 6):
16
sys.stderr.write("[ERROR] Not a supported Python version. Need 2.6+\n")
15
if sys.version_info < (3, 5):
16
sys.stderr.write("[ERROR] Not a supported Python version. Need 3.5+\n")
22
except ImportError as e:
23
sys.stderr.write("[ERROR] Please install setuptools (%s)\n" % e)
19
27
# NOTE: The directory containing setup.py, whether run by 'python setup.py' or
20
28
# './setup.py' or the equivalent with another path, should always be at the
21
29
# start of the path, so this should find the right one...
24
32
def get_long_description():
25
33
dirname = os.path.dirname(__file__)
26
readme = os.path.join(dirname, 'README')
27
f = open(readme, 'rb')
34
readme = os.path.join(dirname, 'README.rst')
35
with open(readme, 'r') as f:
35
40
# META INFORMATION FOR SETUP
36
41
# see http://docs.python.org/dist/meta-data.html
39
'version': bzrlib.__version__,
40
'author': 'Canonical Ltd',
41
'author_email': 'bazaar@lists.canonical.com',
42
'url': 'http://bazaar.canonical.com/',
43
'description': 'Friendly distributed version control system',
44
'license': 'GNU GPL v2',
45
'download_url': 'https://launchpad.net/bzr/+download',
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',
46
51
'long_description': get_long_description(),
48
53
'Development Status :: 6 - Mature',
57
62
'Programming Language :: C',
58
63
'Topic :: Software Development :: Version Control',
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"',
76
'launchpad': ['launchpadlib>=1.6.3'],
77
'workspace': ['pyinotify'],
81
'testtools<=2.4.0;python_version<"3.0"',
86
# The list of packages is automatically generated later. Add other things
87
# that are part of BREEZY here.
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',
62
# The list of packages is automatically generated later. Add other things
63
# that are part of BZRLIB here.
66
PKG_DATA = {# install files from selftest suite
67
'package_data': {'bzrlib': ['doc/api/*.txt',
68
'tests/test_patches_data/*',
69
'help_topics/en/*.txt',
70
'tests/ssl_certs/ca.crt',
71
'tests/ssl_certs/server_without_pass.key',
72
'tests/ssl_certs/server_with_pass.key',
73
'tests/ssl_certs/server.crt',
77
for filepath in glob.glob("bzrlib/locale/*/LC_MESSAGES/*.mo"):
78
langfile = filepath[len("bzrlib/locale/"):]
102
for filepath in glob.glob("breezy/locale/*/LC_MESSAGES/*.mo"):
103
langfile = filepath[len("breezy/locale/"):]
79
104
targetpath = os.path.dirname(os.path.join("share/locale", langfile))
80
105
I18N_FILES.append((targetpath, [filepath]))
82
def get_bzrlib_packages():
83
"""Recurse through the bzrlib directory, and extract the package names"""
107
def get_breezy_packages():
108
"""Recurse through the breezy directory, and extract the package names"""
86
base_path = os.path.dirname(os.path.abspath(bzrlib.__file__))
111
base_path = os.path.dirname(os.path.abspath(breezy.__file__))
87
112
for root, dirs, files in os.walk(base_path):
88
113
if '__init__.py' in files:
89
114
assert root.startswith(base_path)
90
# Get just the path below bzrlib
115
# Get just the path below breezy
91
116
package_path = root[len(base_path):]
92
117
# Remove leading and trailing slashes
93
118
package_path = package_path.strip('\\/')
94
119
if not package_path:
95
package_name = 'bzrlib'
120
package_name = 'breezy'
97
package_name = ('bzrlib.' +
98
package_path.replace('/', '.').replace('\\', '.'))
124
package_path.replace('/', '.').replace('\\', '.'))
99
125
packages.append(package_name)
100
126
return sorted(packages)
103
BZRLIB['packages'] = get_bzrlib_packages()
106
from distutils import log
107
from distutils.core import setup
129
BREEZY['packages'] = get_breezy_packages()
132
from setuptools import setup
108
133
from distutils.version import LooseVersion
109
134
from distutils.command.install_scripts import install_scripts
110
135
from distutils.command.install_data import install_data
126
151
scripts_dir = os.path.join(sys.prefix, 'Scripts')
127
152
script_path = self._quoted_path(os.path.join(scripts_dir,
129
154
python_exe = self._quoted_path(sys.executable)
130
args = self._win_batch_args()
131
batch_str = "@%s %s %s" % (python_exe, script_path, args)
132
batch_path = os.path.join(self.install_dir, "bzr.bat")
133
f = file(batch_path, "w")
136
print("Created: %s" % batch_path)
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:
159
print(("Created: %s" % batch_path))
137
160
except Exception:
138
161
e = sys.exc_info()[1]
139
print("ERROR: Unable to create %s: %s" % (batch_path, e))
162
print(("ERROR: Unable to create %s: %s" % (batch_path, e)))
141
164
def _quoted_path(self, path):
143
166
return '"' + path + '"'
147
def _win_batch_args(self):
148
from bzrlib.win32utils import winver
149
if winver == 'Windows NT':
152
return '%1 %2 %3 %4 %5 %6 %7 %8 %9'
153
169
#/class my_install_scripts
156
172
class bzr_build(build):
157
173
"""Customized build distutils action.
161
177
sub_commands = build.sub_commands + [
162
('build_mo', lambda _: True),
178
('build_mo', lambda _: True),
168
184
from tools import generate_docs
169
generate_docs.main(argv=["bzr", "man"])
185
generate_docs.main(argv=["brz", "man"])
172
188
########################
174
190
########################
176
from bzrlib.bzr_distutils import build_mo
192
from breezy.bzr_distutils import build_mo
178
194
command_classes = {'install_scripts': my_install_scripts,
179
195
'build': bzr_build,
184
200
from distutils.extension import Extension
188
from Cython.Distutils import build_ext
189
from Cython.Compiler.Version import version as pyrex_version
191
print("No Cython, trying Pyrex...")
192
from Pyrex.Distutils import build_ext
193
from Pyrex.Compiler.Version import version as pyrex_version
203
from Cython.Distutils import build_ext
204
from Cython.Compiler.Version import version as cython_version
194
205
except ImportError:
196
207
# try to build the extension from the prior generated source.
198
print("The python package 'Pyrex' is not available."
209
print("The python package 'Cython' is not available."
199
210
" If the .c files are available,")
200
211
print("they will be built,"
201
212
" but modifying the .pyx files will not rebuild them.")
203
214
from distutils.command.build_ext import build_ext
206
pyrex_version_info = LooseVersion(pyrex_version)
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.")
209
229
class build_ext_if_possible(build_ext):
250
# Override the build_ext if we have Pyrex available
270
# Override the build_ext if we have Cython available
251
271
command_classes['build_ext'] = build_ext_if_possible
252
272
unavailable_files = []
255
def add_pyrex_extension(module_name, libraries=None, extra_source=[]):
256
"""Add a pyrex module to build.
275
def add_cython_extension(module_name, libraries=None, extra_source=[]):
276
"""Add a cython module to build.
258
This will use Pyrex to auto-generate the .c file if it is available.
278
This will use Cython to auto-generate the .c file if it is available.
259
279
Otherwise it will fall back on the .c file. If the .c file is not
260
280
available, it will warn, and not add anything.
266
286
determine the .pyx and .c files to use.
268
288
path = module_name.replace('.', '/')
269
pyrex_name = path + '.pyx'
289
cython_name = path + '.pyx'
270
290
c_name = path + '.c'
271
291
define_macros = []
272
292
if sys.platform == 'win32':
273
# pyrex uses the macro WIN32 to detect the platform, even though it
293
# cython uses the macro WIN32 to detect the platform, even though it
274
294
# should be using something like _WIN32 or MS_WINDOWS, oh well, we can
275
295
# give it the right value.
276
296
define_macros.append(('WIN32', None))
278
source = [pyrex_name]
298
source = [cython_name]
280
300
if not os.path.isfile(c_name):
281
301
unavailable_files.append(c_name)
284
304
source = [c_name]
285
305
source.extend(extra_source)
286
ext_modules.append(Extension(module_name, source,
287
define_macros=define_macros, libraries=libraries))
290
add_pyrex_extension('bzrlib._annotator_pyx')
291
add_pyrex_extension('bzrlib._bencode_pyx')
292
add_pyrex_extension('bzrlib._chunks_to_lines_pyx')
293
add_pyrex_extension('bzrlib._groupcompress_pyx',
294
extra_source=['bzrlib/diff-delta.c'])
295
add_pyrex_extension('bzrlib._knit_load_data_pyx')
296
add_pyrex_extension('bzrlib._known_graph_pyx')
297
add_pyrex_extension('bzrlib._rio_pyx')
306
include_dirs = ['breezy']
309
module_name, source, define_macros=define_macros,
310
libraries=libraries, include_dirs=include_dirs))
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')
298
324
if sys.platform == 'win32':
299
add_pyrex_extension('bzrlib._dirstate_helpers_pyx',
300
libraries=['Ws2_32'])
301
add_pyrex_extension('bzrlib._walkdirs_win32')
303
if have_pyrex and pyrex_version_info == LooseVersion("0.9.4.1"):
304
# Pyrex 0.9.4.1 fails to compile this extension correctly
305
# The code it generates re-uses a "local" pointer and
306
# calls "PY_DECREF" after having set it to NULL. (It mixes PY_XDECREF
307
# which is NULL safe with PY_DECREF which is not.)
308
# <https://bugs.launchpad.net/bzr/+bug/449372>
309
# <https://bugs.launchpad.net/bzr/+bug/276868>
310
print('Cannot build extension "bzrlib._dirstate_helpers_pyx" using')
311
print('your version of pyrex "%s". Please upgrade your pyrex'
313
print('install. For now, the non-compiled (python) version will')
314
print('be used instead.')
316
add_pyrex_extension('bzrlib._dirstate_helpers_pyx')
317
add_pyrex_extension('bzrlib._readdir_pyx')
318
add_pyrex_extension('bzrlib._chk_map_pyx')
319
ext_modules.append(Extension('bzrlib._patiencediff_c',
320
['bzrlib/_patiencediff_c.c']))
321
if have_pyrex and pyrex_version_info < LooseVersion("0.9.6.3"):
323
print('Your Pyrex/Cython version %s is too old to build the simple_set' % (
325
print('and static_tuple extensions.')
326
print('Please upgrade to at least Pyrex 0.9.6.3')
328
# TODO: Should this be a fatal error?
330
# We only need 0.9.6.3 to build _simple_set_pyx, but static_tuple depends
332
add_pyrex_extension('bzrlib._simple_set_pyx')
333
ext_modules.append(Extension('bzrlib._static_tuple_c',
334
['bzrlib/_static_tuple_c.c']))
335
add_pyrex_extension('bzrlib._btree_serializer_pyx')
325
add_cython_extension('breezy.bzr._dirstate_helpers_pyx',
326
libraries=['Ws2_32'])
327
add_cython_extension('breezy._walkdirs_win32')
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')
338
335
if unavailable_files:
339
336
print('C extension(s) not found:')
340
print(' %s' % ('\n '.join(unavailable_files),))
337
print((' %s' % ('\n '.join(unavailable_files),)))
341
338
print('The python versions will be used instead.')
362
359
# TBZR points to the TBZR directory
363
360
tbzr_root = os.environ["TBZR"]
365
# Ensure tbzrlib itself is on sys.path
362
# Ensure tbreezy itself is on sys.path
366
363
sys.path.append(tbzr_root)
368
packages.append("tbzrlib")
365
packages.append("tbreezy")
370
367
# collect up our icons.
371
368
cwd = os.getcwd()
372
ico_root = os.path.join(tbzr_root, 'tbzrlib', 'resources')
369
ico_root = os.path.join(tbzr_root, 'tbreezy', 'resources')
373
370
icos = [] # list of (path_root, relative_ico_path)
374
# First always bzr's icon and its in the root of the bzr tree.
375
icos.append(('', 'bzr.ico'))
371
# First always brz's icon and its in the root of the brz tree.
372
icos.append(('', 'brz.ico'))
376
373
for root, dirs, files in os.walk(ico_root):
377
icos.extend([(ico_root, os.path.join(root, f)[len(ico_root)+1:])
374
icos.extend([(ico_root, os.path.join(root, f)[len(ico_root) + 1:])
378
375
for f in files if f.endswith('.ico')])
379
376
# allocate an icon ID for each file and the full path to the ico
380
377
icon_resources = [(rid, os.path.join(ico_dir, ico_name))
395
392
# tbzrcache executables - a "console" version for debugging and a
396
393
# GUI version that is generally used.
397
394
tbzrcache = dict(
398
script = os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
399
icon_resources = icon_resources,
400
other_resources = other_resources,
395
script=os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
396
icon_resources=icon_resources,
397
other_resources=other_resources,
402
399
console_targets.append(tbzrcache)
404
401
# Make a windows version which is the same except for the base name.
405
402
tbzrcachew = tbzrcache.copy()
406
tbzrcachew["dest_base"]="tbzrcachew"
403
tbzrcachew["dest_base"] = "tbzrcachew"
407
404
gui_targets.append(tbzrcachew)
409
406
# ditto for the tbzrcommand tool
410
407
tbzrcommand = dict(
411
script = os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
412
icon_resources = icon_resources,
413
other_resources = other_resources,
408
script=os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
409
icon_resources=icon_resources,
410
other_resources=other_resources,
415
412
console_targets.append(tbzrcommand)
416
413
tbzrcommandw = tbzrcommand.copy()
417
tbzrcommandw["dest_base"]="tbzrcommandw"
414
tbzrcommandw["dest_base"] = "tbzrcommandw"
418
415
gui_targets.append(tbzrcommandw)
420
417
# A utility to see python output from both C++ and Python based shell
422
419
tracer = dict(script=os.path.join(tbzr_root, "scripts", "tbzrtrace.py"))
500
497
for root, dirs, files in os.walk('doc'):
503
if (os.path.splitext(f)[1] in ('.html','.css','.png','.pdf')
504
or f == 'quick-start-summary.svg'):
500
if (os.path.splitext(f)[1] in ('.html', '.css', '.png', '.pdf')
501
or f == 'quick-start-summary.svg'):
505
502
r.append(os.path.join(root, f))
507
504
relative = root[4:]
509
target = os.path.join('Doc\\Bazaar', relative)
506
target = os.path.join('Doc\\Breezy', relative)
511
target = 'Doc\\Bazaar'
508
target = 'Doc\\Breezy'
512
509
docs.append((target, r))
515
512
# python's distutils-based win32 installer
516
ARGS = {'scripts': ['bzr', 'tools/win32/bzr-win32-bdist-postinstall.py'],
513
ARGS = {'scripts': ['brz', 'tools/win32/brz-win32-bdist-postinstall.py'],
517
514
'ext_modules': ext_modules,
519
516
'data_files': find_docs(),
520
# for building pyrex extensions
517
# for building cython extensions
521
518
'cmdclass': command_classes,
524
521
ARGS.update(META_INFO)
526
PKG_DATA['package_data']['bzrlib'].append('locale/*/LC_MESSAGES/*.mo')
523
PKG_DATA['package_data']['breezy'].append('locale/*/LC_MESSAGES/*.mo')
527
524
ARGS.update(PKG_DATA)
574
571
self.outfiles.extend([f + 'o' for f in compile_names])
575
572
# end of class install_data_with_bytecompile
577
target = py2exe.build_exe.Target(script = "bzr",
579
icon_resources = [(0,'bzr.ico')],
580
name = META_INFO['name'],
581
version = version_str,
582
description = META_INFO['description'],
583
author = META_INFO['author'],
584
copyright = "(c) Canonical Ltd, 2005-2010",
585
company_name = "Canonical Ltd.",
586
comments = META_INFO['description'],
574
target = py2exe.build_exe.Target(
577
icon_resources=[(0, 'brz.ico')],
578
name=META_INFO['name'],
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'],
588
586
gui_target = copy.copy(target)
589
587
gui_target.dest_base = "bzrw"
591
packages = BZRLIB['packages']
592
packages.remove('bzrlib')
593
packages = [i for i in packages if not i.startswith('bzrlib.plugins')]
589
packages = BREEZY['packages']
590
packages.remove('breezy')
591
packages = [i for i in packages if not i.startswith('breezy.plugins')]
595
for i in glob.glob('bzrlib\\*.py'):
593
for i in glob.glob('breezy\\*.py'):
596
594
module = i[:-3].replace('\\', '.')
597
595
if module.endswith('__init__'):
598
596
module = module[:-len('__init__')]
599
597
includes.append(module)
601
599
additional_packages = set()
602
if sys.version.startswith('2.4'):
603
# adding elementtree package
604
additional_packages.add('elementtree')
605
elif sys.version.startswith('2.6') or sys.version.startswith('2.5'):
606
additional_packages.add('xml.etree')
609
warnings.warn('Unknown Python version.\n'
610
'Please check setup.py script for compatibility.')
612
601
# Although we currently can't enforce it, we consider it an error for
613
602
# py2exe to report any files are "missing". Such modules we know aren't
660
648
ext = os.path.splitext(i)[1]
661
649
if ext.endswith('~') or ext in [".pyc", ".swp"]:
663
if i == '__init__.py' and root == 'bzrlib/plugins':
651
if i == '__init__.py' and root == 'breezy/plugins':
665
653
x.append(os.path.join(root, i))
667
target_dir = root[len('bzrlib/'):] # install to 'plugins/...'
655
target_dir = root[len('breezy/'):] # install to 'plugins/...'
668
656
plugins_files.append((target_dir, x))
669
657
# find modules for built-in plugins
670
658
import tools.package_mf
671
659
mf = tools.package_mf.CustomModuleFinder()
672
mf.run_package('bzrlib/plugins')
660
mf.run_package('breezy/plugins')
673
661
packs, mods = mf.get_result()
674
662
additional_packages.update(packs)
675
663
includes.extend(mods)
761
749
# ad-hoc for easy_install
763
if not 'bdist_egg' in sys.argv:
764
# generate and install bzr.1 only with plain install, not the
751
if 'bdist_egg' not in sys.argv:
752
# generate and install brz.1 only with plain install, not the
765
753
# easy_install one
766
DATA_FILES = [('man/man1', ['bzr.1'])]
754
DATA_FILES = [('man/man1', ['brz.1', 'breezy/git/git-remote-bzr.1'])]
768
756
DATA_FILES = DATA_FILES + I18N_FILES
770
ARGS = {'scripts': ['bzr'],
758
ARGS = {'scripts': ['brz',
759
# TODO(jelmer): Only install the git scripts if
761
'breezy/git/git-remote-bzr',
762
'breezy/git/bzr-receive-pack',
763
'breezy/git/bzr-upload-pack'],
771
764
'data_files': DATA_FILES,
772
765
'cmdclass': command_classes,
773
766
'ext_modules': ext_modules,
776
769
ARGS.update(META_INFO)
778
771
ARGS.update(PKG_DATA)
780
773
if __name__ == '__main__':