Hi, while trying to use svn_wc_parse_externals_description3 from Perl I stumbled over a fex things. Patches below are against trunk.
perl-bindings-1.patch [[[ Make svn_wc_parse_externals_description3 available from Perl bindings. * subversion/bindings/swig/include/svn_containers.swg: Add output typemap for APR array of svn_wc_external_item2_t. * subversion/bindings/swig/perl/native/Wc.pm: Document function svn_wc_parse_externals_description3. Add the magic to access struct svn_wc_external_item2_t as an object and document its methods. * subversion/bindings/swig/perl/native/Core.pm: Fix a typo that prevented the use of _p_svn_opt_revision_value_t objects. ]]] perl-bindings-2.patch [[[ Replace inline typemap with a function. * subversion/bindings/swig/include/svn_types.swg: The bulky input typemap for svn_opt_revision_t is inlined by Swig for each use in the generated Perl bindings. Move its body ... * subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c (svn_swig_pl_set_revision): ... to a new function here. * subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h: Add function prototype. ]]] perl-bindings-3.patch [[[ Documentation fix for SVN::Ra. * subversion/bindings/swig/perl/native/Ra.pm Fix examples: the $path parameter for SVN::Ra::get_dir() and SVN::Ra::get_file() must not start with a slash. ]]] Cheers, Roderich
Index: subversion/bindings/swig/include/svn_containers.swg =================================================================== --- subversion/bindings/swig/include/svn_containers.swg (revision 1440883) +++ subversion/bindings/swig/include/svn_containers.swg (working copy) @@ -492,6 +492,12 @@ } } #endif +#ifdef SWIGPERL +%typemap(argout) apr_array_header_t **externals_p { + %append_output + (svn_swig_pl_convert_array(*$1, $descriptor(svn_wc_external_item2_t *))); +} +#endif #ifdef SWIGRUBY %typemap(argout) apr_array_header_t **externals_p { %append_output(svn_swig_rb_apr_array_to_array_external_item2(*$1)); Index: subversion/bindings/swig/perl/native/Wc.pm =================================================================== --- subversion/bindings/swig/perl/native/Wc.pm (revision 1440883) +++ subversion/bindings/swig/perl/native/Wc.pm (working copy) @@ -13,12 +13,29 @@ Incomplete +=cut + +swig_init_asp_dot_net_hack($SVN::Core::gpool); + +=head1 FUNCTIONS + +=over 4 + +=item SVN::Wc::parse_externals_description3($parent_directory, $desc, $canonicalize_url, $pool); + +Parse the string $desc as an C<svn:externals> value and return a reference +to an array of L<_p_svn_wc_external_item2_t|svn_wc_external_item2_t> objects. +If $canonicalize_url is true, canonicalize the C<url> member of those objects. +$parent_directory is only used in constructing error strings. + +=back + +=cut + =head1 OBJECTS =cut -swig_init_asp_dot_net_hack($SVN::Core::gpool); - package _p_svn_wc_t; =head2 svn_wc_status2_t @@ -228,6 +245,42 @@ # as method. use SVN::Base qw(Wc svn_wc_entry_t_); +=head2 svn_wc_external_item2_t + +=over 4 + +=item $ext-E<gt>target_dir() + +The name of the subdirectory into which this external should be +checked out. This is relative to the parent directory that +holds this external item. + +=item $ext-E<gt>url() + +Where to check out from. This is possibly a relative external URL, as +allowed in externals definitions, but without the peg revision. + +=item $ext-E<gt>revision() + +What revision to check out, +a L<svn_opt_revision_t|SVN::Core/svn_opt_revision_t> object. +The only valid kind()s for this are $SVN::Core::opt_revision_number, +$SVN::Core::opt_revision_date, and $SVN::Core::opt_revision_head. + +=item $ext-E<gt>peg_revision() + +The peg revision to use when checking out, +a L<svn_opt_revision_t|SVN::Core/svn_opt_revision_t> object. +The only valid kind()s for this are $SVN::Core::opt_revision_number, +$SVN::Core::opt_revision_date, and $SVN::Core::opt_revision_head. + +=back + +=cut + +package _p_svn_wc_external_item2_t; +use SVN::Base qw(Wc svn_wc_external_item2_t_); + =head1 CONSTANTS =head2 SVN::Wc::Notify::Action Index: subversion/bindings/swig/perl/native/Core.pm =================================================================== --- subversion/bindings/swig/perl/native/Core.pm (revision 1440883) +++ subversion/bindings/swig/perl/native/Core.pm (working copy) @@ -774,8 +774,8 @@ =cut -package _p_svn_opt_revision_t_value; -use SVN::Base qw(Core svn_opt_revision_t_value_); +package _p_svn_opt_revision_value_t; +use SVN::Base qw(Core svn_opt_revision_value_t_); package _p_svn_config_t; use SVN::Base qw(Core svn_config_);
Index: subversion/bindings/swig/include/svn_types.swg =================================================================== --- subversion/bindings/swig/include/svn_types.swg (revision 1440883) +++ subversion/bindings/swig/include/svn_types.swg (working copy) @@ -1170,52 +1170,7 @@ #ifdef SWIGPERL %typemap(in) svn_opt_revision_t * (svn_opt_revision_t rev) { $1 = &rev; - if ($input == NULL || $input == &PL_sv_undef || !SvOK($input)) { - rev.kind = svn_opt_revision_unspecified; - } - else if (sv_isobject($input) && sv_derived_from($input, "_p_svn_opt_revision_t")) { - SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, 0); - } - else if (looks_like_number($input)) { - rev.kind = svn_opt_revision_number; - rev.value.number = SvIV($input); - } - else if (SvPOK($input)) { - char *input = SvPV_nolen($input); - if (svn_cstring_casecmp(input, "BASE") == 0) - rev.kind = svn_opt_revision_base; - else if (svn_cstring_casecmp(input, "HEAD") == 0) - rev.kind = svn_opt_revision_head; - else if (svn_cstring_casecmp(input, "WORKING") == 0) - rev.kind = svn_opt_revision_working; - else if (svn_cstring_casecmp(input, "COMMITTED") == 0) - rev.kind = svn_opt_revision_committed; - else if (svn_cstring_casecmp(input, "PREV") == 0) - rev.kind = svn_opt_revision_previous; - else if (*input == '{') { - svn_boolean_t matched; - apr_time_t tm; - svn_error_t *err; - - char *end = strchr(input,'}'); - if (!end) - SWIG_croak("unknown opt_revision_t type"); - *end = '\0'; - err = svn_parse_date (&matched, &tm, input + 1, apr_time_now(), - svn_swig_pl_make_pool ((SV *)NULL)); - if (err) { - svn_error_clear (err); - SWIG_croak("unknown opt_revision_t type"); - } - if (!matched) - SWIG_croak("unknown opt_revision_t type"); - - rev.kind = svn_opt_revision_date; - rev.value.date = tm; - } else - SWIG_croak("unknown opt_revision_t type"); - } else - SWIG_croak("unknown opt_revision_t type"); + svn_swig_pl_set_revision(&rev, $input); } #endif Index: subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c =================================================================== --- subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c (revision 1440883) +++ subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c (working copy) @@ -36,6 +36,7 @@ #include "svn_pools.h" #include "svn_opt.h" +#include "svn_time.h" #include "svn_private_config.h" #include "swig_perl_external_runtime.swg" @@ -313,6 +314,65 @@ NULL); } +/* perl -> c svn_opt_revision_t conversion */ +void svn_swig_pl_set_revision(svn_opt_revision_t *rev, SV *source) +{ + if (source == NULL || source == &PL_sv_undef || !SvOK(source)) { + rev->kind = svn_opt_revision_unspecified; + } + else if (sv_isobject(source) && sv_derived_from(source, "_p_svn_opt_revision_t")) { + SWIG_ConvertPtr(source, (void **)&rev, _SWIG_TYPE("svn_opt_revision_t *"), 0); + } + else if (looks_like_number(source)) { + rev->kind = svn_opt_revision_number; + rev->value.number = SvIV(source); + } + else if (SvPOK(source)) { + char *input = SvPV_nolen(source); + if (svn_cstring_casecmp(input, "BASE") == 0) + rev->kind = svn_opt_revision_base; + else if (svn_cstring_casecmp(input, "HEAD") == 0) + rev->kind = svn_opt_revision_head; + else if (svn_cstring_casecmp(input, "WORKING") == 0) + rev->kind = svn_opt_revision_working; + else if (svn_cstring_casecmp(input, "COMMITTED") == 0) + rev->kind = svn_opt_revision_committed; + else if (svn_cstring_casecmp(input, "PREV") == 0) + rev->kind = svn_opt_revision_previous; + else if (*input == '{') { + svn_boolean_t matched; + apr_time_t tm; + svn_error_t *err; + + char *end = strchr(input,'}'); + if (!end) + croak("unknown opt_revision_t string \"%s\": " + "missing closing brace for \"{DATE}\""); + *end = '\0'; + err = svn_parse_date (&matched, &tm, input + 1, apr_time_now(), + svn_swig_pl_make_pool ((SV *)NULL)); + if (err) { + svn_error_clear (err); + croak("unknown opt_revision_t string \"{%s}\": " + "internal svn_parse_date error", input + 1); + } + if (!matched) + croak("unknown opt_revision_t string \"{%s}\": " + "svn_parse_date failed to parse it", input + 1); + + rev->kind = svn_opt_revision_date; + rev->value.date = tm; + } else + croak("unknown opt_revision_t string \"%s\": must be one of " + "\"BASE\", \"HEAD\", \"WORKING\", \"COMMITTED\", " + "\"PREV\" or a \"{DATE}\"", input); + } else + croak("unknown opt_revision_t type: must be undef, a number, " + "a string (one of \"BASE\", \"HEAD\", \"WORKING\", " + "\"COMMITTED\", \"PREV\" or a \"{DATE}\") " + "or a _p_svn_opt_revision_t object"); +} + /* put the va_arg in stack and invoke caller_func with func. fmt: * O: perl object Index: subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h =================================================================== --- subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h (revision 1440883) +++ subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h (working copy) @@ -106,6 +106,8 @@ SV *svn_swig_pl_revnums_to_list(const apr_array_header_t *array); +void svn_swig_pl_set_revision(svn_opt_revision_t *rev, SV *source); + /* thunked log receiver function. */ svn_error_t * svn_swig_pl_thunk_log_receiver(void *py_receiver, apr_hash_t *changed_paths,
Index: subversion/bindings/swig/perl/native/Ra.pm =================================================================== --- subversion/bindings/swig/perl/native/Ra.pm (revision 1440883) +++ subversion/bindings/swig/perl/native/Ra.pm (working copy) @@ -257,9 +257,9 @@ the user and stored in the repository fs, but non-tweakable ones generated by the SCM system itself (e.g. 'wcprops', 'entryprops', etc). - my ($dirents, undef, $props) = $ra->get_dir('/trunk/dir', 123); + my ($dirents, undef, $props) = $ra->get_dir('trunk/dir', 123); my ($dirents, $fetched_revnum, $props) = $ra->get_dir( - '/trunk/dir', $SVN::Core::INVALID_REVNUM); + 'trunk/dir', $SVN::Core::INVALID_REVNUM); =item $ra-E<gt>get_file($path, $revnum, $fh) @@ -281,15 +281,15 @@ generated by the SCM system itself (e.g. 'wcprops', 'entryprops', etc). my (undef, $props) = $ra->get_file( - '/trunk/foo', 123, undef); + 'trunk/foo', 123, undef); open my $fh, '>', 'tmp_out' or die "error opening file: $!"; my (undef, $props) = $ra->get_file( - '/trunk/foo', 123, $fh); + 'trunk/foo', 123, $fh); my ($fetched_revnum, $props) = $ra->get_file( - '/trunk/foo', $SVN::Core::INVALID_REVNUM, $fh); + 'trunk/foo', $SVN::Core::INVALID_REVNUM, $fh); =item $ra-E<gt>get_file_revs($path, $start, $end, \&callback)