15
if sys.version_info < (3, 5):
16
sys.stderr.write("[ERROR] Not a supported Python version. Need 3.5+\n")
23
sys.stderr.write("[ERROR] Please install setuptools\n")
15
if sys.version_info < (2, 6):
16
sys.stderr.write("[ERROR] Not a supported Python version. Need 2.6+\n")
27
19
# NOTE: The directory containing setup.py, whether run by 'python setup.py' or
28
20
# './setup.py' or the equivalent with another path, should always be at the
29
21
# start of the path, so this should find the right one...
32
24
def get_long_description():
33
25
dirname = os.path.dirname(__file__)
34
readme = os.path.join(dirname, 'README.rst')
35
with open(readme, 'r') as f:
26
readme = os.path.join(dirname, 'README')
27
f = open(readme, 'rb')
40
35
# META INFORMATION FOR SETUP
41
36
# see http://docs.python.org/dist/meta-data.html
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',
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',
51
46
'long_description': get_long_description(),
53
48
'Development Status :: 6 - Mature',
62
57
'Programming Language :: C',
63
58
'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
62
# The list of packages is automatically generated later. Add other things
87
# that are part of BREEZY here.
63
# that are part of BZRLIB 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',
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',
102
for filepath in glob.glob("breezy/locale/*/LC_MESSAGES/*.mo"):
103
langfile = filepath[len("breezy/locale/"):]
77
for filepath in glob.glob("bzrlib/locale/*/LC_MESSAGES/*.mo"):
78
langfile = filepath[len("bzrlib/locale/"):]
104
79
targetpath = os.path.dirname(os.path.join("share/locale", langfile))
105
80
I18N_FILES.append((targetpath, [filepath]))
107
def get_breezy_packages():
108
"""Recurse through the breezy directory, and extract the package names"""
82
def get_bzrlib_packages():
83
"""Recurse through the bzrlib directory, and extract the package names"""
111
base_path = os.path.dirname(os.path.abspath(breezy.__file__))
86
base_path = os.path.dirname(os.path.abspath(bzrlib.__file__))
112
87
for root, dirs, files in os.walk(base_path):
113
88
if '__init__.py' in files:
114
89
assert root.startswith(base_path)
115
# Get just the path below breezy
90
# Get just the path below bzrlib
116
91
package_path = root[len(base_path):]
117
92
# Remove leading and trailing slashes
118
93
package_path = package_path.strip('\\/')
119
94
if not package_path:
120
package_name = 'breezy'
95
package_name = 'bzrlib'
124
package_path.replace('/', '.').replace('\\', '.'))
97
package_name = ('bzrlib.' +
98
package_path.replace('/', '.').replace('\\', '.'))
125
99
packages.append(package_name)
126
100
return sorted(packages)
129
BREEZY['packages'] = get_breezy_packages()
132
from setuptools import setup
103
BZRLIB['packages'] = get_bzrlib_packages()
106
from distutils import log
107
from distutils.core import setup
133
108
from distutils.version import LooseVersion
134
109
from distutils.command.install_scripts import install_scripts
135
110
from distutils.command.install_data import install_data
151
126
scripts_dir = os.path.join(sys.prefix, 'Scripts')
152
127
script_path = self._quoted_path(os.path.join(scripts_dir,
154
129
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:
159
print(("Created: %s" % batch_path))
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)
160
137
except Exception:
161
138
e = sys.exc_info()[1]
162
print(("ERROR: Unable to create %s: %s" % (batch_path, e)))
139
print("ERROR: Unable to create %s: %s" % (batch_path, e))
164
141
def _quoted_path(self, path):
166
143
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'
169
153
#/class my_install_scripts
172
156
class bzr_build(build):
173
157
"""Customized build distutils action.
177
161
sub_commands = build.sub_commands + [
178
('build_mo', lambda _: True),
162
('build_mo', lambda _: True),
184
168
from tools import generate_docs
185
generate_docs.main(argv=["brz", "man"])
169
generate_docs.main(argv=["bzr", "man"])
188
172
########################
190
174
########################
192
from breezy.bzr_distutils import build_mo
176
from bzrlib.bzr_distutils import build_mo
194
178
command_classes = {'install_scripts': my_install_scripts,
195
179
'build': bzr_build,
200
184
from distutils.extension import Extension
203
from Cython.Distutils import build_ext
204
from Cython.Compiler.Version import version as cython_version
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
205
194
except ImportError:
207
196
# try to build the extension from the prior generated source.
209
print("The python package 'Cython' is not available."
198
print("The python package 'Pyrex' is not available."
210
199
" If the .c files are available,")
211
200
print("they will be built,"
212
201
" but modifying the .pyx files will not rebuild them.")
214
203
from distutils.command.build_ext import build_ext
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.")
206
pyrex_version_info = LooseVersion(pyrex_version)
229
209
class build_ext_if_possible(build_ext):
270
# Override the build_ext if we have Cython available
250
# Override the build_ext if we have Pyrex available
271
251
command_classes['build_ext'] = build_ext_if_possible
272
252
unavailable_files = []
275
def add_cython_extension(module_name, libraries=None, extra_source=[]):
276
"""Add a cython module to build.
255
def add_pyrex_extension(module_name, libraries=None, extra_source=[]):
256
"""Add a pyrex module to build.
278
This will use Cython to auto-generate the .c file if it is available.
258
This will use Pyrex to auto-generate the .c file if it is available.
279
259
Otherwise it will fall back on the .c file. If the .c file is not
280
260
available, it will warn, and not add anything.
286
266
determine the .pyx and .c files to use.
288
268
path = module_name.replace('.', '/')
289
cython_name = path + '.pyx'
269
pyrex_name = path + '.pyx'
290
270
c_name = path + '.c'
291
271
define_macros = []
292
272
if sys.platform == 'win32':
293
# cython uses the macro WIN32 to detect the platform, even though it
273
# pyrex uses the macro WIN32 to detect the platform, even though it
294
274
# should be using something like _WIN32 or MS_WINDOWS, oh well, we can
295
275
# give it the right value.
296
276
define_macros.append(('WIN32', None))
298
source = [cython_name]
278
source = [pyrex_name]
300
280
if not os.path.isfile(c_name):
301
281
unavailable_files.append(c_name)
304
284
source = [c_name]
305
285
source.extend(extra_source)
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')
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')
324
298
if sys.platform == 'win32':
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')
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')
335
338
if unavailable_files:
336
339
print('C extension(s) not found:')
337
print((' %s' % ('\n '.join(unavailable_files),)))
340
print(' %s' % ('\n '.join(unavailable_files),))
338
341
print('The python versions will be used instead.')
359
362
# TBZR points to the TBZR directory
360
363
tbzr_root = os.environ["TBZR"]
362
# Ensure tbreezy itself is on sys.path
365
# Ensure tbzrlib itself is on sys.path
363
366
sys.path.append(tbzr_root)
365
packages.append("tbreezy")
368
packages.append("tbzrlib")
367
370
# collect up our icons.
368
371
cwd = os.getcwd()
369
ico_root = os.path.join(tbzr_root, 'tbreezy', 'resources')
372
ico_root = os.path.join(tbzr_root, 'tbzrlib', 'resources')
370
373
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'))
374
# First always bzr's icon and its in the root of the bzr tree.
375
icos.append(('', 'bzr.ico'))
373
376
for root, dirs, files in os.walk(ico_root):
374
icos.extend([(ico_root, os.path.join(root, f)[len(ico_root) + 1:])
377
icos.extend([(ico_root, os.path.join(root, f)[len(ico_root)+1:])
375
378
for f in files if f.endswith('.ico')])
376
379
# allocate an icon ID for each file and the full path to the ico
377
380
icon_resources = [(rid, os.path.join(ico_dir, ico_name))
392
395
# tbzrcache executables - a "console" version for debugging and a
393
396
# GUI version that is generally used.
394
397
tbzrcache = dict(
395
script=os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
396
icon_resources=icon_resources,
397
other_resources=other_resources,
398
script = os.path.join(tbzr_root, "scripts", "tbzrcache.py"),
399
icon_resources = icon_resources,
400
other_resources = other_resources,
399
402
console_targets.append(tbzrcache)
401
404
# Make a windows version which is the same except for the base name.
402
405
tbzrcachew = tbzrcache.copy()
403
tbzrcachew["dest_base"] = "tbzrcachew"
406
tbzrcachew["dest_base"]="tbzrcachew"
404
407
gui_targets.append(tbzrcachew)
406
409
# ditto for the tbzrcommand tool
407
410
tbzrcommand = dict(
408
script=os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
409
icon_resources=icon_resources,
410
other_resources=other_resources,
411
script = os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
412
icon_resources = icon_resources,
413
other_resources = other_resources,
412
415
console_targets.append(tbzrcommand)
413
416
tbzrcommandw = tbzrcommand.copy()
414
tbzrcommandw["dest_base"] = "tbzrcommandw"
417
tbzrcommandw["dest_base"]="tbzrcommandw"
415
418
gui_targets.append(tbzrcommandw)
417
420
# A utility to see python output from both C++ and Python based shell
419
422
tracer = dict(script=os.path.join(tbzr_root, "scripts", "tbzrtrace.py"))
497
500
for root, dirs, files in os.walk('doc'):
500
if (os.path.splitext(f)[1] in ('.html', '.css', '.png', '.pdf')
501
or f == 'quick-start-summary.svg'):
503
if (os.path.splitext(f)[1] in ('.html','.css','.png','.pdf')
504
or f == 'quick-start-summary.svg'):
502
505
r.append(os.path.join(root, f))
504
507
relative = root[4:]
506
target = os.path.join('Doc\\Breezy', relative)
509
target = os.path.join('Doc\\Bazaar', relative)
508
target = 'Doc\\Breezy'
511
target = 'Doc\\Bazaar'
509
512
docs.append((target, r))
512
515
# python's distutils-based win32 installer
513
ARGS = {'scripts': ['brz', 'tools/win32/brz-win32-bdist-postinstall.py'],
516
ARGS = {'scripts': ['bzr', 'tools/win32/bzr-win32-bdist-postinstall.py'],
514
517
'ext_modules': ext_modules,
516
519
'data_files': find_docs(),
517
# for building cython extensions
520
# for building pyrex extensions
518
521
'cmdclass': command_classes,
521
524
ARGS.update(META_INFO)
523
PKG_DATA['package_data']['breezy'].append('locale/*/LC_MESSAGES/*.mo')
526
PKG_DATA['package_data']['bzrlib'].append('locale/*/LC_MESSAGES/*.mo')
524
527
ARGS.update(PKG_DATA)
571
574
self.outfiles.extend([f + 'o' for f in compile_names])
572
575
# end of class install_data_with_bytecompile
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'],
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'],
586
588
gui_target = copy.copy(target)
587
589
gui_target.dest_base = "bzrw"
589
packages = BREEZY['packages']
590
packages.remove('breezy')
591
packages = [i for i in packages if not i.startswith('breezy.plugins')]
591
packages = BZRLIB['packages']
592
packages.remove('bzrlib')
593
packages = [i for i in packages if not i.startswith('bzrlib.plugins')]
593
for i in glob.glob('breezy\\*.py'):
595
for i in glob.glob('bzrlib\\*.py'):
594
596
module = i[:-3].replace('\\', '.')
595
597
if module.endswith('__init__'):
596
598
module = module[:-len('__init__')]
597
599
includes.append(module)
599
601
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.')
601
612
# Although we currently can't enforce it, we consider it an error for
602
613
# py2exe to report any files are "missing". Such modules we know aren't
648
660
ext = os.path.splitext(i)[1]
649
661
if ext.endswith('~') or ext in [".pyc", ".swp"]:
651
if i == '__init__.py' and root == 'breezy/plugins':
663
if i == '__init__.py' and root == 'bzrlib/plugins':
653
665
x.append(os.path.join(root, i))
655
target_dir = root[len('breezy/'):] # install to 'plugins/...'
667
target_dir = root[len('bzrlib/'):] # install to 'plugins/...'
656
668
plugins_files.append((target_dir, x))
657
669
# find modules for built-in plugins
658
670
import tools.package_mf
659
671
mf = tools.package_mf.CustomModuleFinder()
660
mf.run_package('breezy/plugins')
672
mf.run_package('bzrlib/plugins')
661
673
packs, mods = mf.get_result()
662
674
additional_packages.update(packs)
663
675
includes.extend(mods)
749
761
# ad-hoc for easy_install
751
if 'bdist_egg' not in sys.argv:
752
# generate and install brz.1 only with plain install, not the
763
if not 'bdist_egg' in sys.argv:
764
# generate and install bzr.1 only with plain install, not the
753
765
# easy_install one
754
DATA_FILES = [('man/man1', ['brz.1', 'breezy/git/git-remote-bzr.1'])]
766
DATA_FILES = [('man/man1', ['bzr.1'])]
756
768
DATA_FILES = DATA_FILES + I18N_FILES
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'],
770
ARGS = {'scripts': ['bzr'],
764
771
'data_files': DATA_FILES,
765
772
'cmdclass': command_classes,
766
773
'ext_modules': ext_modules,
769
776
ARGS.update(META_INFO)
771
778
ARGS.update(PKG_DATA)
773
780
if __name__ == '__main__':