#!/usr/bin/env python
-# Setup file for bzr-svn
-# Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
+# Setup file for subvertpy
+# Copyright (C) 2005-2010 Jelmer Vernooij <jelmer@samba.org>
from distutils.core import setup
from distutils.extension import Extension
import os
import re
-# Build instructions for Windows:
-# * Install the SVN dev kit ZIP for Windows from
-# http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91
-# At time of writing, this was svn-win32-1.4.6_dev.zip
-# * Find the SVN binary ZIP file with the binaries for your dev kit.
-# At time of writing, this was svn-win32-1.4.6.zip
-# Unzip this in the *same directory* as the dev kit - README.txt will be
-# overwritten, but that is all. This is the default location the .ZIP file
-# will suggest (ie, the directory embedded in both .zip files are the same)
-# * Set SVN_DEV to point at this directory.
-# * Install the APR BDB and INTL packages - see README.txt from the devkit
-# * Set SVN_BDB and SVN_LIBINTL to point at these dirs.
-#
-# To install into a particular bzr location, use:
-# % python setup.py install --install-lib=c:\root\of\bazaar
-
class CommandException(Exception):
- """Encapsulate exit status of apr-config execution"""
+ """Encapsulate exit status of command execution"""
def __init__(self, msg, cmd, arg, status, val):
self.message = msg % (cmd, val)
Exception.__init__(self, self.message)
return os.WIFEXITED(self.status) and os.WEXITSTATUS(self.status) == 127
+def split_shell_results(line):
+ return [s for s in line.split(" ") if s != ""]
+
+
def run_cmd(cmd, arg):
"""Run specified command with given arguments, handling status"""
f = os.popen("'%s' %s" % (cmd, arg))
cmd, arg, status, status)
+def config_value(command, arg):
+ cmds = [command] + [os.path.join(p, command) for p in ["/usr/local/apr/bin/", "/opt/local/bin/"]]
+ for cmd in cmds:
+ try:
+ return run_cmd(cmd, arg)
+ except CommandException, e:
+ if not e.not_found():
+ raise
+ else:
+ raise Exception("apr-config not found."
+ " Please set APR_CONFIG environment variable")
+
+
def apr_config(arg):
- apr_config_cmd = os.getenv("APR_CONFIG")
- if apr_config_cmd is None:
- cmds = ["apr-1-config", "/usr/local/apr/bin/apr-1-config",
- "/opt/local/bin/apr-1-config", ]
- for cmd in cmds:
- try:
- res = run_cmd(cmd, arg)
- apr_config_cmd = cmd
- break
- except CommandException, e:
- if not e.not_found():
- raise
- else:
- raise Exception("apr-config not found."
- " Please set APR_CONFIG environment variable")
+ config_cmd = os.getenv("APR_CONFIG")
+ if config_cmd is None:
+ return config_value("apr-1-config", arg)
+ else:
+ return run_cmd(config_cmd, arg)
+
+
+def apu_config(arg):
+ config_cmd = os.getenv("APU_CONFIG")
+ if config_cmd is None:
+ return config_value("apu-1-config", arg)
else:
- res = run_cmd(apr_config_cmd, arg)
- return res
+ return run_cmd(config_cmd, arg)
def apr_build_data():
includedir = apr_config("--includedir")
if not os.path.isdir(includedir):
raise Exception("APR development headers not found")
- return (includedir,)
+ extra_link_flags = apr_config("--link-ld --libs")
+ return (includedir, split_shell_results(extra_link_flags))
+
+
+def apu_build_data():
+ """Determine the APR util header file location."""
+ includedir = apu_config("--includedir")
+ if not os.path.isdir(includedir):
+ raise Exception("APR util development headers not found")
+ extra_link_flags = apu_config("--link-ld --libs")
+ return (includedir, split_shell_results(extra_link_flags))
def svn_build_data():
"""Determine the Subversion header file location."""
if "SVN_HEADER_PATH" in os.environ and "SVN_LIBRARY_PATH" in os.environ:
- return ([os.getenv("SVN_HEADER_PATH")], [os.getenv("SVN_LIBRARY_PATH")], [])
+ return ([os.getenv("SVN_HEADER_PATH")], [os.getenv("SVN_LIBRARY_PATH")], [], [])
svn_prefix = os.getenv("SVN_PREFIX")
if svn_prefix is None:
basedirs = ["/usr/local", "/usr"]
break
if svn_prefix is not None:
return ([os.path.join(svn_prefix, "include/subversion-1")],
- [os.path.join(svn_prefix, "lib")], [])
+ [os.path.join(svn_prefix, "lib")], [], [])
raise Exception("Subversion development files not found. "
"Please set SVN_PREFIX or (SVN_LIBRARY_PATH and SVN_HEADER_PATH) environment variable. ")
+def is_keychain_provider_available():
+ """
+ Checks for the availability of the Keychain simple authentication provider in Subversion by compiling a simple test program.
+ """
+ abd = apr_build_data()
+ sbd = svn_build_data()
+ gcc_command_args = ['gcc'] + ['-I' + inc for inc in sbd[0]] + ['-L' + lib for lib in sbd[1]] + ['-I' + abd[0], '-lsvn_subr-1', '-x', 'c', '-']
+ (gcc_in, gcc_out, gcc_err) = os.popen3(gcc_command_args)
+ gcc_in.write("""
+#include <svn_auth.h>
+int main(int argc, const char* arv[]) {
+ svn_auth_get_keychain_simple_provider(NULL, NULL);
+}
+""")
+ gcc_in.close()
+ gcc_out.read()
+ return (gcc_out.close() is None)
+
+
class VersionQuery(object):
+
def __init__(self, filename):
self.filename = filename
f = file(filename, "rU")
def grep(self, what):
m = re.search(r"^#define\s+%s\s+(\d+)\s*$" % (what,), self.text, re.MULTILINE)
if not m:
- raise Exception, "Definition for %s was not found in file %s." % (what, self.filename)
+ raise Exception("Definition for %s was not found in file %s." % (what, self.filename))
return int(m.group(1))
# Windows versions - we use environment variables to locate the directories
# and hard-code a list of libraries.
if os.name == "nt":
def get_apr_version():
- apr_version_file = os.path.join(os.environ["SVN_DEV"], r"include\apr\apr_version.h")
+ apr_version_file = os.path.join(os.environ["SVN_DEV"],
+ r"include\apr\apr_version.h")
if not os.path.isfile(apr_version_file):
raise Exception(
"Please check that your SVN_DEV location is correct.\n"
"Unable to find required apr\\apr_version.h file.")
query = VersionQuery(apr_version_file)
- return query.grep("APR_MAJOR_VERSION"), query.grep("APR_MINOR_VERSION"), query.grep("APR_PATCH_VERSION")
+ return (query.grep("APR_MAJOR_VERSION"),
+ query.grep("APR_MINOR_VERSION"),
+ query.grep("APR_PATCH_VERSION"))
def get_svn_version():
svn_version_file = os.path.join(os.environ["SVN_DEV"], r"include\svn_version.h")
"Please check that your SVN_DEV location is correct.\n"
"Unable to find required svn_version.h file.")
query = VersionQuery(svn_version_file)
- return query.grep("SVN_VER_MAJOR"), query.grep("SVN_VER_MINOR"), query.grep("SVN_VER_PATCH")
+ return (query.grep("SVN_VER_MAJOR"),
+ query.grep("SVN_VER_MINOR"),
+ query.grep("SVN_VER_PATCH"))
# just clobber the functions above we can't use
# for simplicitly, everything is done in the 'svn' one
def apr_build_data():
- return '.',
+ return '.', []
+
+ def apu_build_data():
+ return '.', []
def svn_build_data():
# environment vars for the directories we need.
raise Exception(
"Please set SVN_DEV to the location of the svn development "
"packages.\nThese can be downloaded from:\n"
- "http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91")
+ "http://sourceforge.net/projects/win32svn/files/")
svn_bdb_dir = os.environ.get("SVN_BDB")
if not svn_bdb_dir or not os.path.isdir(svn_bdb_dir):
raise Exception(
"Please set SVN_BDB to the location of the svn BDB packages "
- "- see README.txt in the SV_DEV dir")
+ "- see README.txt in the SVN_DEV dir")
svn_libintl_dir = os.environ.get("SVN_LIBINTL")
if not svn_libintl_dir or not os.path.isdir(svn_libintl_dir):
raise Exception(
"Please set SVN_LIBINTL to the location of the svn libintl "
- "packages - see README.txt in the SV_DEV dir")
+ "packages - see README.txt in the SVN_DEV dir")
svn_version = get_svn_version()
apr_version = get_apr_version()
includes = [
# apr dirs.
os.path.join(svn_dev_dir, r"include\apr"),
- os.path.join(svn_dev_dir, r"include\apr-utils"),
+ os.path.join(svn_dev_dir, r"include\apr-util"),
os.path.join(svn_dev_dir, r"include\apr-iconv"),
# svn dirs.
os.path.join(svn_dev_dir, "include"),
# Since 1.5.0 libsvn_ra_dav-1 was removed
libs.remove("libsvn_ra_dav-1")
- return includes, lib_dirs, aprlibs+libs,
+ return includes, lib_dirs, [], aprlibs+libs,
-(apr_includedir, ) = apr_build_data()
-(svn_includedirs, svn_libdirs, extra_libs) = svn_build_data()
+(apr_includedir, apr_link_flags) = apr_build_data()
+(apu_includedir, apu_link_flags) = apu_build_data()
+(svn_includedirs, svn_libdirs, svn_link_flags, extra_libs) = svn_build_data()
-def SvnExtension(name, *args, **kwargs):
- kwargs["include_dirs"] = [apr_includedir] + svn_includedirs
- kwargs["library_dirs"] = svn_libdirs
- if os.name == 'nt':
- # on windows, just ignore and overwrite the libraries!
- kwargs["libraries"] = extra_libs
- # APR needs WIN32 defined.
- kwargs["define_macros"] = [("WIN32", None)]
- return Extension("bzrlib.plugins.svn.%s" % name, *args, **kwargs)
+class SvnExtension(Extension):
+
+ def __init__(self, name, *args, **kwargs):
+ kwargs["include_dirs"] = ([apr_includedir, apu_includedir] + svn_includedirs +
+ ["subvertpy"])
+ kwargs["library_dirs"] = svn_libdirs
+ # Note that the apr-util link flags are not included here, as
+ # subvertpy only uses some apr util constants but does not use
+ # the library directly.
+ kwargs["extra_link_args"] = apr_link_flags + svn_link_flags
+ if os.name == 'nt':
+ # on windows, just ignore and overwrite the libraries!
+ kwargs["libraries"] = extra_libs
+ # APR needs WIN32 defined.
+ kwargs["define_macros"] = [("WIN32", None)]
+ if sys.platform == 'darwin':
+ # on Mac OS X, we need to check for Keychain availability
+ if is_keychain_provider_available():
+ if "define_macros" not in kwargs:
+ kwargs["define_macros"] = []
+ kwargs["define_macros"].extend((
+ ('DARWIN', None),
+ ('SVN_KEYCHAIN_PROVIDER_AVAILABLE', '1'))
+ )
+ Extension.__init__(self, name, *args, **kwargs)
# On Windows, we install the apr binaries too.
def _get_dlls(self):
# return a list of of (FQ-in-name, relative-out-name) tuples.
ret = []
- apr_bins = [libname + ".dll" for libname in extra_libs if libname.startswith("libapr")]
+ apr_bins = [libname + ".dll" for libname in extra_libs
+ if libname.startswith("libapr")]
if get_svn_version() >= (1,5,0):
# Since 1.5.0 these libraries became shared
apr_bins += """libsvn_client-1.dll libsvn_delta-1.dll libsvn_diff-1.dll
for look in look_dirs:
f = os.path.join(look, bin)
if os.path.isfile(f):
- target = os.path.join(self.install_dir, "bzrlib",
- "plugins", "svn", bin)
+ target = os.path.join(self.install_dir, "subvertpy", bin)
ret.append((f, target))
break
else:
self.copy_file(s, d)
def get_outputs(self):
- ret = install_lib.get_outputs()
+ ret = install_lib.get_outputs(self)
if os.name == 'nt':
ret.extend([info[1] for info in self._get_dlls()])
return ret
-setup(name='bzr-svn',
- description='Support for Subversion branches in Bazaar',
- keywords='plugin bzr svn',
- version='0.4.13',
- url='http://bazaar-vcs.org/BzrForeignBranches/Subversion',
- download_url='http://bazaar-vcs.org/BzrSvn',
- license='GPL',
- author='Jelmer Vernooij',
- author_email='jelmer@samba.org',
- long_description="""
- This plugin adds support for branching off and
- committing to Subversion repositories from
- Bazaar.
- """,
- package_dir={'bzrlib.plugins.svn':'.',
- 'bzrlib.plugins.svn.tests':'tests'},
- packages=['bzrlib.plugins.svn',
- 'bzrlib.plugins.svn.mapping3',
- 'bzrlib.plugins.svn.tests'],
- ext_modules=[
- SvnExtension("client", ["client.c", "editor.c", "util.c", "ra.c", "wc.c"], libraries=["svn_client-1", "svn_subr-1"]),
- SvnExtension("ra", ["ra.c", "util.c", "editor.c"], libraries=["svn_ra-1", "svn_delta-1", "svn_subr-1"]),
- SvnExtension("repos", ["repos.c", "util.c"], libraries=["svn_repos-1", "svn_subr-1"]),
- SvnExtension("wc", ["wc.c", "util.c", "editor.c"], libraries=["svn_wc-1", "svn_subr-1"]),
- ],
- cmdclass = { 'install_lib': install_lib_with_dlls },
- )
+
+def source_path(filename):
+ return os.path.join("subvertpy", filename)
+
+
+def subvertpy_modules():
+ return [
+ SvnExtension("subvertpy.client", [source_path(n) for n in
+ ("client.c", "editor.c", "util.c", "_ra.c", "wc.c")],
+ libraries=["svn_client-1", "svn_subr-1", "svn_ra-1", "svn_wc-1"]),
+ SvnExtension("subvertpy._ra", [source_path(n) for n in
+ ("_ra.c", "util.c", "editor.c")],
+ libraries=["svn_ra-1", "svn_delta-1", "svn_subr-1"]),
+ SvnExtension("subvertpy.repos", [source_path(n) for n in ("repos.c", "util.c")],
+ libraries=["svn_repos-1", "svn_subr-1", "svn_fs-1"]),
+ SvnExtension("subvertpy.wc", [source_path(n) for n in ("wc.c",
+ "util.c", "editor.c")], libraries=["svn_wc-1", "svn_subr-1"])
+ ]
+
+
+subvertpy_version = (0, 8, 10)
+subvertpy_version_string = ".".join(map(str, subvertpy_version))
+
+
+if __name__ == "__main__":
+ setup(name='subvertpy',
+ description='Alternative Python bindings for Subversion',
+ keywords='svn subvertpy subversion bindings',
+ version=subvertpy_version_string,
+ url='http://samba.org/~jelmer/subvertpy',
+ download_url="http://samba.org/~jelmer/subvertpy/subvertpy-%s.tar.gz" % (
+ subvertpy_version_string, ),
+ license='LGPLv2.1 or later',
+ author='Jelmer Vernooij',
+ author_email='jelmer@samba.org',
+ long_description="""
+ Alternative Python bindings for Subversion. The goal is to have complete, portable and "Pythonic" Python bindings.
+ """,
+ packages=['subvertpy', 'subvertpy.tests'],
+ ext_modules=subvertpy_modules(),
+ scripts=['bin/subvertpy-fast-export'],
+ cmdclass = { 'install_lib': install_lib_with_dlls },
+ )