Support ignore_ancestry argument to RemoteAccess.do.update().
[jelmer/subvertpy.git] / setup.py
index 33868bdf27657dee9597314a5c5ed3ca9a9e2d73..f62c28853a6c0616e4384b6a0cb3cb2658427fb2 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,27 +1,15 @@
 #!/usr/bin/env python
 # Setup file for subvertpy
-# Copyright (C) 2005-2010 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2005-2010 Jelmer Vernooij <jelmer@jelmer.uk>
 
-from distutils.core import setup
+from distutils.core import setup, Command
 from distutils.extension import Extension
-from distutils.command.install_lib import install_lib
+from distutils.command.build import build
 from distutils import log
 import sys
 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.
+import subprocess
 
 class CommandException(Exception):
     """Encapsulate exit status of command execution"""
@@ -65,7 +53,7 @@ def config_value(command, arg):
     for cmd in cmds:
         try:
             return run_cmd(cmd, arg)
-        except CommandException, e:
+        except CommandException as e:
             if not e.not_found():
                 raise
     else:
@@ -120,7 +108,7 @@ def svn_build_data():
                 svn_prefix = basedir
                 break
     if svn_prefix is not None:
-        return ([os.path.join(svn_prefix, "include/subversion-1")], 
+        return ([os.path.join(svn_prefix, "include/subversion-1")],
                 [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. ")
@@ -132,23 +120,23 @@ def is_keychain_provider_available():
     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("""
+    gcc = subprocess.Popen(gcc_command_args,
+        stdin=subprocess.PIPE, universal_newlines=True,
+        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    gcc.communicate("""
 #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)
+    return (gcc.returncode == 0)
 
 
 class VersionQuery(object):
 
     def __init__(self, filename):
         self.filename = filename
-        f = file(filename, "rU")
+        f = open(filename, "rU")
         try:
             self.text = f.read()
         finally:
@@ -164,13 +152,16 @@ class VersionQuery(object):
 # 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")
@@ -179,7 +170,9 @@ if os.name == "nt":
                 "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
@@ -196,7 +189,7 @@ if os.name == "nt":
             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(
@@ -217,7 +210,7 @@ if os.name == "nt":
             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"), 
+            os.path.join(svn_dev_dir, "include"),
         ]
         lib_dirs = [
             os.path.join(svn_dev_dir, "lib"),
@@ -240,9 +233,13 @@ if os.name == "nt":
                   libsvn_repos-1 libsvn_wc-1 libsvn_delta-1 libsvn_diff-1
                   libsvn_fs-1 libsvn_repos-1 libsvn_fs_fs-1 libsvn_fs_base-1
                   intl3_svn
-                  libdb44 xml
+                  xml
                   advapi32 shell32 ws2_32 zlibstat
                """.split()
+        if svn_version >= (1,7,0):
+            libs += ["libdb48"]
+        else:
+            libs += ["libdb44"]
         if svn_version >= (1,5,0):
             # Since 1.5.0 libsvn_ra_dav-1 was removed
             libs.remove("libsvn_ra_dav-1")
@@ -253,47 +250,92 @@ if os.name == "nt":
 (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, 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')))
-    return Extension(name, *args, **kwargs)
-
-
-# On Windows, we install the apr binaries too.
-class install_lib_with_dlls(install_lib):
+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)
+
+
+class TestCommand(Command):
+    """Command for running unittests without install."""
+
+    user_options = [("args=", None, '''The command args string passed to
+                                    unittest framework, such as 
+                                     --args="-v -f"''')]
+
+    def initialize_options(self):
+        self.args = ''
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        self.run_command('build')
+        bld = self.distribution.get_command_obj('build')
+        #Add build_lib in to sys.path so that unittest can found DLLs and libs
+        sys.path = [os.path.abspath(bld.build_lib)] + sys.path
+        os.chdir(bld.build_lib)
+        log.info("Running unittest without install.")
+
+        import shlex
+        import unittest
+        test_argv0 = [sys.argv[0] + ' test --args=']
+        #For transfering args to unittest, we have to split args
+        #by ourself, so that command like:
+        #python setup.py test --args="-v -f"
+        #can be executed, and the parameter '-v -f' can be
+        #transfering to unittest properly.
+        test_argv = test_argv0 + shlex.split(self.args)
+        unittest.main(module=None, defaultTest='subvertpy.tests.test_suite', argv=test_argv)
+
+
+class BuildWithDLLs(build):
     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")]
+        # the apr binaries.
+        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
                            libsvn_fs-1.dll libsvn_ra-1.dll libsvn_repos-1.dll
                            libsvn_subr-1.dll libsvn_wc-1.dll libsasl.dll""".split()
-        apr_bins += """intl3_svn.dll libdb44.dll libeay32.dll ssleay32.dll""".split()
+        if get_svn_version() >= (1,7,0):
+            apr_bins += ["libdb48.dll"]
+        else:
+            apr_bins += ["libdb44.dll"]
+        apr_bins += """intl3_svn.dll libeay32.dll ssleay32.dll""".split()
         look_dirs = os.environ.get("PATH","").split(os.pathsep)
         look_dirs.insert(0, os.path.join(os.environ["SVN_DEV"], "bin"))
-    
+
+        target = os.path.abspath(os.path.join(self.build_lib, 'subvertpy'))
         for bin in apr_bins:
             for look in look_dirs:
                 f = os.path.join(look, bin)
                 if os.path.isfile(f):
-                    target = os.path.join(self.install_dir, "subvertpy", bin)
                     ret.append((f, target))
                     break
             else:
@@ -302,19 +344,22 @@ class install_lib_with_dlls(install_lib):
         return ret
 
     def run(self):
-        install_lib.run(self)
+        build.run(self)
         # the apr binaries.
-        if os.name == 'nt':
-            # On Windows we package up the apr dlls with the plugin.
-            for s, d in self._get_dlls():
-                self.copy_file(s, d)
+        # On Windows we package up the apr dlls with the plugin.
+        for s, d in self._get_dlls():
+            self.copy_file(s, d)
 
     def get_outputs(self):
-        ret = install_lib.get_outputs(self)
-        if os.name == 'nt':
-            ret.extend([info[1] for info in self._get_dlls()])
+        ret = build.get_outputs(self)
+        ret.extend(info[1] for info in self._get_dlls())
         return ret
 
+cmdclass = {'test': TestCommand}
+if os.name == 'nt':
+    # BuildWithDLLs can copy external DLLs into build directory On Win32.
+    # So we can running unittest directly from build directory.
+    cmdclass['build'] = BuildWithDLLs
 
 def source_path(filename):
     return os.path.join("subvertpy", filename)
@@ -322,14 +367,20 @@ def source_path(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"])
+        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, 1)
+subvertpy_version = (0, 9, 3)
 subvertpy_version_string = ".".join(map(str, subvertpy_version))
 
 
@@ -338,16 +389,17 @@ if __name__ == "__main__":
           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,
+          url='https://jelmer.uk/subvertpy',
+          download_url="https://jelmer.uk/subvertpy/subvertpy-%s.tar.gz" % (
+              subvertpy_version_string, ),
           license='LGPLv2.1 or later',
           author='Jelmer Vernooij',
-          author_email='jelmer@samba.org',
+          author_email='jelmer@jelmer.uk',
           long_description="""
-          Alternative Python bindings for Subversion. The goal is to have complete, portable and "Pythonic" Python bindings. 
+          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 },
+          cmdclass=cmdclass,
           )