BenReser http svnms autosvnslides Subversion Committer working at WANdisco since 2012 Started working on Perl Bindings in 2003 to automate Subversion as a replacement for CVS Never finished the project that inspired the work and ended up working on Subversion itself ID: 562006
Download Presentation The PPT/PDF document "Automating Subversion with Bindings" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Automating Subversion with Bindings
@
BenReser
http://
svn.ms
/
autosvnslidesSlide2
Subversion Committer working at WANdisco
since 2012.
Started working on Perl Bindings in 2003 to automate Subversion as a replacement for CVS. Never finished the project that inspired the work and ended up working on Subversion itself.My work isn’t limited to bindings anymore and has expanded across the different parts of Subversion including acting as the Release Manager.
Automating Subversion with Bindings
About Ben
Slide
2Slide3
What are Bindings?Slide4
An implementation of a Version Control System?
Automating Subversion with Bindings
What is Subversion…
Slide 4Slide5
An implementation of a Version Control System?
Libraries
that implement a Version Control System.Automating Subversion with BindingsWhat is Subversion…
Slide
5Slide6
An implementation of a Version Control System?
Libraries
that implement a Version Control System.Written in CAutomating Subversion with Bindings
What is Subversion…
Slide 6Slide7
Automating Subversion with Bindings
Layered Library Design
Slide
7Slide8
Client
Implements the basic functions of a client. Knows about working copies and uses the…
Automating Subversion with BindingsLayered Library Design - Client
Slide
8Slide9
Client
Implements the basic functions of a client. Knows about working copies and uses the…
WC (Working Copy)Implements the working copy Automating Subversion with Bindings
Layered Library Design - Client
Slide 9Slide10
Client
Implements the basic functions of a client. Knows about working copies and uses the…
WC (Working Copy)Implements the working copyRA (Repository Access)Implements protocol to talk to (possibly remote) repositoryLocal (file://)Neon (http(s):// 1.7.x and older was called DAV in 1.4.x and older, gone in 1.8.x)
Serf (http(s):// 1.5.x and newer)SVN (svn://
)
Automating Subversion with Bindings
Layered Library Design - Client
Slide
10Slide11
Repos
Repository interface which implements high level repository functionality and uses…
Automating Subversion with Bindings
Layered Library Design - Server
Slide 11Slide12
Repos
Repository interface
which implements high level repository functionality and uses…FSFile system implementation to store a repositoryFS_Base (Berkeley DB)FS_FS (non database implementation)
Automating Subversion with Bindings
Layered Library Design - Server
Slide
12Slide13
Subr
Miscellaneous subroutines
Automating Subversion with BindingsLayered Library Design – Misc.
Slide
13Slide14
Subr
Miscellaneous subroutines
DeltaTree and byte-stream differencing routines Automating Subversion with Bindings
Layered Library Design – Misc.
Slide 14Slide15
Subr
Miscellaneous subroutines
DeltaTree and byte-stream differencing routinesDiffContextual differencing and merge routines
Automating Subversion with Bindings
Layered Library Design – Misc.
Slide
15Slide16
Access Subversion C APIs from other Higher Level Programming Languages
Automating Subversion with Bindings
What are Bindings?
Slide 16Slide17
Access Subversion C APIs from other Higher Level Programming Languages
Somewhat easier to use than C
Automating Subversion with Bindings
What are Bindings?
Slide
17Slide18
Access Subversion C APIs from other Higher Level Programming Languages
Somewhat easier to use than C
Provide an interface that somewhat matches the Higher Level Language’s idioms Automating Subversion with Bindings
What are Bindings?
Slide
18Slide19
Access Subversion C APIs from other Higher Level Programming Languages
Somewhat easier to use than C
Provide an interface that somewhat matches the Higher Level Language’s idiomsMay even hide some annoying details from using the libraries
Automating Subversion with Bindings
What are Bindings?
Slide
19Slide20
Why use Bindings?Slide21
The client tries to have machine readable formats
Automating Subversion with Bindings
Can’t I Just Script The Client?
Slide
21Slide22
The client tries to have machine readable formats
I recently used something like this to try and find a bug in diff –summarize:
(svn log $URL | grep -
Eo '^r[0-9]+ \| ' | sed 's/[^0-9]//g') | while read
rev; do
svn
diff
--summarize $URL -c
$rev; done
Automating Subversion with Bindings
Can’t I Just Script The Client?
Slide
22Slide23
It worked great until it ran into this output:
svn
log –c 933481 https://svn.apache.org/repos/asf
/subversion/trunk------------------------------------------------------------------------
r933481 | gstein | 2010-04-12 21:20:50 -0700 (Mon, 12 Apr 2010) | 27 lines
Add some new methods to the Sandbox class for performing simple,
unverified operations.
Also introduce deep magic with
svntest.main.make_log_msg
() to produce log
messages that show the source of the command invocation. These automated
log messages look like:
----
r2 |
jrandom
| 2010-04-12 23:57:10 -0400 (Mon, 12 Apr 2010) | 1 line
File './
schedule_tests.py
', line 543, in
status_add_deleted_directory
---
-
Automating Subversion with Bindings
Can’t I Just Script The Client?
Slide
23Slide24
The client supports XML output with --xml on most commands.
Automating Subversion with Bindings
What about XML?
Slide
24Slide25
The client supports XML output with --xml on most commands.
XML is hard to parse correctly
Regexps aren’t reliableXSLT is a pain to writeXML parsers are far from easy to drive
Automating Subversion with Bindings
What about XML?
Slide
25Slide26
We try to avoid changing the output and behavior of commands.
Automating Subversion with Bindings
Command behavior changes
Slide
26Slide27
We try to avoid changing the output and behavior of commands.
Automating Subversion with Bindings
Command behavior changes
Slide
27Slide28
We try to avoid changing the output and behavior of commands.
svn
mergeinfo prior to 1.8.0 behaved as though --show-revs=merged was passed if no --show-revs option was passed. In 1.8.x this shows a graph.
Automating Subversion with Bindings
Command behavior changes
Slide
28Slide29
We can implement functionality that the command line client doesn’t have.
Examples:
ViewVCSubclipsecontrol-chars.py hook-script
Automating Subversion with Bindings
Greater capabilities
Slide
29Slide30
Poor documentation
Automating Subversion with Bindings
Why not use Bindings?
Slide 30Slide31
Poor documentation
Need to install them
Automating Subversion with Bindings
Why not use Bindings?
Slide 31Slide32
Poor documentation
Need to install them
Expose internal details that may be hard to understand Automating Subversion with Bindings
Why not use Bindings?
Slide
32Slide33
Poor documentation
Need to install them
Expose internal details that may be hard to understandNot always updated for the latest features
Automating Subversion with Bindings
Why not use Bindings?
Slide
33Slide34
Getting StartedSlide35
SWIG
Python
PerlRubyJavaHL
ctypes-pythonSVNKit
pySVN
Automating Subversion with Bindings
What Bindings Are Available
Slide
35Slide36
Simplified Wrapper and Interface Generator
Automating Subversion with BindingsWhat is SWIG?
Slide
36Slide37
Simplified Wrapper and Interface Generator
Partly automated generator
Automating Subversion with Bindings
What is SWIG?
Slide 37Slide38
Simplified Wrapper and Interface Generator
Partly automated generator
Acts like a specialized C compiler Automating Subversion with Bindings
What is SWIG?
Slide 38Slide39
Simplified Wrapper and Interface Generator
Partly automated generator
Acts like a specialized C compilerOnly needed at interface generation time Automating Subversion with Bindings
What is SWIG?
Slide
39Slide40
WindowsMac
RedHat
based LinuxDebian based LinuxOtherAutomating Subversion with Bindings
How To Install Bindings
Slide
40Slide41
WANdisco installer
Provides
swig-python (for Python 2.7.2) and JavaHLAlagazam.netProvides swig-python, swig-perl, swig-ruby, and JavaHL
Automating Subversion with Bindings
Windows
Slide
41Slide42
WANdisco packages
subversion-python (SWIG)
subversion-ruby (subversion 1.8.x only)subversion-perlsubversion-javahlOS Packages
Older but usually available and named same as above.
Automating Subversion with Bindings
RedHat
based Linux
Slide
42Slide43
WANdisco packages
python-subversion (SWIG)
libsvn-ruby (and libsvn-ruby1.8 for Ruby 1.8)libsvn-perllibsvn-java (JavaHL
)OS PackagesOlder but usually available and named same as above.
Automating Subversion with Bindings
Debian
based Linux
Slide
43Slide44
WANdisco
installer
Provides swig-python, swig-perl, swig-ruby and JavaHLMacPortssubversion-javahlbindingssubversion-perlbindings-5.16 (number is
perl version)subversion-python27bindings (number is python version)subversion-
rubybindingsHomebrewcan
provide
JavaHL
, swig-
perl
, swig-python, and swig-
ruby
Xcode
Command line tools
old but includes swig-python, swig-
perl
and swig-ruby
Automating Subversion with Bindings
Mac
Slide
44Slide45
WANdisco packages should have Bindings for most
OSes
*NIX platforms build it yourself by:[usual Subversion build instructions]make $bindingmake check-$bindingmake install-$bindingw
here $binding can be: javahl swig-
pl swig-py
swig-
rb
Don’t use do parallel builds of bindings (-j option to make)
Automating Subversion with Bindings
Other
Slide
45Slide46
On the Mac you need to do this before the normal Subversion instructions due to a bug in our API that makes the bindings fail to compile (requires SWIG,
libtool
and autoconf):make extraclean./autogen.sh
Automating Subversion with Bindings
Build It Yourself - SWIG
Slide
46Slide47
On the Mac you need to do this before the normal Subversion instructions due to a bug in our API that makes the bindings fail to compile (requires SWIG,
libtool
and autoconf):make extraclean./autogen.shMay need the same instructions on other platforms if you get an error about an undeclared symbol starting with SVN_AUTH
Automating Subversion with Bindings
Build It Yourself - SWIG
Slide
47Slide48
On the Mac you need to do this before the normal Subversion instructions due to a bug in our API that makes the bindings fail to compile (requires SWIG,
libtool
and autoconf):make extraclean./autogen.shMay need the same instructions on other platforms if you get an error about an undeclared symbol starting with SVN_AUTH
To use Ruby 1.9 need Subversion 1.8.x
Automating Subversion with Bindings
Build It Yourself - SWIG
Slide
48Slide49
On the Mac you need to do this before the normal Subversion instructions due to a bug in our API that makes the bindings fail to compile (requires SWIG,
libtool
and autoconf):make extraclean./autogen.shMay need the same instructions on other platforms if you get an error about an undeclared symbol starting with SVN_AUTH
To use Ruby 1.9 need Subversion 1.8.xPython 3 doesn’t work
Automating Subversion with Bindings
Build It Yourself - SWIG
Slide
49Slide50
Need --enable-
javahl
passed to configureAutomating Subversion with Bindings
Build It Yourself - JavaHL
Slide
50Slide51
Need --enable-
javahl
passed to configureNeed JUnit, specify where it is by passing this to configure (make sure this is an absolute path): --with-
junit=/usr/share/java/junit.jar
Automating Subversion with Bindings
Build It Yourself -
JavaHL
Slide
51Slide52
Need --enable-
javahl
passed to configureNeed JUnit, specify where it is by passing this to configure (make sure this is an absolute path): --with-
junit=/usr/share/java/junit.jar
Can specify which JDK to use by passing this to configure:
-
-with-
jdk
=/
usr
/lib/
jvm
/java-6-openjdk-amd64
Automating Subversion with Bindings
Build It Yourself -
JavaHL
Slide
52Slide53
Using the BindingsSlide54
Thin layer over C API
Automating Subversion with Bindings
SWIG Bindings
Slide
54Slide55
Thin layer over C API
Perl and Ruby have more syntactic sugar to make it feel more like a normal Perl or Ruby program
Automating Subversion with Bindings
SWIG Bindings
Slide 55Slide56
Thin layer over C API
Perl and Ruby have more syntactic sugar to make it feel more like a normal Perl or Ruby program
Python has very little syntactic sugar but is more completeAutomating Subversion with Bindings
SWIG Bindings
Slide
56Slide57
Thin layer over C API
Perl and Ruby have more syntactic sugar to make it feel more like a normal Perl or Ruby program
Python has very little syntactic sugar but is more completeNot every language has everything completely wrapped.
Automating Subversion with Bindings
SWIG Bindings
Slide
57Slide58
Core
The things that don’t fit anywhere else, includes APR functions that are needed and
libsvn_subr.ClientWcDiffDeltaRaReposFs
Automating Subversion with Bindings
SWIG Modules
Slide
58Slide59
APR is Apache Portable Runtime
Automating Subversion with Bindings
APR Pools
Slide
59Slide60
APR is Apache Portable Runtime
Pools are used for memory management.
Automating Subversion with Bindings
APR Pools
Slide 60Slide61
APR is Apache Portable Runtime
Pools are used for memory management.
Pools have a lifetime. Lifetime ends when pool or its parent is destroyed.Automating Subversion with Bindings
APR Pools
Slide
61Slide62
APR is Apache Portable Runtime
Pools are used for memory management.
Pools have a lifetime. Lifetime ends when pool or its parent is destroyed.Pools can be cleared to free memory and reuse the same pool (iteration)
Automating Subversion with Bindings
APR Pools
Slide
62Slide63
APR is Apache Portable Runtime
Pools are used for memory management.
Pools have a lifetime. Lifetime ends when pool or its parent is destroyed.Pools can be cleared to free memory and reuse the same pool (iteration)SWIG bindings largely let you ignore pools by defaulting to a single global pool
Automating Subversion with Bindings
APR Pools
Slide
63Slide64
APR is Apache Portable Runtime
Pools are used for memory management.
Pools have a lifetime. Lifetime ends when pool or its parent is destroyed.Pools can be cleared to free memory and reuse the same pool (iteration)SWIG bindings largely let you ignore pools by defaulting to a single global poolYou can still use pools and may want to in some cases (iteration, long running programs)
Automating Subversion with Bindings
APR Pools
Slide
64Slide65
C API uses a lot of callbacks, so SWIG does as well
Automating Subversion with Bindings
Callbacks and Batons
Slide
65Slide66
C API uses a lot of callbacks, so SWIG does as well
Callback
args are func, baton.
Automating Subversion with Bindings
Callbacks and Batons
Slide
66Slide67
C API uses a lot of callbacks, so SWIG does as well
Callback
args are func, baton.You can provide a binding language function for the callback.
Automating Subversion with Bindings
Callbacks and Batons
Slide
67Slide68
C API uses a lot of callbacks, so SWIG does as well
Callback
args are func, baton.You can provide a binding language function for the callback.Batons are a way of passing data through to the callback that you provide.
Automating Subversion with Bindings
Callbacks and Batons
Slide
68Slide69
C API uses a lot of callbacks, so SWIG does as well
Callback
args are func, baton.You can provide a binding language function for the callback.Batons are a way of passing data through to the callback that you provide.SWIG doesn’t support batons so use closures/lambdas.
Automating Subversion with Bindings
Callbacks and Batons
Slide
69Slide70
SWIG wraps the C types for you
Automating Subversion with Bindings
SWIG Types
Slide
70Slide71
SWIG wraps the C types for you
Structs
have getters and setters (type_field_get/type_field_set), but syntactic sugar allows you to use structs like objects in binding language
Automating Subversion with Bindings
SWIG Types
Slide
71Slide72
SWIG wraps the C types for you
Structs
have getters and setters (type_field_get/type_field_set), but syntactic sugar allows you to use structs like objects in binding languageStructs can be allocated and freed (
new_type/delete_type) e.g. new_svn_opt_revision_t
()
Automating Subversion with Bindings
SWIG Types
Slide
72Slide73
SWIG wraps the C types for you
Structs
have getters and setters (type_field_get/type_field_set), but syntactic sugar allows you to use structs like objects in binding languageStructs can be allocated and freed (
new_type/delete_type) e.g. new_svn_opt_revision_t
()Ints, Hashes and Arrays are mapped to the binding languages equivalent types
Automating Subversion with Bindings
SWIG Types
Slide
73Slide74
SWIG wraps the C types for you
Structs
have getters and setters (type_field_get/type_field_set), but syntactic sugar allows you to use structs like objects in binding languageStructs can be allocated and freed (
new_type/delete_type) e.g. new_svn_opt_revision_t
()Ints, Hashes and Arrays are mapped to the binding languages equivalent types
If a type hasn’t been mapped in SWIG you may have trouble using it
Automating Subversion with Bindings
SWIG Types
Slide
74Slide75
C API requires that paths be UTF-8 and canonical
Automating Subversion with Bindings
Canonicalization
Slide
75Slide76
C API requires that paths be UTF-8 and canonical
There are 3 types of paths
URL or URIDirent (path on local fileystem)Relpath (unrooted relative path)
Automating Subversion with Bindings
Canonicalization
Slide
76Slide77
C API requires that paths be UTF-8 and canonical
There are 3 types of paths
URL or URIDirent (path on local fileystem)Relpath (unrooted relative path)Use
svn_path_is_url() and context to determine which you have
Automating Subversion with Bindings
Canonicalization
Slide
77Slide78
C API requires that paths be UTF-8 and canonical
There are 3 types of paths
URL or URIDirent (path on local fileystem)Relpath (unrooted relative path)Use
svn_path_is_url() and context to determine which you haveUse svn_uri_canonicalize
(), svn_dirent_canonicalize() or svn_relpath_canonicalize
() to
canonicalize
a path.
Automating Subversion with Bindings
Canonicalization
Slide
78Slide79
C API requires that paths be UTF-8 and canonical
There are 3 types of paths
URL or URIDirent (path on local fileystem)Relpath (unrooted relative path)Use
svn_path_is_url() and context to determine which you haveUse svn_uri_canonicalize
(), svn_dirent_canonicalize() or svn_relpath_canonicalize
() to
canonicalize
a path.
Not doing this will cause assertions or crashes.
Automating Subversion with Bindings
Canonicalization
Slide
79Slide80
Python and Ruby have exceptions so errors are handled via that mechanism
Automating Subversion with Bindings
Error Handling
Slide 80Slide81
Python and Ruby have exceptions so errors are handled via that mechanism
Perl does not have exceptions
Uses an error handler callback $SVN::Error::handlerDefault callback croaks with message provided by libraries.See perldoc SVN::Core and read the documentation on SVN::Error for details
Automating Subversion with Bindings
Error Handling
Slide
81Slide82
Python and Ruby have exceptions so errors are handled via that mechanism
Perl does not have exceptions
Uses an error handler callback $SVN::Error::handlerDefault callback croaks with message provided by libraries.See perldoc SVN::Core and read the documentation on SVN::Error for detailsAll have access to data from Subversion’s error
struct svn_error_t
Errors can be chained, next error is in child fieldapr_err is a numeric code for the error
m
essage is a human readable string
Automating Subversion with Bindings
Error Handling
Slide
82Slide83
import sys
from
svn import core, clientctx
= client.create_context()
cfg =
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
83Slide84
import
sys
from svn
import core, client
ctx
=
client.create_context
()
cfg
=
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
84Slide85
import sys
from
svn import core, client
ctx =
client.create_context()
cfg
=
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
85Slide86
import sys
from
svn import core, client
ctx
=
client.create_context
()
cfg
=
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
86Slide87
import sys
from
svn import core, client
ctx
=
client.create_context
()
cfg
=
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
87Slide88
import sys
from
svn import core, client
ctx
= client.create_context
()
cfg
=
core.svn_config_get_config
(None)
cfg_config
=
cfg
[
core.SVN_CONFIG_CATEGORY_CONFIG
]
ctx.auth_baton
=
core.svn_cmdline_create_auth_baton
(False, #
non_interactive
None, #username
None, #password
None, #
config_dir
False, #
no_auth_cache
False, #
trust_server_cert
cfg_config
, #
config
category
None, #
cancel_func
None) #
cancel_baton
rev =
core.svn_opt_revision_t
()
rev.kind
=
core.svn_opt_revision_head
if
core.svn_path_is_url
(
sys.argv
[1]):
target =
core.svn_uri_canonicalize
(
sys.argv
[1])
else:
target =
core.svn_dirent_canonicalize
(
sys.argv
[1])
client.cat
(
sys.stdout
, # output file handle
target,
rev, # revision
ctx
) #client context
Automating Subversion with Bindings
Python Example - Cat
Slide
88Slide89
use SVN::Client;
my $
ctx = new SVN::Client();my $
cfg = SVN::Core::config_get_config
(undef
);
my $
cfg_config
= $
cfg
->{SVN::Core::CONFIG_CATEGORY_CONFIG};
$
ctx
->
auth
(
SVN::Core::
cmdline_create_auth_baton
(0, #
non_interactive
undef
, #username
undef
, #password
undef
, #
config_dir
0, #
no_auth_cache
0, #
trust_server_cert
,
$
cfg_config
, #
config
category
undef
, #
cancel_func
undef
) #
cancel_baton
);
my $target;
if (SVN::Core::
path_is_url
($ARGV[0])) {
$target = SVN::Core::
uri_canonicalize
($ARGV[0]);
} else {
$target = SVN::Core::
dirent_canonicalize
($ARGV[0]);
}
$
ctx
->cat(\*STDOUT, #output
filehandle
$target,
'HEAD'); #rev
Automating Subversion with Bindings
Perl Example - Cat
Slide
89Slide90
use SVN::Client;
my $
ctx
= new SVN::Client();my $
cfg
= SVN::Core::
config_get_config
(
undef
);
my $
cfg_config
= $
cfg
->{SVN::Core::CONFIG_CATEGORY_CONFIG};
$
ctx
->
auth
(
SVN::Core::
cmdline_create_auth_baton
(0, #
non_interactive
undef
, #username
undef
, #password
undef
, #
config_dir
0, #
no_auth_cache
0, #
trust_server_cert
,
$
cfg_config
, #
config
category
undef
, #
cancel_func
undef
) #
cancel_baton
);
my $target;
if (SVN::Core::
path_is_url
($ARGV[0])) {
$target = SVN::Core::
uri_canonicalize
($ARGV[0]);
} else {
$target = SVN::Core::
dirent_canonicalize
($ARGV[0]);
}
$
ctx
->cat(\*STDOUT, #output
filehandle
$target,
'HEAD'); #rev
Automating Subversion with Bindings
Perl Example - Cat
Slide
90Slide91
use SVN::Client;
my $
ctx = new SVN::Client();
my $cfg = SVN::Core::
config_get_config(
undef
);
my $
cfg_config
= $
cfg
->{SVN::Core::CONFIG_CATEGORY_CONFIG};
$
ctx
->
auth
(
SVN::Core::
cmdline_create_auth_baton
(0, #
non_interactive
undef
, #username
undef
, #password
undef
, #
config_dir
0, #
no_auth_cache
0, #
trust_server_cert
,
$
cfg_config
, #
config
category
undef
, #
cancel_func
undef
) #
cancel_baton
);
my $target;
if (SVN::Core::
path_is_url
($ARGV[0])) {
$target = SVN::Core::
uri_canonicalize
($ARGV[0]);
} else {
$target = SVN::Core::
dirent_canonicalize
($ARGV[0]);
}
$
ctx
->cat(\*STDOUT, #output
filehandle
$target,
'HEAD'); #rev
Automating Subversion with Bindings
Perl Example - Cat
Slide
91Slide92
use SVN::Client;
my $
ctx
= new SVN::Client();
my $cfg
= SVN::Core::
config_get_config
(
undef
);
my $
cfg_config
= $
cfg
->{SVN::Core::CONFIG_CATEGORY_CONFIG};
$
ctx
->
auth
(
SVN::Core::
cmdline_create_auth_baton
(0, #
non_interactive
undef
, #username
undef
, #password
undef
, #
config_dir
0, #
no_auth_cache
0, #
trust_server_cert
,
$
cfg_config
, #
config
category
undef
, #
cancel_func
undef
) #
cancel_baton
);
my $target;
if (SVN::Core::
path_is_url
($ARGV[0])) {
$target = SVN::Core::
uri_canonicalize
($ARGV[0]);
} else {
$target = SVN::Core::
dirent_canonicalize
($ARGV[0]);
}
$
ctx
->cat(\*STDOUT, #output
filehandle
$target,
'HEAD'); #rev
Automating Subversion with Bindings
Perl Example - Cat
Slide
92Slide93
use SVN::Client;
my $
ctx
= new SVN::Client();my $
cfg = SVN::Core::
config_get_config
(
undef
);
my $
cfg_config
= $
cfg
->{SVN::Core::CONFIG_CATEGORY_CONFIG};
$
ctx
->
auth
(
SVN::Core::
cmdline_create_auth_baton
(0, #
non_interactive
undef
, #username
undef
, #password
undef
, #
config_dir
0, #
no_auth_cache
0, #
trust_server_cert
,
$
cfg_config
, #
config
category
undef
, #
cancel_func
undef
) #
cancel_baton
);
my $target;
if (SVN::Core::
path_is_url
($ARGV[0])) {
$target = SVN::Core::
uri_canonicalize
($ARGV[0]);
} else {
$target = SVN::Core::
dirent_canonicalize
($ARGV[0]);
}
$
ctx
->cat(\*STDOUT, #output
filehandle
$target,
'HEAD'); #rev
Automating Subversion with Bindings
Perl Example - Cat
Slide
93Slide94
require "
svn
/client"Svn
::Client::Context.new do |
ctx|
cfg
=
Svn
::Core::
Config.get
()
cfg_config
=
cfg
[
Svn
::Core::CONFIG_CATEGORY_CONFIG]
ctx.auth_baton
=
Svn
::
Core.cmdline_create_auth_baton
(
false, #
non_interactive
nil, #username
nil, #password
nil, #
config_dir
false, #
no_auth_cache
false, #
trust_server_cert
cfg_config
, #
config
category
nil, #
cancel_func
nil) #
cancel_baton
if
Svn
::
Core.path_is_url
(ARGV[0])
target =
Svn
::Core::
uri_canonicalize
(ARGV[0])
else
target =
Svn
::Core::
dirent_canonicalize
(ARGV[0])
end
ctx.cat
(target,
"HEAD", #rev
nil, #
pegrev
STDOUT) #output
filehandle
end
Automating Subversion with Bindings
Ruby Example - Cat
Slide
94Slide95
require "
svn
/client"
Svn::Client::
Context.new do |
ctx
|
cfg
=
Svn
::Core::
Config.get
()
cfg_config
=
cfg
[
Svn
::Core::CONFIG_CATEGORY_CONFIG]
ctx.auth_baton
=
Svn
::
Core.cmdline_create_auth_baton
(
false, #
non_interactive
nil, #username
nil, #password
nil, #
config_dir
false, #
no_auth_cache
false, #
trust_server_cert
cfg_config
, #
config
category
nil, #
cancel_func
nil) #
cancel_baton
if
Svn
::
Core.path_is_url
(ARGV[0])
target =
Svn
::Core::
uri_canonicalize
(ARGV[0])
else
target =
Svn
::Core::
dirent_canonicalize
(ARGV[0])
end
ctx.cat
(target,
"HEAD", #rev
nil, #
pegrev
STDOUT) #output
filehandle
end
Automating Subversion with Bindings
Ruby Example - Cat
Slide
95Slide96
require "
svn
/client"Svn
::Client::Context.new do |
ctx|
cfg
=
Svn
::Core::
Config.get
()
cfg_config
=
cfg
[
Svn
::Core::CONFIG_CATEGORY_CONFIG]
ctx.auth_baton
=
Svn
::
Core.cmdline_create_auth_baton
(
false, #
non_interactive
nil, #username
nil, #password
nil, #
config_dir
false, #
no_auth_cache
false, #
trust_server_cert
cfg_config
, #
config
category
nil, #
cancel_func
nil) #
cancel_baton
if
Svn
::
Core.path_is_url
(ARGV[0])
target =
Svn
::Core::
uri_canonicalize
(ARGV[0])
else
target =
Svn
::Core::
dirent_canonicalize
(ARGV[0])
end
ctx.cat
(target,
"HEAD", #rev
nil, #
pegrev
STDOUT) #output
filehandle
end
Automating Subversion with Bindings
Ruby Example - Cat
Slide
96Slide97
require "
svn
/client"
Svn
::Client::Context.new
do |
ctx
|
cfg
=
Svn
::Core::
Config.get
()
cfg_config
=
cfg
[
Svn
::Core::CONFIG_CATEGORY_CONFIG]
ctx.auth_baton
=
Svn
::
Core.cmdline_create_auth_baton
(
false, #
non_interactive
nil, #username
nil, #password
nil, #
config_dir
false, #
no_auth_cache
false, #
trust_server_cert
cfg_config
, #
config
category
nil, #
cancel_func
nil) #
cancel_baton
if
Svn
::
Core.path_is_url
(ARGV[0])
target =
Svn
::Core::
uri_canonicalize
(ARGV[0])
else
target =
Svn
::Core::
dirent_canonicalize
(ARGV[0])
end
ctx.cat
(target,
"HEAD", #rev
nil, #
pegrev
STDOUT) #output
filehandle
end
Automating Subversion with Bindings
Ruby Example - Cat
Slide
97Slide98
require "
svn
/client"
Svn::Client::Context.new
do |
ctx
|
cfg
=
Svn
::Core::
Config.get
()
cfg_config
=
cfg
[
Svn
::Core::CONFIG_CATEGORY_CONFIG]
ctx.auth_baton
=
Svn
::
Core.cmdline_create_auth_baton
(
false, #
non_interactive
nil, #username
nil, #password
nil, #
config_dir
false, #
no_auth_cache
false, #
trust_server_cert
cfg_config
, #
config
category
nil, #
cancel_func
nil) #
cancel_baton
if
Svn
::
Core.path_is_url
(ARGV[0])
target =
Svn
::Core::
uri_canonicalize
(ARGV[0])
else
target =
Svn
::Core::
dirent_canonicalize
(ARGV[0])
end
ctx.cat
(target,
"HEAD", #rev
nil, #
pegrev
STDOUT) #output
filehandle
end
Automating Subversion with Bindings
Ruby Example - Cat
Slide
98Slide99
def
log_entry_receiver(log_entry
, pool): print("r"+
str(
log_entry.revision
))
revprops
=
log_entry.revprops
print(
revprops
['
svn:log
']+"\n")
end =
core.svn_opt_revision_t
()
end.kind
=
core.svn_opt_revision_number
end.value.number
= 0
rev_range
=
core.svn_opt_revision_range_t
()
rev_range.start
= rev
rev_range.end
= end
client.log5((target,), #target
rev, #
pegrev
(
rev_range
,), #rev range
0, #limit (0=unlimited)
True, #discover changed paths
True, #
strict_node_history
False, #
include_merged_revisions
None, #array of
revprops
to retrieve
# (None for all)
log_entry_receiver
, #callback
ctx
)
Automating Subversion with Bindings
Python Example - Log
Slide
99Slide100
def
log_entry_receiver(log_entry
, pool): print("r"+
str
(
log_entry.revision
))
revprops
=
log_entry.revprops
print(
revprops
['
svn:log
']+"\n")
end =
core.svn_opt_revision_t
()
end.kind
=
core.svn_opt_revision_number
end.value.number
= 0
rev_range
=
core.svn_opt_revision_range_t
()
rev_range.start
= rev
rev_range.end
= end
client.log5((target,), #target
rev, #
pegrev
(
rev_range
,), #rev range
0, #limit (0=unlimited)
True, #discover changed paths
True, #
strict_node_history
False, #
include_merged_revisions
None, #array of
revprops
to retrieve
# (None for all)
log_entry_receiver
, #callback
ctx
)
Automating Subversion with Bindings
Python Example - Log
Slide
100Slide101
def
log_entry_receiver(log_entry
, pool): print("r"+
str(
log_entry.revision
))
revprops
=
log_entry.revprops
print(
revprops
['
svn:log
']+"\n")
end =
core.svn_opt_revision_t
()
end.kind
=
core.svn_opt_revision_number
end.value.number
= 0
rev_range
=
core.svn_opt_revision_range_t
()
rev_range.start
= rev
rev_range.end
= end
client.log5((target,), #target
rev, #
pegrev
(
rev_range
,), #rev range
0, #limit (0=unlimited)
True, #discover changed paths
True, #
strict_node_history
False, #
include_merged_revisions
None, #array of
revprops
to retrieve
# (None for all)
log_entry_receiver
, #callback
ctx
)
Automating Subversion with Bindings
Python Example - Log
Slide
101Slide102
def
log_entry_receiver(
log_entry, pool):
print("r"+
str
(
log_entry.revision
))
revprops
=
log_entry.revprops
print(
revprops
['
svn:log
']+"\n")
end =
core.svn_opt_revision_t
()
end.kind
=
core.svn_opt_revision_number
end.value.number
= 0
rev_range
=
core.svn_opt_revision_range_t
()
rev_range.start
= rev
rev_range.end
= end
client.log5((target,), #target
rev, #
pegrev
(
rev_range
,), #rev range
0, #limit (0=unlimited)
True, #discover changed paths
True, #
strict_node_history
False, #
include_merged_revisions
None, #array of
revprops
to retrieve
# (None for all)
log_entry_receiver
, #callback
ctx
)
Automating Subversion with Bindings
Python Example - Log
Slide
102Slide103
sub
log_entry_receiver
{ my ($log_entry,$pool
) = @_;
my $revprops
= $
log_entry
->
revprops
;
print "r",$
log_entry
->revision;
print "\
n$revprops
->{'
svn:log
'}\n\n"
}
$
ctx
->log5($target,
'HEAD', #
pegrev
['HEAD',0], #rev range
0, #limit (0=unlimited)
1, #
discover_changed_paths
1, #
strict_node_history
0, #
include_merged_revisions
undef
, #array of
revprops
to
retrive
# (
undef
for all)
\&
log_entry_receiver
); #callback
Automating Subversion with Bindings
Perl Example - Log
Slide
103Slide104
sub
log_entry_receiver
{ my ($log_entry,$pool
) = @_;
my $revprops
= $
log_entry
->
revprops
;
print "r",$
log_entry
->revision;
print "\
n$revprops
->{'
svn:log
'}\n\n"
}
$
ctx
->log5($target,
'HEAD', #
pegrev
['HEAD',0], #rev range
0, #limit (0=unlimited)
1, #
discover_changed_paths
1, #
strict_node_history
0, #
include_merged_revisions
undef
, #array of
revprops
to
retrive
# (
undef
for all)
\&
log_entry_receiver
); #callback
Automating Subversion with Bindings
Perl Example - Log
Slide
104Slide105
sub
log_entry_receiver
{ my ($log_entry,$pool
) = @_;
my $revprops
= $
log_entry
->
revprops
;
print "r",$
log_entry
->revision;
print "\
n$revprops
->{'
svn:log
'}\n\n"
}
$
ctx
->log5($target,
'HEAD', #
pegrev
['HEAD',0], #rev range
0, #limit (0=unlimited)
1, #
discover_changed_paths
1, #
strict_node_history
0, #
include_merged_revisions
undef
, #array of
revprops
to
retrive
# (
undef
for all)
\&
log_entry_receiver
); #callback
Automating Subversion with Bindings
Perl Example - Log
Slide
105Slide106
args
= [target, "HEAD", #start rev
0, #end rev 0, #limit
true, #
discover_changed_paths
true] #strict node history
ctx.log
(*
args
) do |
changed_paths
, rev, author, date, message|
print("
r",rev
,"\n")
print(message,"\n\n")
end
Automating Subversion with Bindings
Ruby Example - Log
Slide
106Slide107
args
= [target, "HEAD", #start rev
0, #end rev 0, #limit
true, #
discover_changed_paths
true] #strict node history
ctx.log
(*
args
) do |
changed_paths
, rev, author, date, message|
print("
r",rev
,"\n")
print(message,"\n\n")
end
Automating Subversion with Bindings
Ruby Example - Log
Slide
107Slide108
args
= [target, "HEAD", #start rev
0, #end rev 0, #limit
true, #
discover_changed_paths
true] #strict node history
ctx.log
(*
args
)
do |
changed_paths
, rev, author, date, message|
print("
r",rev
,"\n")
print(message,"\n\n")
end
Automating Subversion with Bindings
Ruby Example - Log
Slide
108Slide109
args
= [target, "HEAD", #start rev
0, #end rev
0, #limit
true, #
discover_changed_paths
true] #strict node history
ctx.log
(*
args
)
do |
changed_paths
, rev, author, date, message|
print("
r",rev
,"\n")
print(message,"\n\n")
end
Automating Subversion with Bindings
Ruby Example - Log
Slide
109Slide110
Use the latest version
Automating Subversion with Bindings
SWIG Advice
Slide
110Slide111
Use the latest version
Refer to C API documentation to determine arguments
Automating Subversion with Bindings
SWIG Advice
Slide
111Slide112
Use the latest version
Refer to C API documentation to determine arguments
Use the forceAutomating Subversion with Bindings
SWIG Advice
Slide
112Slide113
Use the latest version
Refer to C API documentation to determine arguments
Use the force source
Automating Subversion with Bindings
SWIG Advice
Slide
113Slide114
Use the latest version
Refer to C API documentation to determine arguments
Use the source and examples under tools/examples, {tools,contrib}/{client-side,hook-scripts,server-side}, and the test suites for the bindings.
Automating Subversion with Bindings
SWIG Advice
Slide
114Slide115
Use the latest version
Refer to C API documentation to determine arguments
Use the source and examples under tools/examples, {tools,contrib}/{client-side,hook-scripts,server-side}, and the test suites for the bindings.Errors about missing functions are often a sign of mismatched libraries. Check that the language path is correct and that the Subversion libraries being loaded match. Adding a sleep to your code and then using
lsof against that process can be helpful here.
Automating Subversion with Bindings
SWIG Advice
Slide
115Slide116
If you can, build your own with debug symbols by passing this to configure:
--enable-maintainer-modeAutomating Subversion with Bindings
SWIG Advice
Slide
116Slide117
If you can, build your own with debug symbols by passing this to configure:
--enable-maintainer-modeUse the start.sh script included with my examples to use uninstalled bindings from a Subversion build to ease debugging/testing: SVN_BUILDDIR=$HOME/subversion-1.8.3 \
start.sh
gdb –
args
perl
cat.pl
Automating Subversion with Bindings
SWIG Advice
Slide
117Slide118
If you can, build your own with debug symbols by passing this to configure:
--enable-maintainer-modeUse the start.sh script included with my examples to use uninstalled bindings from a Subversion build to ease debugging/testing: SVN_BUILDDIR=$HOME/subversion-1.8.3 \
start.sh
gdb
-
args
perl
cat.pl
The
start.sh
script can be helpful in understanding what parameters are needed to point your language at the right libraries.
Automating Subversion with Bindings
SWIG Advice
Slide
118Slide119
HL stands for High Level
Automating Subversion with Bindings
JavaHL
Slide
119Slide120
HL stands for High LevelUses the C API behind the scenes via
JNI
Automating Subversion with Bindings
JavaHL
Slide 120Slide121
HL stands for High Level
Uses the C API behind the scenes via
JNIInterface is not based on C APIAutomating Subversion with Bindings
JavaHL
Slide 121Slide122
HL stands for High Level
Uses the C API behind the scenes via
JNIInterface is not based on C APIHides details like APR PoolsAutomating Subversion with Bindings
JavaHL
Slide
122Slide123
HL stands for High Level
Uses the C API behind the scenes via
JNIInterface is not based on C APIHides details like APR PoolsInterface is more Java like than SWIG bindings are to their languagesAutomating Subversion with Bindings
JavaHL
Slide
123Slide124
HL stands for High Level
Uses the C API behind the scenes via JNI
Interface is not based on C APIHides details like APR PoolsInterface is more Java like than SWIG bindings are to their languagesDon’t need to canonicalize
Automating Subversion with Bindings
JavaHL
Slide
124Slide125
HL stands for High Level
Uses the C API behind the scenes via JNI
Interface is not based on C APIHides details like APR PoolsInterface is more Java like than SWIG bindings are to their languagesDon’t need to canonicalizeThrows SubversionException and
ClientException
Automating Subversion with Bindings
JavaHL
Slide
125Slide126
import
org.apache.subversion.javahl.SVNClient
;import org.apache.subversion.javahl.types.*;
import org.apache.subversion.javahl.ClientException;
public class cat {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
client.streamFileContent
(
args
[0], // target
Revision.HEAD
, // rev
Revision.HEAD
, // peg rev
System.out
); //output
}
}
Automating Subversion with Bindings
JavaHL
Example - Cat
Slide
126Slide127
import
org.apache.subversion.javahl.SVNClient
;import org.apache.subversion.javahl.types.*;
import org.apache.subversion.javahl.ClientException
;
public class cat {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
client.streamFileContent
(
args
[0], // target
Revision.HEAD
, // rev
Revision.HEAD
, // peg rev
System.out
); //output
}
}
Automating Subversion with Bindings
JavaHL
Example - Cat
Slide
127Slide128
import
org.apache.subversion.javahl.SVNClient
;
import org.apache.subversion.javahl.types
.*;
import
org.apache.subversion.javahl.ClientException
;
public class cat {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
client.streamFileContent
(
args
[0], // target
Revision.HEAD
, // rev
Revision.HEAD
, // peg rev
System.out
); //output
}
}
Automating Subversion with Bindings
JavaHL
Example - Cat
Slide
128Slide129
import
org.apache.subversion.javahl.SVNClient
;import org.apache.subversion.javahl.types
.*;
import org.apache.subversion.javahl.ClientException
;
public class cat {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
client.streamFileContent
(
args
[0], // target
Revision.HEAD
, // rev
Revision.HEAD
, // peg rev
System.out
); //output
}
}
Automating Subversion with Bindings
JavaHL
Example - Cat
Slide
129Slide130
import
org.apache.subversion.javahl.SVNClient
;import org.apache.subversion.javahl.types.*;
import org.apache.subversion.javahl.callback.*;
import org.apache.subversion.javahl.ClientException
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Map
;
import
java.io.UnsupportedEncodingException
;
public class log {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
List<
RevisionRange
>
revRanges
= new
ArrayList
<
RevisionRange
>(1);
revRanges.add
(new
RevisionRange
(
Revision.HEAD
,
Revision.getInstance
(0)));
Set<String>
revProps
= new
HashSet
<String>(1);
revProps.add
("
svn:log
");
Automating Subversion with Bindings
JavaHL
Example – Log (1/2)
Slide
130Slide131
import
org.apache.subversion.javahl.SVNClient
;import org.apache.subversion.javahl.types
.*;
import org.apache.subversion.javahl.callback
.*;
import
org.apache.subversion.javahl.ClientException
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Map
;
import
java.io.UnsupportedEncodingException
;
public class log {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
List<
RevisionRange
>
revRanges
= new
ArrayList
<
RevisionRange
>(1);
revRanges.add
(new
RevisionRange
(
Revision.HEAD
,
Revision.getInstance
(0)));
Set<String>
revProps
= new
HashSet
<String>(1);
revProps.add
("
svn:log
");
Automating Subversion with Bindings
JavaHL
Example – Log (1/2)
Slide
131Slide132
import
org.apache.subversion.javahl.SVNClient
;
import org.apache.subversion.javahl.types
.*;
import
org.apache.subversion.javahl.callback
.*;
import
org.apache.subversion.javahl.ClientException
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Map
;
import
java.io.UnsupportedEncodingException
;
public class log {
public static void main(String[]
args
)
throws
ClientException
{
SVNClient
client = new
SVNClient
();
List<
RevisionRange
>
revRanges
= new
ArrayList
<
RevisionRange
>(1);
revRanges.add
(new
RevisionRange
(
Revision.HEAD
,
Revision.getInstance
(0)));
Set<String>
revProps
= new
HashSet
<String>(1);
revProps.add
("
svn:log
");
Automating Subversion with Bindings
JavaHL
Example – Log (1/2)
Slide
132Slide133
client.logMessages
(args[0], // target Revision.HEAD
, //peg rev
revRanges, // rev ranges
true, // stop on copy
true, // discover path
false, // include merged revisions
revProps
, //
revprops
to get
0, // limit (0 = unlimited)
new
LogMessageCallback
() {
public void
singleMessage
(Set<
ChangePath
>
changedPaths
,
long revision,
Map<
String,byte
[]>
revprops
,
boolean
hasChildren
)
{
byte[] message =
revprops.get
("
svn:log
");
System.out.println
("r" + revision);
if (message != null) {
try {
System.out.println
(new String(message, "UTF-8"));
} catch (
UnsupportedEncodingException
e) { /* ignore */ }
}
System.out.println
("\n");
}
});
}
}
Automating Subversion with Bindings
JavaHL
Example – Log (2/2)
Slide
133Slide134
client.logMessages
(args[0], // target
Revision.HEAD, //peg rev
revRanges, // rev ranges
true, // stop on copy
true, // discover path
false, // include merged revisions
revProps
, //
revprops
to get
0, // limit (0 = unlimited)
new
LogMessageCallback
() {
public void
singleMessage
(Set<
ChangePath
>
changedPaths
,
long revision,
Map<
String,byte
[]>
revprops
,
boolean
hasChildren
)
{
byte[] message =
revprops.get
("
svn:log
");
System.out.println
("r" + revision);
if (message != null) {
try {
System.out.println
(new String(message, "UTF-8"));
} catch (
UnsupportedEncodingException
e) { /* ignore */ }
}
System.out.println
("\n");
}
});
}
}
Automating Subversion with Bindings
JavaHL
Example – Log (2/2)
Slide
134Slide135
client.logMessages
(args[0], // target
Revision.HEAD
, //peg rev
revRanges
, // rev ranges
true, // stop on copy
true, // discover path
false, // include merged revisions
revProps
, //
revprops
to get
0, // limit (0 = unlimited)
new
LogMessageCallback
() {
public void
singleMessage
(Set<
ChangePath
>
changedPaths
,
long revision,
Map<
String,byte
[]>
revprops
,
boolean
hasChildren
)
{
byte[] message =
revprops.get
("
svn:log
");
System.out.println
("r" + revision);
if (message != null) {
try {
System.out.println
(new String(message, "UTF-8"));
} catch (
UnsupportedEncodingException
e) { /* ignore */ }
}
System.out.println
("\n");
}
});
}
}
Automating Subversion with Bindings
JavaHL
Example – Log (2/2)
Slide
135Slide136
ResourcesSlide137
http://svn.ms/autosvnexamples
http
://subversion.apache.org/mailing-lists.html (particularly users@subversion.apache.org)http://subversion.apache.org/docs/
(C API and JavaHL documentation)http://svnbook.red-bean.com
/ (Chapter 8)perldoc
SVN::Client (et al)
http://svn.apache.org/repos/asf/subversion/
trunk/
http://www.wandisco.com/subversion/
download
http://
alagazam.net/
http://pysvn.tigris.org
/
http://svnkit.com
/
Automating Subversion with Bindings
Getting Help/Resources
Slide
137Slide138
Found a Bug? Have a fix for a bug? Want to write documentation?
Participate at
dev@subversion.apache.org mailing list.Automating Subversion with Bindings
Contributing
Slide
138Slide139
Questions?