Open 0.4.12 for development.
[jelmer/subvertpy.git] / setup.py
1 #!/usr/bin/env python
2 # Setup file for bzr-svn
3 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
4
5 from distutils.core import setup
6 from distutils.extension import Extension
7 from distutils.command.install_lib import install_lib
8 from distutils import log
9 import sys
10 import os
11
12 # Build instructions for Windows:
13 # * Install the SVN dev kit ZIP for Windows from
14 #   http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91
15 #   At time of writing, this was svn-win32-1.4.6_dev.zip
16 # * Find the SVN binary ZIP file with the binaries for your dev kit.
17 #   At time of writing, this was svn-win32-1.4.6.zip
18 #   Unzip this in the *same directory* as the dev kit - README.txt will be
19 #   overwritten, but that is all. This is the default location the .ZIP file
20 #   will suggest (ie, the directory embedded in both .zip files are the same)
21 # * Set SVN_DEV to point at this directory.
22 # * Install the APR BDB and INTL packages - see README.txt from the devkit
23 # * Set SVN_BDB and SVN_LIBINTL to point at these dirs.
24 #
25 #  To install into a particular bzr location, use:
26 #  % python setup.py install --install-lib=c:\root\of\bazaar
27
28 class CommandException(Exception):
29     """Encapsulate exit status of apr-config execution"""
30     def __init__(self, msg, cmd, arg, status, val):
31         self.message = msg % (cmd, val)
32         Exception.__init__(self, self.message)
33         self.cmd = cmd
34         self.arg = arg
35         self.status = status
36     def not_found(self):
37         return os.WIFEXITED(self.status) and os.WEXITSTATUS(self.status) == 127
38
39
40 def run_cmd(cmd, arg):
41     """Run specified command with given arguments, handling status"""
42     f = os.popen("'%s' %s" % (cmd, arg))
43     dir = f.read().rstrip("\n")
44     status = f.close()
45     if status is None:
46         return dir
47     if os.WIFEXITED(status):
48         code = os.WEXITSTATUS(status)
49         if code == 0:
50             return dir
51         raise CommandException("%s exited with status %d",
52                                cmd, arg, status, code)
53     if os.WIFSIGNALED(status):
54         signal = os.WTERMSIG(status)
55         raise CommandException("%s killed by signal %d",
56                                cmd, arg, status, signal)
57     raise CommandException("%s terminated abnormally (%d)",
58                            cmd, arg, status, status)
59
60
61 def apr_config(arg):
62     apr_config_cmd = os.getenv("APR_CONFIG")
63     if apr_config_cmd is None:
64         cmds = ["apr-config", "apr-1-config", "/usr/local/apr/bin/apr-config",
65                 "/usr/local/apr/bin/apr-1-config", 
66                 "/opt/local/bin/apr-1-config",
67                 "/usr/local/bin/apr-config", ]
68         for cmd in cmds:
69             try:
70                 res = run_cmd(cmd, arg)
71                 apr_config_cmd = cmd
72                 break
73             except CommandException, e:
74                 if not e.not_found():
75                     raise
76         else:
77             raise Exception("apr-config not found."
78                             " Please set APR_CONFIG environment variable")
79     else:
80         res = run_cmd(apr_config_cmd, arg)
81     return res
82
83
84 def apr_build_data():
85     """Determine the APR header file location."""
86     includedir = apr_config("--includedir")
87     if not os.path.isdir(includedir):
88         raise Exception("APR development headers not found")
89     ldflags = filter(lambda x: x != "", apr_config("--link-ld").split(" "))
90     return (includedir, ldflags)
91
92
93 def svn_build_data():
94     """Determine the Subversion header file location."""
95     if "SVN_HEADER_PATH" in os.environ and "SVN_LIBRARY_PATH" in os.environ:
96         return ([os.getenv("SVN_HEADER_PATH")], [os.getenv("SVN_LIBRARY_PATH")], [])
97     svn_prefix = os.getenv("SVN_PREFIX")
98     if svn_prefix is None:
99         basedirs = ["/usr/local", "/usr"]
100         for basedir in basedirs:
101             includedir = os.path.join(basedir, "include/subversion-1")
102             if os.path.isdir(includedir):
103                 svn_prefix = basedir
104                 break
105     if svn_prefix is not None:
106         return ([os.path.join(svn_prefix, "include/subversion-1")], 
107                 [os.path.join(svn_prefix, "lib")], [])
108     raise Exception("Subversion development files not found. "
109                     "Please set SVN_PREFIX or (SVN_LIBRARY_PATH and SVN_HEADER_PATH) environment variable. ")
110
111 # Windows versions - we use environment variables to locate the directories
112 # and hard-code a list of libraries.
113 if os.name == "nt":
114     # just clobber the functions above we can't use
115     # for simplicitly, everything is done in the 'svn' one
116     def apr_build_data():
117         return '.', ''
118
119     def svn_build_data():
120         # environment vars for the directories we need.
121         svn_dev_dir = os.environ.get("SVN_DEV")
122         if not svn_dev_dir or not os.path.isdir(svn_dev_dir):
123             raise Exception(
124                 "Please set SVN_DEV to the location of the svn development "
125                 "packages.\nThese can be downloaded from:\n"
126                 "http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91")
127         svn_bdb_dir = os.environ.get("SVN_BDB")
128         if not svn_bdb_dir or not os.path.isdir(svn_bdb_dir):
129             raise Exception(
130                 "Please set SVN_BDB to the location of the svn BDB packages "
131                 "- see README.txt in the SV_DEV dir")
132         svn_libintl_dir = os.environ.get("SVN_LIBINTL")
133         if not svn_libintl_dir or not os.path.isdir(svn_libintl_dir):
134             raise Exception(
135                 "Please set SVN_LIBINTL to the location of the svn libintl "
136                 "packages - see README.txt in the SV_DEV dir")
137
138         includes = [
139             # apr dirs.
140             os.path.join(svn_dev_dir, r"include\apr"),
141             os.path.join(svn_dev_dir, r"include\apr-utils"),
142             os.path.join(svn_dev_dir, r"include\apr-iconv"),
143             # svn dirs.
144             os.path.join(svn_dev_dir, "include"), 
145         ]
146         lib_dirs = [
147             os.path.join(svn_dev_dir, "lib"),
148             os.path.join(svn_dev_dir, "lib", "apr"),
149             os.path.join(svn_dev_dir, "lib", "apr-iconv"),
150             os.path.join(svn_dev_dir, "lib", "apr-util"),
151             os.path.join(svn_dev_dir, "lib", "neon"),
152             os.path.join(svn_bdb_dir, "lib"),
153             os.path.join(svn_libintl_dir, "lib"),
154         ]
155         libs = """libapr libapriconv libaprutil libneon
156                   libsvn_subr-1 libsvn_client-1 libsvn_ra-1
157                   libsvn_ra_dav-1 libsvn_ra_local-1 libsvn_ra_svn-1
158                   libsvn_repos-1 libsvn_wc-1 libsvn_delta-1 libsvn_diff-1
159                   libsvn_fs-1 libsvn_repos-1 libsvn_fs_fs-1 libsvn_fs_base-1
160                   intl3_svn
161                   libdb44 xml
162                   advapi32 shell32 ws2_32 zlibstat
163                """.split()
164
165         return includes, lib_dirs, libs,
166
167 (apr_includedir, apr_ldflags) = apr_build_data()
168 (svn_includedirs, svn_libdirs, extra_libs) = svn_build_data()
169
170 def SvnExtension(name, *args, **kwargs):
171     kwargs["include_dirs"] = [apr_includedir] + svn_includedirs
172     kwargs["library_dirs"] = svn_libdirs
173     kwargs["extra_link_args"] = apr_ldflags
174     if os.name == 'nt':
175         # on windows, just ignore and overwrite the libraries!
176         kwargs["libraries"] = extra_libs
177         # APR needs WIN32 defined.
178         kwargs["define_macros"] = [("WIN32", None)]
179     return Extension("bzrlib.plugins.svn.%s" % name, *args, **kwargs)
180
181
182 # On Windows, we install the apr binaries too.
183 class install_lib_with_dlls(install_lib):
184     def _get_dlls(self):
185         # return a list of of (FQ-in-name, relative-out-name) tuples.
186         ret = []
187         apr_bins = """libaprutil.dll libapriconv.dll libapr.dll intl3_svn.dll
188                       libdb44.dll libeay32.dll ssleay32.dll""".split()
189         look_dirs = os.environ.get("PATH","").split(os.pathsep)
190         look_dirs.insert(0, os.path.join(os.environ["SVN_DEV"], "bin"))
191     
192         for bin in apr_bins:
193             for look in look_dirs:
194                 f = os.path.join(look, bin)
195                 if os.path.isfile(f):
196                     target = os.path.join(self.install_dir, "bzrlib",
197                                           "plugins", "svn", bin)
198                     ret.append((f, target))
199                     break
200             else:
201                 log.warn("Could not find required DLL %r to include", bin)
202                 log.debug("(looked in %s)", look_dirs)
203         return ret
204
205     def run(self):
206         install_lib.run(self)
207         # the apr binaries.
208         if os.name == 'nt':
209             # On Windows we package up the apr dlls with the plugin.
210             for s, d in self._get_dlls():
211                 self.copy_file(s, d)
212
213     def get_outputs(self):
214         ret = install_lib.get_outputs()
215         if os.name == 'nt':
216             ret.extend([info[1] for info in self._get_dlls()])
217         return ret
218
219 setup(name='bzr-svn',
220       description='Support for Subversion branches in Bazaar',
221       keywords='plugin bzr svn',
222       version='0.4.12',
223       url='http://bazaar-vcs.org/BzrForeignBranches/Subversion',
224       download_url='http://bazaar-vcs.org/BzrSvn',
225       license='GPL',
226       author='Jelmer Vernooij',
227       author_email='jelmer@samba.org',
228       long_description="""
229       This plugin adds support for branching off and 
230       committing to Subversion repositories from 
231       Bazaar.
232       """,
233       package_dir={'bzrlib.plugins.svn':'.', 
234                    'bzrlib.plugins.svn.tests':'tests'},
235       packages=['bzrlib.plugins.svn', 
236                 'bzrlib.plugins.svn.mapping3', 
237                 'bzrlib.plugins.svn.tests'],
238       ext_modules=[
239           SvnExtension("client", ["client.c", "editor.c", "util.c", "ra.c", "wc.c"], libraries=["svn_client-1", "svn_subr-1"]), 
240           SvnExtension("ra", ["ra.c", "util.c", "editor.c"], libraries=["svn_ra-1", "svn_delta-1", "svn_subr-1"]),
241           SvnExtension("repos", ["repos.c", "util.c"], libraries=["svn_repos-1", "svn_subr-1"]),
242           SvnExtension("wc", ["wc.c", "util.c", "editor.c"], libraries=["svn_wc-1", "svn_subr-1"]),
243           ],
244       cmdclass = { 'install_lib': install_lib_with_dlls },
245       )