1 //
2 // ====================================================================
3 // Copyright (c) 2003-2009 Barry A Scott.  All rights reserved.
4 //
5 // This software is licensed as described in the file LICENSE.txt,
6 // which you should have received as part of this distribution.
7 //
8 // ====================================================================
9 //
10 #include "pysvn_svnenv.hpp"
11 #include "svn_config.h"
12 #include "svn_pools.h"
13 #include "CXX/Objects.hxx"
14 
15 //--------------------------------------------------------------------------------
16 //
17 //        SvnException
18 //
19 //--------------------------------------------------------------------------------
SvnException(svn_error_t * error)20 SvnException::SvnException( svn_error_t *error )
21 : m_message()
22 , m_exception_arg()
23 {
24     std::string whole_message;
25 
26     // set the error to be a list of (code, message) tuples
27     Py::List error_list;
28     while( error != NULL )
29     {
30         Py::Tuple t( 2 );
31 
32         if( !whole_message.empty() )
33         {
34             whole_message += "\n";
35         }
36 
37         if( error->message != NULL )
38         {
39             t[0] = Py::String( error->message );
40             whole_message += error->message;
41         }
42         else
43         {
44             char buffer[256];
45             buffer[0] = '\0';
46 
47             svn_strerror( error->apr_err, buffer, sizeof( buffer ) );
48             whole_message += buffer;
49             t[0] = Py::String( buffer );
50         }
51         t[1] = Py::Int( error->apr_err );
52         error_list.append( t );
53 
54         error = error->child;
55     }
56     m_message = Py::String( whole_message );
57     Py::Tuple arg_list(2);
58     arg_list[0] = m_message;
59     arg_list[1] = error_list;
60 
61     m_exception_arg = arg_list;
62 
63     svn_error_clear( error );
64 }
65 
SvnException(const SvnException & other)66 SvnException::SvnException( const SvnException &other )
67 : m_code( other.m_code )
68 , m_message( other.m_message )
69 , m_exception_arg( other.m_exception_arg )
70 { }
71 
~SvnException()72 SvnException::~SvnException()
73 { }
74 
message()75 Py::String &SvnException::message()
76 {
77     return m_message;
78 }
79 
code()80 apr_status_t SvnException::code()
81 {
82     return m_code;
83 }
84 
pythonExceptionArg(int style)85 Py::Object &SvnException::pythonExceptionArg( int style )
86 {
87     if( style == 1 )
88     {
89         return m_exception_arg;
90     }
91     else
92     {
93         return m_message;
94     }
95 }
96 
97 //--------------------------------------------------------------------------------
98 //
99 //        SvnContext
100 //
101 //--------------------------------------------------------------------------------
102 #if defined( PYSVN_HAS_CONTEXT_LOG_MSG2 )
handlerLogMsg2(const char ** log_msg,const char ** tmp_file,const apr_array_header_t * commit_items,void * baton,apr_pool_t * pool)103 extern "C" svn_error_t *handlerLogMsg2
104     (
105     const char **log_msg,
106     const char **tmp_file,
107     const apr_array_header_t *commit_items,
108     void *baton,
109     apr_pool_t *pool
110     )
111 {
112     SvnContext *context = SvnContext::castBaton( baton );
113 
114     std::string msg;
115 
116     if (!context->contextGetLogMessage( msg ) )
117         return svn_error_create( SVN_ERR_CANCELLED, NULL, "" );
118 
119     *log_msg = svn_string_ncreate( msg.data(), msg.length(), pool )->data;
120     *tmp_file = NULL;
121 
122     return SVN_NO_ERROR;
123 }
124 #else
handlerLogMsg(const char ** log_msg,const char ** tmp_file,apr_array_header_t * commit_items,void * baton,apr_pool_t * pool)125 extern "C" svn_error_t *handlerLogMsg
126     (
127     const char **log_msg,
128     const char **tmp_file,
129     apr_array_header_t *commit_items,
130     void *baton,
131     apr_pool_t *pool
132     )
133 {
134     SvnContext *context = SvnContext::castBaton( baton );
135 
136     std::string msg;
137 
138     if (!context->contextGetLogMessage( msg ) )
139         return svn_error_create( SVN_ERR_CANCELLED, NULL, "" );
140 
141     *log_msg = svn_string_ncreate( msg.data(), msg.length(), pool )->data;
142     *tmp_file = NULL;
143 
144     return SVN_NO_ERROR;
145 }
146 #endif
147 
148 #if defined( PYSVN_HAS_CONTEXT_NOTIFY2 )
handlerNotify2(void * baton,const svn_wc_notify_t * notify,apr_pool_t * pool)149 extern "C" void handlerNotify2
150     (
151     void *baton,
152     const svn_wc_notify_t *notify,
153     apr_pool_t *pool
154     )
155 {
156     SvnContext *context = SvnContext::castBaton( baton );
157 
158     context->contextNotify2( notify, pool );
159 }
160 #else
handlerNotify(void * baton,const char * path,svn_wc_notify_action_t action,svn_node_kind_t kind,const char * mime_type,svn_wc_notify_state_t content_state,svn_wc_notify_state_t prop_state,svn_revnum_t revision)161 extern "C" void handlerNotify
162     (
163     void * baton,
164     const char *path,
165     svn_wc_notify_action_t action,
166     svn_node_kind_t kind,
167     const char *mime_type,
168     svn_wc_notify_state_t content_state,
169     svn_wc_notify_state_t prop_state,
170     svn_revnum_t revision
171     )
172 {
173     pysvn_bpt();
174 
175     SvnContext *context = SvnContext::castBaton( baton );
176 
177     context->contextNotify( path, action, kind, mime_type, content_state, prop_state, revision );
178 }
179 #endif
180 
181 #if defined( PYSVN_HAS_CONTEXT_PROGRESS )
handlerProgress(apr_off_t progress,apr_off_t total,void * baton,apr_pool_t * pool)182 extern "C" void handlerProgress
183     (
184     apr_off_t progress,
185     apr_off_t total,
186     void *baton,
187     apr_pool_t *pool
188     )
189 {
190     SvnContext *context = SvnContext::castBaton( baton );
191 
192     context->contextProgress( progress, total );
193 }
194 #endif
195 
196 #if defined( PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC )
handlerConflictResolver(svn_wc_conflict_result_t ** result,const svn_wc_conflict_description_t * description,void * baton,apr_pool_t * pool)197 extern "C" svn_error_t *handlerConflictResolver
198     (
199     svn_wc_conflict_result_t **result,
200     const svn_wc_conflict_description_t *description,
201     void *baton,
202     apr_pool_t *pool
203     )
204 {
205     SvnContext *context = SvnContext::castBaton( baton );
206 
207     if( context->contextConflictResolver( result, description, pool ) )
208         return SVN_NO_ERROR;
209     else
210         return svn_error_create( SVN_ERR_CANCELLED, NULL, "cancelled by user" );
211 }
212 #endif
213 
handlerCancel(void * baton)214 extern "C" svn_error_t *handlerCancel
215     (
216     void * baton
217     )
218 {
219     SvnContext *context = SvnContext::castBaton( baton );
220 
221     if( context->contextCancel() )
222         return svn_error_create( SVN_ERR_CANCELLED, NULL, "cancelled by user" );
223     else
224         return SVN_NO_ERROR;
225 }
226 
handlerSimplePrompt(svn_auth_cred_simple_t ** cred,void * baton,const char * a_realm,const char * a_username,svn_boolean_t a_may_save,apr_pool_t * pool)227 extern "C" svn_error_t *handlerSimplePrompt
228     (
229     svn_auth_cred_simple_t **cred,
230     void *baton,
231     const char *a_realm,
232     const char *a_username,
233     svn_boolean_t a_may_save,
234     apr_pool_t *pool
235     )
236 {
237     SvnContext *context = SvnContext::castBaton( baton );
238 
239     bool may_save = a_may_save != 0;
240 
241     if( a_realm == NULL )
242         a_realm = "";
243     if( a_username == NULL )
244         a_username = "";
245     std::string realm( a_realm );
246     std::string username( a_username );
247     std::string password;
248 
249     if( !context->contextGetLogin( realm, username, password, may_save ) )
250         return svn_error_create( SVN_ERR_CANCELLED, NULL, "" );
251 
252     svn_auth_cred_simple_t *lcred = (svn_auth_cred_simple_t *)apr_palloc( pool, sizeof( svn_auth_cred_simple_t ) );
253     lcred->username = svn_string_ncreate( username.data(), username.length(), pool )->data;
254     lcred->password = svn_string_ncreate( password.data(), password.length(), pool )->data;
255 
256     // tell svn if the credentials need to be saved
257     lcred->may_save = may_save;
258     *cred = lcred;
259 
260     return SVN_NO_ERROR;
261 }
262 
handlerSslServerTrustPrompt(svn_auth_cred_ssl_server_trust_t ** cred,void * baton,const char * a_realm,apr_uint32_t failures,const svn_auth_ssl_server_cert_info_t * info,svn_boolean_t may_save,apr_pool_t * pool)263 extern "C" svn_error_t *handlerSslServerTrustPrompt
264     (
265     svn_auth_cred_ssl_server_trust_t **cred,
266     void *baton,
267     const char *a_realm,
268     apr_uint32_t failures,
269     const svn_auth_ssl_server_cert_info_t *info,
270     svn_boolean_t may_save,
271     apr_pool_t *pool
272     )
273 {
274     SvnContext *context = SvnContext::castBaton( baton );
275 
276     apr_uint32_t accepted_failures = failures;
277     bool accept_permanently = true;
278 
279     if( a_realm == NULL )
280         a_realm = "";
281     std::string realm( a_realm );
282     if( !context->contextSslServerTrustPrompt( *info, realm, accepted_failures, accept_permanently ) )
283     {
284         *cred = NULL;
285 
286         return SVN_NO_ERROR;
287     }
288 
289     svn_auth_cred_ssl_server_trust_t *new_cred = (svn_auth_cred_ssl_server_trust_t *)
290             apr_palloc( pool, sizeof (svn_auth_cred_ssl_server_trust_t) );
291 
292     if( accept_permanently )
293     {
294         new_cred->may_save = 1;
295     }
296 
297     new_cred->accepted_failures = accepted_failures;
298 
299     *cred = new_cred;
300 
301     return SVN_NO_ERROR;
302 }
303 
handlerSslClientCertPrompt(svn_auth_cred_ssl_client_cert_t ** cred,void * baton,const char * a_realm,svn_boolean_t a_may_save,apr_pool_t * pool)304 extern "C" svn_error_t *handlerSslClientCertPrompt
305     (
306     svn_auth_cred_ssl_client_cert_t **cred,
307     void *baton,
308     const char *a_realm,
309     svn_boolean_t a_may_save,
310     apr_pool_t *pool
311     )
312 {
313     SvnContext *context = SvnContext::castBaton( baton );
314 
315     if( a_realm == NULL )
316         a_realm = "";
317     std::string realm( a_realm );
318     bool may_save = a_may_save != 0;
319     std::string cert_file;
320     if( !context->contextSslClientCertPrompt( cert_file, realm, may_save ) )
321         return svn_error_create (SVN_ERR_CANCELLED, NULL, "");
322 
323     svn_auth_cred_ssl_client_cert_t *new_cred = (svn_auth_cred_ssl_client_cert_t*)
324         apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_t));
325 
326     new_cred->cert_file = svn_string_ncreate( cert_file.data(), cert_file.length(), pool )->data;
327     new_cred->may_save = may_save;
328 
329     *cred = new_cred;
330 
331     return SVN_NO_ERROR;
332 }
333 
handlerSslClientCertPwPrompt(svn_auth_cred_ssl_client_cert_pw_t ** cred,void * baton,const char * a_realm,svn_boolean_t a_may_save,apr_pool_t * pool)334 extern "C" svn_error_t *handlerSslClientCertPwPrompt
335     (
336     svn_auth_cred_ssl_client_cert_pw_t **cred,
337     void *baton,
338     const char *a_realm,
339     svn_boolean_t a_may_save,
340     apr_pool_t *pool
341     )
342 {
343     SvnContext *context = SvnContext::castBaton( baton );
344 
345     if( a_realm == NULL )
346         a_realm = "";
347     std::string realm( a_realm );
348 
349     std::string password;
350     bool may_save = a_may_save != 0;
351     if( !context->contextSslClientCertPwPrompt( password, realm, may_save ) )
352         return svn_error_create( SVN_ERR_CANCELLED, NULL, "" );
353 
354     svn_auth_cred_ssl_client_cert_pw_t *new_cred = (svn_auth_cred_ssl_client_cert_pw_t *)
355         apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_pw_t));
356 
357     new_cred->password = svn_string_ncreate( password.data(), password.length(), pool )->data;
358     new_cred->may_save = may_save;
359 
360     *cred = new_cred;
361 
362     return SVN_NO_ERROR;
363 }
364 
SvnContext(const std::string & config_dir_str)365 SvnContext::SvnContext( const std::string &config_dir_str )
366 : m_pool( NULL )
367 , m_context( NULL )
368 , m_config_dir( NULL )
369 {
370     memset( &m_context, 0, sizeof( m_context ) );
371 
372     apr_pool_create( &m_pool, NULL );
373 
374 #if defined( PYSVN_HAS_CLIENT_CREATE_CONTEXT2 )
375     svn_client_create_context2( &m_context, NULL, m_pool );
376 #else
377     svn_client_create_context( &m_context, m_pool );
378 #endif
379 
380     if( !config_dir_str.empty() )
381     {
382         m_config_dir = svn_dirent_canonicalize( config_dir_str.c_str(), m_pool );
383     }
384 
385     svn_config_ensure( m_config_dir, m_pool );
386 
387     // get the config based on the config dir passed in
388     svn_config_get_config( &m_context->config, m_config_dir, m_pool );
389 
390     svn_auth_provider_object_t *provider = NULL;
391     apr_array_header_t *providers = apr_array_make( m_pool, 11, sizeof( svn_auth_provider_object_t * ) );
392 
393 #if defined( PYSVN_HAS_SVN_AUTH_PROVIDERS )
394 
395     // simple providers
396 # if defined( PYSVN_HAS_SVN_AUTH_GET_PLATFORM_SPECIFIC_CLIENT_PROVIDERS )
397     svn_config_t *cfg = (svn_config_t *)apr_hash_get
398         (
399         m_context->config,
400         SVN_CONFIG_CATEGORY_CONFIG,
401         APR_HASH_KEY_STRING
402         );
403     svn_auth_get_platform_specific_client_providers( &providers, cfg, m_pool );
404 
405 # else
406 #  if defined( WIN32 )
407     svn_auth_get_windows_simple_provider(&provider, m_pool);
408     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
409 #  endif
410 #  if defined( DARWIN )
411     svn_auth_get_keychain_simple_provider(&provider, m_pool);
412     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
413 #  endif
414 # endif
415 
416 #  if defined( PYSVN_HAS_AUTH_GET_SIMPLE_PROVIDER2 )
417     svn_auth_get_simple_provider2( &provider, NULL, NULL, m_pool );
418 #  else
419     svn_auth_get_simple_provider( &provider, m_pool );
420 #  endif
421     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
422 
423     svn_auth_get_username_provider( &provider, m_pool );
424     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
425 
426     svn_auth_get_simple_prompt_provider( &provider, handlerSimplePrompt, this, 1000000, m_pool );
427     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
428 
429     // ssl providers
430 
431     // order is important - file first then prompt providers
432     svn_auth_get_ssl_server_trust_file_provider( &provider, m_pool );
433     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
434 
435     svn_auth_get_ssl_client_cert_file_provider( &provider, m_pool );
436     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
437 
438 # if defined( PYSVN_HAS_AUTH_GET_SSL_CLIENT_CERT_PW_FILE_PROVIDER2 )
439     svn_auth_get_ssl_client_cert_pw_file_provider2( &provider, NULL, NULL, m_pool );
440 # else
441     svn_auth_get_ssl_client_cert_pw_file_provider( &provider, m_pool );
442 # endif
443     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
444 
445     svn_auth_get_ssl_server_trust_prompt_provider( &provider, handlerSslServerTrustPrompt, this, m_pool );
446     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
447 
448     svn_auth_get_ssl_client_cert_prompt_provider( &provider, handlerSslClientCertPrompt, this, 3, m_pool );
449     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
450 
451     svn_auth_get_ssl_client_cert_pw_prompt_provider( &provider, handlerSslClientCertPwPrompt, this, 3, m_pool );
452     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
453 #else
454     // Pre 1.4.0 version
455     apr_array_header_t *providers = apr_array_make( m_pool, 8, sizeof( svn_auth_provider_object_t * ) );
456 
457     // simple providers
458     svn_auth_provider_object_t *provider = NULL;
459     svn_client_get_simple_provider( &provider, m_pool );
460     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
461 
462     svn_client_get_username_provider( &provider, m_pool );
463     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
464 
465     svn_client_get_simple_prompt_provider( &provider, handlerSimplePrompt, this, 3, m_pool );
466     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
467 
468     // ssl providers
469 
470     // order is important - file first then prompt providers
471     svn_client_get_ssl_server_trust_file_provider( &provider, m_pool );
472     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
473 
474     svn_client_get_ssl_client_cert_file_provider( &provider, m_pool );
475     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
476 
477     svn_client_get_ssl_client_cert_pw_file_provider( &provider, m_pool );
478     *(svn_auth_provider_object_t **)apr_array_push( providers ) = provider;
479 
480     svn_client_get_ssl_server_trust_prompt_provider( &provider, handlerSslServerTrustPrompt, this, m_pool );
481     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
482 
483     svn_client_get_ssl_client_cert_prompt_provider( &provider, handlerSslClientCertPrompt, this, 3, m_pool );
484     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
485 
486     svn_client_get_ssl_client_cert_pw_prompt_provider( &provider, handlerSslClientCertPwPrompt, this, 3, m_pool );
487     *(svn_auth_provider_object_t **)apr_array_push (providers) = provider;
488 #endif
489 
490     svn_auth_baton_t *auth_baton = NULL;
491     svn_auth_open( &auth_baton, providers, m_pool );
492 
493     // tell the auth functions where the config dir is
494     svn_auth_set_parameter( auth_baton, SVN_AUTH_PARAM_CONFIG_DIR, m_config_dir );
495 
496     m_context->auth_baton = auth_baton;
497 
498 #if defined( PYSVN_HAS_CONTEXT_LOG_MSG2 )
499     m_context->log_msg_func2 = handlerLogMsg2;
500     m_context->log_msg_baton2 = this;
501 #else
502     m_context->log_msg_func = handlerLogMsg;
503     m_context->log_msg_baton = this;
504 #endif
505 }
506 
installCancel(bool install)507 void SvnContext::installCancel( bool install )
508 {
509     if( install )
510     {
511         m_context->cancel_func = handlerCancel;
512         m_context->cancel_baton = this;
513     }
514     else
515     {
516         m_context->cancel_func = NULL;
517         m_context->cancel_baton = NULL;
518     }
519 }
520 
installNotify(bool install)521 void SvnContext::installNotify( bool install )
522 {
523     if( install )
524     {
525 #if defined( PYSVN_HAS_CONTEXT_NOTIFY2 )
526         m_context->notify_func2 = handlerNotify2;
527         m_context->notify_baton2 = this;
528 #else
529         m_context->notify_func = handlerNotify;
530         m_context->notify_baton = this;
531 #endif
532     }
533     else
534     {
535 #if defined( PYSVN_HAS_CONTEXT_NOTIFY2 )
536         m_context->notify_func2 = NULL;
537         m_context->notify_baton2 = NULL;
538 #else
539         m_context->notify_func = NULL;
540         m_context->notify_baton = NULL;
541 #endif
542     }
543 }
544 
545 #if defined( PYSVN_HAS_CONTEXT_PROGRESS )
installProgress(bool install)546 void SvnContext::installProgress( bool install )
547 {
548     if( install )
549     {
550         m_context->progress_func = handlerProgress;
551         m_context->progress_baton = this;
552     }
553     else
554     {
555         m_context->progress_func = handlerProgress;
556         m_context->progress_baton = this;
557     }
558 }
559 #endif
560 
561 #if defined( PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC )
installConflictResolver(bool install)562 void SvnContext::installConflictResolver( bool install )
563 {
564     if( install )
565     {
566         m_context->conflict_func = handlerConflictResolver;
567         m_context->conflict_baton = this;
568     }
569     else
570     {
571         m_context->conflict_func = NULL;
572         m_context->conflict_baton = NULL;
573     }
574 }
575 #endif
576 
~SvnContext()577 SvnContext::~SvnContext()
578 {
579     if( m_pool )
580     {
581         apr_pool_destroy( m_pool );
582     }
583 }
584 
operator svn_client_ctx_t*()585 SvnContext::operator svn_client_ctx_t *()
586 {
587     return m_context;
588 }
589 
ctx()590 svn_client_ctx_t *SvnContext::ctx()
591 {
592     return m_context;
593 }
594 
595 // only use this pool for data that has a life time
596 // that matches the life time of the context
getContextPool()597 apr_pool_t *SvnContext::getContextPool()
598 {
599     return m_pool;
600 }
601 
602 //--------------------------------------------------------------------------------
603 //
604 //        SvnTransaction
605 //
606 //--------------------------------------------------------------------------------
SvnTransaction()607 SvnTransaction::SvnTransaction()
608 : m_pool( NULL )
609 , m_repos( NULL )
610 , m_fs( NULL )
611 , m_txn( NULL )
612 , m_txn_name( NULL )
613 , m_rev_id( SVN_INVALID_REVNUM )
614 {
615     apr_pool_create( &m_pool, NULL );
616 }
617 
init(const std::string & repos_path,const std::string & transaction_name,bool is_revision)618 svn_error_t *SvnTransaction::init( const std::string &repos_path,
619     const std::string &transaction_name, bool is_revision )
620 {
621     svn_error_t *error;
622 
623     SvnPool scratch_pool( *this );
624 
625 #if defined( PYSVN_HAS_REPOS_OPEN3 )
626     error = svn_repos_open3( &m_repos, repos_path.c_str(), NULL, m_pool, scratch_pool );
627 
628 # elif defined( PYSNV_HAS_REPOS_OPEN2 )
629     error = svn_repos_open2( &m_repos, repos_path.c_str(), NULL, m_pool );
630 
631 #else
632     error = svn_repos_open( &m_repos, repos_path.c_str(), m_pool );
633 #endif
634     if( error != NULL )
635         return error;
636 
637     m_fs = svn_repos_fs( m_repos );
638     // what is a warning function?
639     // svn_fs_set_warning_func (m_fs, warning_func, NULL);
640 
641     if( is_revision )
642     {
643         Py::String rev_name( transaction_name );
644         Py::Long long_val( rev_name );
645         m_rev_id = (long)long_val;
646         if (! SVN_IS_VALID_REVNUM( m_rev_id ))
647             return svn_error_create( SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
648                 "invalid revision number supplied" );
649     }
650     else
651     {
652         m_txn_name = apr_pstrdup( m_pool, transaction_name.c_str() );
653         error = svn_fs_open_txn( &m_txn, m_fs, m_txn_name, m_pool );
654     }
655 
656     return error;
657 }
658 
~SvnTransaction()659 SvnTransaction::~SvnTransaction()
660 {
661 }
662 
root(svn_fs_root_t ** root,apr_pool_t * pool)663 svn_error_t *SvnTransaction::root( svn_fs_root_t **root, apr_pool_t *pool )
664 {
665     if( is_revision() )
666         return svn_fs_revision_root( root, m_fs, m_rev_id, pool );
667     else
668         return svn_fs_txn_root( root, m_txn, pool );
669 }
670 
operator svn_fs_txn_t*()671 SvnTransaction::operator svn_fs_txn_t *()
672 {
673     return m_txn;
674 }
675 
operator svn_fs_t*()676 SvnTransaction::operator svn_fs_t *()
677 {
678     return m_fs;
679 }
680 
operator svn_repos_t*()681 SvnTransaction::operator svn_repos_t *()
682 {
683     return m_repos;
684 }
685 
686 
transaction()687 svn_fs_txn_t *SvnTransaction::transaction()
688 {
689     return m_txn;
690 }
691 
revision()692 svn_revnum_t SvnTransaction::revision()
693 {
694     return m_rev_id;
695 }
696 
697 //--------------------------------------------------------------------------------
698 //
699 //        Pool
700 //
701 //--------------------------------------------------------------------------------
SvnPool(SvnContext & ctx)702 SvnPool::SvnPool( SvnContext &ctx )
703 : m_pool( NULL )
704 {
705     m_pool = svn_pool_create( NULL );
706 }
707 
SvnPool(SvnTransaction & txn)708 SvnPool::SvnPool( SvnTransaction &txn )
709 : m_pool( NULL )
710 {
711     m_pool = svn_pool_create( NULL );
712 }
713 
~SvnPool()714 SvnPool::~SvnPool()
715 {
716     if( m_pool != NULL )
717     {
718         svn_pool_destroy( m_pool );
719     }
720 }
721 
operator apr_pool_t*() const722 SvnPool::operator apr_pool_t *() const
723 {
724     return m_pool;
725 }
726 
727 #if 0
728 // keep around as it useful for debugging pysvn
729 static const char *toHex( unsigned int num )
730 {
731     static char buffer[9];
732     for( int i=0; i<8; i++ )
733     {
734         buffer[i] = "0123456789abcdef"[ (num >> (32-(i+1)*4)) & 0x0f ];
735     }
736     buffer[8] = '\0';
737     return buffer;
738 }
739 #endif
740