Hi Stefan, > It appears the attachment is missing. Yeah, motoric memory took over and I sent the mail, while I intended to actually test the patches again before resending.
So, here's the updated _and_ tested patches, attached this time. Gr. Matthijs
[[[ Fix the python bindings for svn_auth_get_platform_specific_client_providers. The bindings were present, but due to a missing argout typemap for apr_array_header_t **providers, they threw a not implemented error. This was fixed for perl in r1035745, but was still broken for python and ruby. [in subversion/bindings/swig] * include/svn_containers.swg Add an argout typemap for apr_array_header_t **providers, using the new svn_swig_py_pointerlist_to_list. * python/libsvn_swig_py/swigutil_py.c Generalize convert_rangelist and svn_swig_py_ranglist_to_list to work with any apr_array containing pointers and rename them to convert_pointerlist and svn_swig_py_pointerlist_to_list respectively. * python/libsvn_swig_py/swigutil_py.h Rename svn_swig_py_ranglist_to_list to svn_swig_py_pointerlist_to_list. * python/test/client.py (test_platform_providers): Add testcase. [in /tools/examples] * get-location-segments.py Let this example use svn_auth_get_platform_specific_client_providers. Patch by: Matthijs Kooijman <matth...@stdin.nl> ]]] Index: subversion-trunk/subversion/bindings/swig/include/svn_containers.swg =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/include/svn_containers.swg 2012-01-06 10:10:47.872180699 +0100 +++ subversion-trunk/subversion/bindings/swig/include/svn_containers.swg 2012-02-07 16:20:36.906353455 +0100 @@ -825,8 +825,8 @@ #ifdef SWIGPYTHON %typemap(argout) apr_array_header_t **RANGELIST { %append_output - (svn_swig_py_rangelist_to_list(*$1, $descriptor(svn_merge_range_t *), - _global_py_pool)); + (svn_swig_py_pointerlist_to_list(*$1, $descriptor(svn_merge_range_t *), + _global_py_pool)); if (PyErr_Occurred()) { SWIG_fail; } @@ -873,3 +873,14 @@ $descriptor(svn_auth_provider_object_t *))); } #endif + +#ifdef SWIGPYTHON +%typemap(argout) apr_array_header_t **providers { + %append_output + (svn_swig_py_pointerlist_to_list(*$1, $descriptor(svn_auth_provider_object_t *), + _global_py_pool)); + if (PyErr_Occurred()) { + SWIG_fail; + } +} +#endif Index: subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c 2012-02-07 16:16:30.304976327 +0100 +++ subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c 2012-02-07 16:24:48.087755431 +0100 @@ -650,7 +650,7 @@ return convert_hash(hash, convert_string, NULL, NULL); } -static PyObject *convert_rangelist(void *value, void *ctx, PyObject *py_pool) +static PyObject *convert_pointerlist(void *value, void *ctx, PyObject *py_pool) { int i; PyObject *list; @@ -662,11 +662,11 @@ for (i = 0; i < array->nelts; i++) { - svn_merge_range_t *range = APR_ARRAY_IDX(array, i, svn_merge_range_t *); + void *ptr = APR_ARRAY_IDX(array, i, void *); PyObject *obj; int result; - obj = convert_to_swigtype(range, ctx, py_pool); + obj = convert_to_swigtype(ptr, ctx, py_pool); if (obj == NULL) goto error; @@ -681,18 +681,18 @@ return NULL; } -PyObject *svn_swig_py_rangelist_to_list(apr_array_header_t *rangelist, - swig_type_info *type, - PyObject *py_pool) +PyObject *svn_swig_py_pointerlist_to_list(apr_array_header_t *list, + swig_type_info *type, + PyObject *py_pool) { - return convert_rangelist(rangelist, type, py_pool); + return convert_pointerlist(list, type, py_pool); } PyObject *svn_swig_py_mergeinfo_to_dict(apr_hash_t *hash, swig_type_info *type, PyObject *py_pool) { - return convert_hash(hash, convert_rangelist, type, py_pool); + return convert_hash(hash, convert_pointerlist, type, py_pool); } static PyObject *convert_mergeinfo_hash(void *value, void *ctx, Index: subversion-trunk/tools/examples/get-location-segments.py =================================================================== --- subversion-trunk.orig/tools/examples/get-location-segments.py 2012-02-07 16:19:07.413853775 +0100 +++ subversion-trunk/tools/examples/get-location-segments.py 2012-02-07 16:20:36.914353499 +0100 @@ -125,7 +125,13 @@ core.svn_config_ensure(None) ctx = client.svn_client_create_context() - providers = [ + + # Make sure that these are at the start of the list, so passwords from + # gnome-keyring / kwallet are checked before asking for new passwords. + # Note that we don't pass our config here, since we can't seem to access + # ctx.config.config (ctx.config is opaque). + providers = core.svn_auth_get_platform_specific_client_providers(None, None) + providers.extend([ client.get_simple_provider(), core.svn_auth_get_ssl_server_trust_file_provider(), core.svn_auth_get_simple_prompt_provider(prompt_func_simple_prompt, 2), @@ -134,7 +140,8 @@ client.get_ssl_server_trust_file_provider(), client.get_ssl_client_cert_file_provider(), client.get_ssl_client_cert_pw_file_provider(), - ] + ]) + ctx.auth_baton = core.svn_auth_open(providers) ctx.config = core.svn_config_get_config(None) Index: subversion-trunk/subversion/bindings/swig/python/tests/client.py =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/tests/client.py 2012-01-06 10:10:47.856180623 +0100 +++ subversion-trunk/subversion/bindings/swig/python/tests/client.py 2012-02-07 16:20:36.914353499 +0100 @@ -374,6 +374,11 @@ self.assertEqual(readme_text, 'This is a test.\n') + def test_platform_providers(self): + providers = core.svn_auth_get_platform_specific_client_providers(None, None) + # Not much more we can test in this minimal environment. + self.assert_(isinstance(providers, list)) + def suite(): return unittest.defaultTestLoader.loadTestsFromTestCase( SubversionClientTestCase) Index: subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 2012-01-06 10:10:47.840180547 +0100 +++ subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 2012-02-07 16:20:36.914353499 +0100 @@ -135,9 +135,9 @@ /* helper function to convert an apr_array_header_t* (of svn_merge_range_t *) to a Python list */ SVN_SWIG_SWIGUTIL_EXPORT -PyObject *svn_swig_py_rangelist_to_list(apr_array_header_t *rangelist, - swig_type_info *type, - PyObject *py_pool); +PyObject *svn_swig_py_pointerlist_to_list(apr_array_header_t *list, + swig_type_info *type, + PyObject *py_pool); /* helper function to convert an apr_hash_t* (const char *->array of svn_merge_range_t *) to a Python dict */
[[[ Fix the ruby bindings for svn_auth_get_platform_specific_client_providers. The bindings were present, but due to a missing argout typemap for apr_array_header_t **providers, they threw a not implemented error. This was fixed for perl in r1035745 and for python in the previous commit, but was still broken for ruby. [in subversion/bindings/swig] * include/svn_containers.swg Add an argout typemap for apr_array_header_t **providers, using the new svn_swig_rb_apr_array_to_array_auth_provider_object. * ruby/libsvn_swig_ruby/swigutil_rb.c, ruby/libsvn_swig_ruby/swigutil_rb.h (svn_swig_rb_apr_array_to_array_auth_provider_object): Add function. * ruby/svn/core.rb (add_platform_specific_client_providers, add_providers): Add functions. [in tools/examples] * info.rb Add a new example that shows how to do remote access instead of working on an existing working copy (like the existing examples do). This example also shows how to call svn_auth_get_platform_specific_client_providers. Patch by: Matthijs Kooijman <matth...@stdin.nl> ]]] Index: subversion-trunk/subversion/bindings/swig/include/svn_containers.swg =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/include/svn_containers.swg 2012-02-07 16:20:36.906353455 +0100 +++ subversion-trunk/subversion/bindings/swig/include/svn_containers.swg 2012-02-07 16:25:20.339935397 +0100 @@ -884,3 +884,9 @@ } } #endif + +#ifdef SWIGRUBY +%typemap(argout) apr_array_header_t **providers { + %append_output(svn_swig_rb_apr_array_to_array_auth_provider_object(*$1)); +} +#endif Index: subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c 2012-01-06 10:10:47.652179654 +0100 +++ subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c 2012-02-07 16:25:37.444030832 +0100 @@ -1313,6 +1313,9 @@ DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_merge_range, c2r_merge_range_dup, EMPTY_CPP_ARGUMENT, svn_merge_range_t *, NULL) +DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_auth_provider_object, + c2r_swig_type, EMPTY_CPP_ARGUMENT, + svn_auth_provider_object_t *, "svn_auth_provider_object_t*") static VALUE c2r_merge_range_array(void *value, void *ctx) Index: subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h 2012-01-06 10:10:47.636179576 +0100 +++ subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h 2012-02-07 16:25:37.428030743 +0100 @@ -154,6 +154,8 @@ VALUE svn_swig_rb_apr_array_to_array_external_item2(const apr_array_header_t *ary); SVN_RB_SWIG_SWIGUTIL_EXPORT VALUE svn_swig_rb_apr_array_to_array_merge_range(const apr_array_header_t *ary); +SVN_RB_SWIG_SWIGUTIL_EXPORT +VALUE svn_swig_rb_apr_array_to_array_auth_provider_object(const apr_array_header_t *ary); SVN_RB_SWIG_SWIGUTIL_EXPORT VALUE svn_swig_rb_prop_apr_array_to_hash_prop(const apr_array_header_t *ary); Index: subversion-trunk/tools/examples/info.rb =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ subversion-trunk/tools/examples/info.rb 2012-02-07 16:25:37.544031390 +0100 @@ -0,0 +1,54 @@ +# Example based on a blogpost by Mark Deepwell +# http://www.markdeepwell.com/2010/06/ruby-subversion-bindings/ + +require "svn/core" +require "svn/client" +require "svn/wc" +require "svn/repos" + +# Prompt function mimicking svn's own prompt +simple_prompt = Proc.new do + |result, realm, username, default, may_save, pool| + + puts "Authentication realm: #{realm}" + if username != nil + result.username = username + else + print "Username: " + result.username = STDIN.gets.strip + end + print "Password for '#{result.username}': " + result.password = STDIN.gets.strip +end + + +if ARGV.length != 1 + puts "Usage: info.rb URL[@REV]" +else + ctx = Svn::Client::Context.new() + ctx.add_platform_specific_client_providers + ctx.add_simple_provider + ctx.add_simple_prompt_provider(2, simple_prompt) + ctx.add_username_provider + ctx.add_ssl_server_trust_file_provider + ctx.add_ssl_client_cert_file_provider + ctx.add_ssl_client_cert_pw_file_provider + + repos_uri, revision = ARGV[0].split("@", 2) + if revision + revision = Integer(revision) + end + + begin + ctx.info(repos_uri, revision) do |path, info| + puts("Url: #{info.url}") + puts("Last changed rev: #{info.last_changed_rev}") + puts("Last changed author: #{info.last_changed_author}") + puts("Last changed date: #{info.last_changed_date}") + puts("Kind: #{info.kind}") + end + rescue Svn::Error => e + # catch a generic svn error + raise "Failed to retrieve SVN info at revision " + revision.to_s + end +end Index: subversion-trunk/subversion/bindings/swig/ruby/svn/core.rb =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/ruby/svn/core.rb 2012-01-06 10:10:47.624179521 +0100 +++ subversion-trunk/subversion/bindings/swig/ruby/svn/core.rb 2012-02-07 16:25:20.343935419 +0100 @@ -279,6 +279,10 @@ add_prompt_provider("ssl_client_cert_pw", args, prompt, klass) end + def add_platform_specific_client_providers(config=nil) + add_providers(Core.auth_get_platform_specific_client_providers(config)) + end + private def add_prompt_provider(name, args, prompt, credential_class) real_prompt = Proc.new do |*prompt_args| @@ -294,6 +298,10 @@ end def add_provider(provider) + add_providers([provider]) + end + + def add_providers(new_providers) if auth_baton providers = auth_baton.providers parameters = auth_baton.parameters @@ -301,7 +309,7 @@ providers = [] parameters = {} end - self.auth_baton = AuthBaton.new(providers + [provider], parameters) + self.auth_baton = AuthBaton.new(providers + new_providers, parameters) end end
[[[ Allow setting the SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC authentication parameter from the perl, python and ruby bindings. This parameter cannot be set using the regular svn_auth_set_parameter function, since the function from perl/python/ruby space must be wrapped in a C function to allow it to be called. For this reason, a new function, svn_auth_set_gnome_keyring_unlock_prompt_func, is introduced (in the bindings only). [in subversion/bindings/swig] * core.i (svn_auth_set_gnome_keyring_unlock_prompt_func): Add function and setup corresponding authprompt_callback_typemap. * perl/libsvn_swig_perl/swigutil_pl.c, perl/libsvn_swig_perl/swigutil_pl.h (svn_swig_pl_thunk_gnome_keyring_unlock_prompt): Add function (called by authprompt_callback_typemap) * python/libsvn_swig_py/swigutil_py.c python/libsvn_swig_py/swigutil_py.h (svn_swig_py_auth_gnome_keyring_unlock_prompt_func): Add function (called by authprompt_callback_typemap) * ruby/libsvn_swig_ruby/swigutil_rb.c, ruby/libsvn_swig_ruby/swigutil_rb.h (svn_swig_rb_auth_gnome_keyring_unlock_prompt_func): Add function (called by authprompt_callback_typemap) * perl/native/t/3client.t, python/tests/client.py Add test for svn_auth_set_gnome_keyring_unlock_prompt_func. [in tools/examples] * get-location-segments.py, info.rb Use the new svn_auth_set_gnome_keyring_unlock_prompt_func function. Patch by: Matthijs Kooijman <matth...@stdin.nl> ]]] Index: subversion-trunk/subversion/bindings/swig/core.i =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/core.i 2012-01-06 10:10:47.452178703 +0100 +++ subversion-trunk/subversion/bindings/swig/core.i 2012-02-07 16:25:21.547942137 +0100 @@ -699,6 +699,34 @@ %authprompt_callback_typemap(ssl_client_cert) %authprompt_callback_typemap(ssl_client_cert_pw) +%{ +#ifdef SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC +/* Helper function to set the gnome-keyring unlock prompt function. This + * C function accepts an auth baton, a function and a prompt baton, but + * the below callback_typemap uses both the function and the prompt + * baton, so the resulting binding has just two arguments: The auth + * baton and the prompt function. + * The prompt function should again have two arguments: The keyring name + * (string) and a pool (except for the ruby version, which doesn't have + * the pool argument). It should return the entered password (string). + * This binding generated for this function generates a reference to the + * prompt function that was passed into this. The caller should store + * that reference somewhere, to prevent the function from being garbage + * collected... + */ +static void svn_auth_set_gnome_keyring_unlock_prompt_func(svn_auth_baton_t *ab, + svn_auth_gnome_keyring_unlock_prompt_func_t prompt_func, + void *prompt_baton) { + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC, + prompt_func); + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON, + prompt_baton); +} +#endif +%} + +%authprompt_callback_typemap(gnome_keyring_unlock) + /* ----------------------------------------------------------------------- * For all the various functions that set a callback baton create a reference * for the baton (which in this case is an SV pointing to the callback) @@ -764,6 +792,12 @@ %include svn_pools_h.swg %include svn_version_h.swg +/* This is the function defined above */ +void svn_auth_set_gnome_keyring_unlock_prompt_func(svn_auth_baton_t *ab, + svn_auth_gnome_keyring_unlock_prompt_func_t prompt_func, + void *prompt_baton); + + /* The constant SVN_PROP_REVISION_ALL_PROPS is a C fragment, not a single data value, so the SWIG parser will raise a 305 warning if we don't suppress it. */ Index: subversion-trunk/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c 2012-01-06 10:10:47.348178211 +0100 +++ subversion-trunk/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c 2012-02-07 16:25:21.547942137 +0100 @@ -984,6 +984,34 @@ return SVN_NO_ERROR; } +svn_error_t *svn_swig_pl_thunk_gnome_keyring_unlock_prompt(char **keyring_password, + const char *keyring_name, + void *baton, + apr_pool_t *pool) +{ + SV *result; + STRLEN len; + /* The baton is the actual prompt function passed from perl, so we + * call that one and process the result. */ + svn_swig_pl_callback_thunk(CALL_SV, + baton, &result, + "sS", keyring_name, + pool, POOLINFO); + if (!SvOK(result) || result == &PL_sv_undef) { + *keyring_password = NULL; + } + else if (SvPOK(result)) { + *keyring_password = apr_pstrdup(pool, SvPV(result, len)); + } + else { + SvREFCNT_dec(result); + croak("not a string"); + } + + SvREFCNT_dec(result); + return SVN_NO_ERROR; +} + svn_error_t *svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t **cred, void *baton, const char *realm, Index: subversion-trunk/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h 2012-01-06 10:10:47.364178285 +0100 +++ subversion-trunk/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h 2012-02-07 16:25:21.551942160 +0100 @@ -144,6 +144,11 @@ SV *perl_callbacks, apr_pool_t *pool); +/* thunked gnome_keyring_unlock_prompt callback function */ +svn_error_t *svn_swig_pl_thunk_gnome_keyring_unlock_prompt(char **keyring_password, + const char *keyring_name, + void *baton, + apr_pool_t *pool); /* thunked simple_prompt callback function */ svn_error_t *svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t **cred, void *baton, Index: subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c 2012-02-07 16:24:48.087755431 +0100 +++ subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c 2012-02-07 16:25:21.551942160 +0100 @@ -2804,6 +2804,41 @@ } svn_error_t * +svn_swig_py_auth_gnome_keyring_unlock_prompt_func(char **keyring_passwd, + const char *keyring_name, + void *baton, + apr_pool_t *pool) +{ + /* The baton is the actual prompt function passed from python */ + PyObject *function = baton; + PyObject *result; + svn_error_t *err = SVN_NO_ERROR; + *keyring_passwd = NULL; + + if ((function == NULL) || (function == Py_None)) + return SVN_NO_ERROR; + + svn_swig_py_acquire_py_lock(); + + if ((result = PyObject_CallFunction(function, + (char *)"sO&", + keyring_name, + make_ob_pool, pool)) == NULL) + { + err = callback_exception_error(); + } + else + { + *keyring_passwd = make_string_from_ob(result, pool); + Py_DECREF(result); + } + + svn_swig_py_release_py_lock(); + return err; +} + + +svn_error_t * svn_swig_py_auth_simple_prompt_func(svn_auth_cred_simple_t **cred, void *baton, const char *realm, Index: subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 2012-02-07 16:20:36.914353499 +0100 +++ subversion-trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 2012-02-07 16:25:21.551942160 +0100 @@ -423,6 +423,13 @@ /* auth provider callbacks */ SVN_SWIG_SWIGUTIL_EXPORT +svn_error_t * svn_swig_py_auth_gnome_keyring_unlock_prompt_func( + char **keyring_passwd, + const char *keyring_name, + void *baton, + apr_pool_t *pool); + +SVN_SWIG_SWIGUTIL_EXPORT svn_error_t *svn_swig_py_auth_simple_prompt_func( svn_auth_cred_simple_t **cred, void *baton, Index: subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c 2012-02-07 16:25:20.339935397 +0100 +++ subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c 2012-02-07 16:25:21.555942182 +0100 @@ -2963,6 +2963,41 @@ } svn_error_t * +svn_swig_rb_auth_gnome_keyring_unlock_prompt_func(char **keyring_passwd, + const char *keyring_name, + void *baton, + apr_pool_t *pool) +{ + svn_error_t *err = SVN_NO_ERROR; + VALUE proc, rb_pool; + *keyring_passwd = NULL; + + svn_swig_rb_from_baton((VALUE)baton, &proc, &rb_pool); + + if (!NIL_P(proc)) { + char error_message[] = + "svn_auth_gnome_keyring_unlock_prompt_func_t should" + "return a string, not '%s'."; + + callback_baton_t cbb; + VALUE result; + + cbb.receiver = proc; + cbb.message = id_call; + cbb.args = rb_ary_new3(1, c2r_string2(keyring_name)); + result = invoke_callback_handle_error((VALUE)(&cbb), rb_pool, &err); + + if (!NIL_P(result)) { + if (!RTEST(rb_obj_is_kind_of(result, rb_cString))) + rb_raise(rb_eTypeError, error_message, r2c_inspect(result)); + *keyring_passwd = (char *)r2c_string(result, NULL, pool); + } + } + + return err; +} + +svn_error_t * svn_swig_rb_auth_username_prompt_func(svn_auth_cred_username_t **cred, void *baton, const char *realm, Index: subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h 2012-02-07 16:25:20.343935419 +0100 +++ subversion-trunk/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h 2012-02-07 16:25:21.555942182 +0100 @@ -380,6 +380,13 @@ /* auth provider callbacks */ SVN_RB_SWIG_SWIGUTIL_EXPORT +svn_error_t * svn_swig_rb_auth_gnome_keyring_unlock_prompt_func( + char **keyring_passwd, + const char *keyring_name, + void *baton, + apr_pool_t *pool); + +SVN_RB_SWIG_SWIGUTIL_EXPORT svn_error_t *svn_swig_rb_auth_simple_prompt_func( svn_auth_cred_simple_t **cred, void *baton, Index: subversion-trunk/subversion/bindings/swig/perl/native/t/3client.t =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/perl/native/t/3client.t 2012-01-06 10:10:47.332178134 +0100 +++ subversion-trunk/subversion/bindings/swig/perl/native/t/3client.t 2012-02-07 16:25:21.555942182 +0100 @@ -20,7 +20,7 @@ # # -use Test::More tests => 119; +use Test::More tests => 120; use strict; # shut up about variables that are only used once. @@ -477,6 +477,23 @@ } ok($ok, 'svn_auth_get_platform_specific_client_providers returns _p_svn_auth_provider_object_t\'s'); +# Test setting gnome_keyring prompt function. This just sets the proper +# attributes in the auth baton and checks the return value (which should +# be a reference to the passed function reference). This does not +# actually try the prompt, since that would require setting up a +# gnome-keyring-daemon... +sub gnome_keyring_unlock_prompt { + my $keyring_name = shift; + my $pool = shift; + + 'test'; +} + +my $callback = \&gnome_keyring_unlock_prompt; +my $result = SVN::Core::auth_set_gnome_keyring_unlock_prompt_func( + $ctx->auth(), $callback); +is(${$result}, $callback, 'auth_set_gnome_keyring_unlock_prompt_func result equals paramter'); + END { diag('cleanup'); rmtree($testpath); Index: subversion-trunk/subversion/bindings/swig/python/tests/client.py =================================================================== --- subversion-trunk.orig/subversion/bindings/swig/python/tests/client.py 2012-02-07 16:20:36.914353499 +0100 +++ subversion-trunk/subversion/bindings/swig/python/tests/client.py 2012-02-07 16:25:21.555942182 +0100 @@ -379,6 +379,17 @@ # Not much more we can test in this minimal environment. self.assert_(isinstance(providers, list)) + def testGnomeKeyring(self): + # This tests setting the gnome-keyring unlock prompt function as an + # auth baton parameter. It doesn't actually call gnome-keyring + # stuff, since that would require having a gnome-keyring running. We + # just test if this doesn't error out, there's not even a return + # value to test. + def prompt_func(realm_string, pool): + return "Foo" + + core.svn_auth_set_gnome_keyring_unlock_prompt_func(self.client_ctx.auth_baton, prompt_func) + def suite(): return unittest.defaultTestLoader.loadTestsFromTestCase( SubversionClientTestCase) Index: subversion-trunk/tools/examples/get-location-segments.py =================================================================== --- subversion-trunk.orig/tools/examples/get-location-segments.py 2012-02-07 16:20:36.914353499 +0100 +++ subversion-trunk/tools/examples/get-location-segments.py 2012-02-07 16:25:21.555942182 +0100 @@ -105,6 +105,9 @@ simple_cred.may_save = False return simple_cred +def prompt_func_gnome_keyring_prompt(keyring, pool): + return getpass.getpass(prompt="Password for '%s' GNOME keyring: " % keyring) + def main(): try: url, peg_revision, start_revision, end_revision = parse_args(sys.argv[1:]) @@ -145,6 +148,9 @@ ctx.auth_baton = core.svn_auth_open(providers) ctx.config = core.svn_config_get_config(None) + if hasattr(core, 'svn_auth_set_gnome_keyring_unlock_prompt_func'): + core.svn_auth_set_gnome_keyring_unlock_prompt_func(ctx.auth_baton, prompt_func_gnome_keyring_prompt) + ra_callbacks = ra.callbacks_t() ra_callbacks.auth_baton = ctx.auth_baton ra_session = ra.open(url, ra_callbacks, None, ctx.config) Index: subversion-trunk/tools/examples/info.rb =================================================================== --- subversion-trunk.orig/tools/examples/info.rb 2012-02-07 16:25:20.343935419 +0100 +++ subversion-trunk/tools/examples/info.rb 2012-02-07 16:25:21.559942204 +0100 @@ -1,7 +1,9 @@ +#!/usr/bin/ruby # Example based on a blogpost by Mark Deepwell # http://www.markdeepwell.com/2010/06/ruby-subversion-bindings/ require "svn/core" +require "svn/ext/core" require "svn/client" require "svn/wc" require "svn/repos" @@ -21,6 +23,12 @@ result.password = STDIN.gets.strip end +gnome_keyring_prompt = Proc.new do + |keyring_name| + + print "Password for '#{keyring_name}' GNOME keyring: " + STDIN.gets.strip +end if ARGV.length != 1 puts "Usage: info.rb URL[@REV]" @@ -34,6 +42,12 @@ ctx.add_ssl_client_cert_file_provider ctx.add_ssl_client_cert_pw_file_provider + # Allow asking for the gnome keyring password, in case the keyring is + # locked. + if Svn::Ext::Core.respond_to?(:svn_auth_set_gnome_keyring_unlock_prompt_func) + Svn::Ext::Core::svn_auth_set_gnome_keyring_unlock_prompt_func(ctx.auth_baton, gnome_keyring_prompt) + end + repos_uri, revision = ARGV[0].split("@", 2) if revision revision = Integer(revision)
signature.asc
Description: Digital signature