1 //
2 // ====================================================================
3 // (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 //
11 // pysvn_client.cpp
12 //
13
14 #if defined( _MSC_VER )
15 // disable warning C4786: symbol greater than 255 character,
16 // nessesary to ignore as <map> causes lots of warning
17 #pragma warning(disable: 4786)
18 #endif
19
20 #include "pysvn.hpp"
21 #include "pysvn_docs.hpp"
22 #include "pysvn_svnenv.hpp"
23 #include "svn_path.h"
24 #include "svn_config.h"
25 #include "svn_sorts.h"
26 #include "pysvn_static_strings.hpp"
27
28 static const char *g_utf_8 = "utf-8";
29
init_py_names()30 static void init_py_names()
31 {
32 static bool init_done = false;
33 if( init_done )
34 {
35 return;
36 }
37
38 py_name_callback_cancel = new Py::String( name_callback_cancel );
39 py_name_callback_conflict_resolver = new Py::String( name_callback_conflict_resolver );
40 py_name_callback_get_log_message = new Py::String( name_callback_get_log_message );
41 py_name_callback_get_login = new Py::String( name_callback_get_login );
42 py_name_callback_notify = new Py::String( name_callback_notify );
43 py_name_callback_ssl_client_cert_password_prompt = new Py::String( name_callback_ssl_client_cert_password_prompt );
44 py_name_callback_ssl_client_cert_prompt = new Py::String( name_callback_ssl_client_cert_prompt );
45 py_name_callback_ssl_server_prompt = new Py::String( name_callback_ssl_server_prompt );
46 py_name_callback_ssl_server_trust_prompt = new Py::String( name_callback_ssl_server_trust_prompt );
47 py_name_commit_info_style = new Py::String( name_commit_info_style );
48 py_name_created_rev = new Py::String( name_created_rev );
49 py_name_exception_style = new Py::String( name_exception_style );
50 py_name_has_props = new Py::String( name_has_props );
51 py_name_kind = new Py::String( name_kind );
52 py_name_last_author = new Py::String( name_last_author );
53 py_name_lock = new Py::String( name_lock );
54 py_name_name = new Py::String( name_name );
55 py_name_node_kind = new Py::String( name_node_kind );
56 py_name_path = new Py::String( name_path );
57 py_name_prop_changed = new Py::String( name_prop_changed );
58 py_name_repos_path = new Py::String( name_repos_path );
59 py_name_size = new Py::String( name_size );
60 py_name_summarize_kind = new Py::String( name_summarize_kind );
61 py_name_time = new Py::String( name_time );
62
63 init_done = true;
64 }
65
66 //--------------------------------------------------------------------------------
67 #if defined( PYSVN_HAS_CLIENT_STATUS_T )
68 std::string name_wrapper_status2("PysvnStatus2");
69 #endif
70 std::string name_wrapper_status("PysvnStatus");
71 std::string name_wrapper_entry("PysvnEntry");
72 std::string name_wrapper_info("PysvnInfo");
73 std::string name_wrapper_lock("PysvnLock");
74 std::string name_wrapper_list("PysvnList");
75 std::string name_wrapper_log("PysvnLog");
76 std::string name_wrapper_log_changed_path("PysvnLogChangedPath");
77 std::string name_wrapper_dirent("PysvnDirent");
78 std::string name_wrapper_wc_info("PysvnWcInfo");
79 std::string name_wrapper_diff_summary("PysvnDiffSummary");
80 std::string name_wrapper_commit_info("PysvnCommitInfo");
81
pysvn_client(pysvn_module & _module,const std::string & config_dir,Py::Dict result_wrappers)82 pysvn_client::pysvn_client
83 (
84 pysvn_module &_module,
85 const std::string &config_dir,
86 Py::Dict result_wrappers
87 )
88 : m_module( _module )
89 , m_result_wrappers( result_wrappers )
90 , m_context( config_dir )
91 , m_exception_style( 0 )
92 , m_commit_info_style( 0 )
93 #if defined( PYSVN_HAS_CLIENT_STATUS_T )
94 , m_wrapper_status2( result_wrappers, name_wrapper_status2 )
95 #endif
96 , m_wrapper_status( result_wrappers, name_wrapper_status )
97 , m_wrapper_entry( result_wrappers, name_wrapper_entry )
98 , m_wrapper_info( result_wrappers, name_wrapper_info )
99 , m_wrapper_lock( result_wrappers, name_wrapper_lock )
100 , m_wrapper_list( result_wrappers, name_wrapper_list )
101 , m_wrapper_log( result_wrappers, name_wrapper_log )
102 , m_wrapper_log_changed_path( result_wrappers, name_wrapper_log_changed_path )
103 , m_wrapper_dirent( result_wrappers, name_wrapper_dirent )
104 , m_wrapper_wc_info( result_wrappers, name_wrapper_wc_info )
105 , m_wrapper_diff_summary( result_wrappers, name_wrapper_diff_summary )
106 , m_wrapper_commit_info( result_wrappers, name_wrapper_commit_info )
107 {
108 init_py_names();
109 }
110
~pysvn_client()111 pysvn_client::~pysvn_client()
112 {
113 }
114
getattr(const char * _name)115 Py::Object pysvn_client::getattr( const char *_name )
116 {
117 std::string name( _name );
118
119 // std::cout << "getattr( " << name << " )" << std::endl << std::flush;
120
121 if( name == name___members__ )
122 {
123 Py::List members;
124
125 members.append( *py_name_callback_get_login );
126 members.append( *py_name_callback_notify );
127 members.append( *py_name_callback_cancel );
128 members.append( *py_name_callback_conflict_resolver );
129 members.append( *py_name_callback_get_log_message );
130 members.append( *py_name_callback_ssl_server_prompt );
131 members.append( *py_name_callback_ssl_server_trust_prompt );
132 members.append( *py_name_callback_ssl_client_cert_prompt );
133 members.append( *py_name_callback_ssl_client_cert_password_prompt );
134
135 members.append( *py_name_exception_style );
136 members.append( *py_name_commit_info_style );
137
138 return members;
139 }
140
141 if( name == name_callback_get_login )
142 return m_context.m_pyfn_GetLogin;
143
144 if( name == name_callback_notify )
145 return m_context.m_pyfn_Notify;
146
147 #if defined( PYSVN_HAS_CONTEXT_PROGRESS )
148 if( name == name_callback_progress )
149 return m_context.m_pyfn_Progress;
150 #endif
151
152 #if defined( PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC )
153 if( name == name_callback_conflict_resolver )
154 return m_context.m_pyfn_ConflictResolver;
155 #endif
156
157 if( name == name_callback_cancel )
158 return m_context.m_pyfn_Cancel;
159
160 if( name == name_callback_get_log_message )
161 return m_context.m_pyfn_GetLogMessage;
162
163 if( name == name_callback_ssl_server_prompt )
164 return m_context.m_pyfn_SslServerPrompt;
165
166 if( name == name_callback_ssl_server_trust_prompt )
167 return m_context.m_pyfn_SslServerTrustPrompt;
168
169 if( name == name_callback_ssl_client_cert_prompt )
170 return m_context.m_pyfn_SslClientCertPrompt;
171
172 if( name == name_callback_ssl_client_cert_password_prompt )
173 return m_context.m_pyfn_SslClientCertPwPrompt;
174
175 if( name == name_callback_ssl_client_cert_password_prompt )
176 return m_context.m_pyfn_SslClientCertPwPrompt;
177
178 if( name == name_exception_style )
179 return Py::Int( m_exception_style );
180
181 if( name == name_commit_info_style )
182 return Py::Int( m_commit_info_style );
183
184 return getattr_default( _name );
185 }
186
set_callable(Py::Object & callback,const Py::Object & value)187 static bool set_callable( Py::Object &callback, const Py::Object &value )
188 {
189 if( value.isCallable() )
190 {
191 callback = value;
192 return true;
193 }
194
195 else
196 if( value.is( Py::None() ) )
197 {
198 callback = value;
199 return false;
200 }
201
202 else
203 {
204 throw Py::AttributeError( "expecting None or a callable object" );
205 }
206 }
207
setattr(const char * _name,const Py::Object & value)208 int pysvn_client::setattr( const char *_name, const Py::Object &value )
209 {
210 std::string name( _name );
211 if( name == name_callback_get_login )
212 set_callable( m_context.m_pyfn_GetLogin, value );
213
214 else if( name == name_callback_notify )
215 m_context.installNotify( set_callable( m_context.m_pyfn_Notify, value ) );
216
217 #if defined( PYSVN_HAS_CONTEXT_PROGRESS )
218 else if( name == name_callback_progress )
219 m_context.installProgress( set_callable( m_context.m_pyfn_Progress, value ) );
220 #endif
221
222 #if defined( PYSVN_HAS_SVN_CLIENT_CTX_T__CONFLICT_FUNC )
223 else if( name == name_callback_conflict_resolver )
224 m_context.installConflictResolver( set_callable( m_context.m_pyfn_ConflictResolver, value ) );
225 #endif
226
227 else if( name == name_callback_cancel )
228 m_context.installCancel( set_callable( m_context.m_pyfn_Cancel, value ) );
229
230 else if( name == name_callback_get_log_message )
231 set_callable( m_context.m_pyfn_GetLogMessage, value );
232
233 else if( name == name_callback_ssl_server_prompt )
234 set_callable( m_context.m_pyfn_SslServerPrompt, value );
235
236 else if( name == name_callback_ssl_server_trust_prompt )
237 set_callable( m_context.m_pyfn_SslServerTrustPrompt, value );
238
239 else if( name == name_callback_ssl_client_cert_prompt )
240 set_callable( m_context.m_pyfn_SslClientCertPrompt, value );
241
242 else if( name == name_callback_ssl_client_cert_password_prompt )
243 set_callable( m_context.m_pyfn_SslClientCertPwPrompt, value );
244
245 else if( name == name_exception_style )
246 {
247 Py::Int style( value );
248 if( style == 0l || style == 1l )
249 {
250 m_exception_style = style;
251 }
252 else
253 {
254 throw Py::AttributeError( "exception_style value must be 0 or 1" );
255 }
256 }
257
258 else if( name == name_commit_info_style )
259 {
260 Py::Int style( value );
261 if( style == 0l || style == 1l || style == 2l )
262 {
263 m_commit_info_style = style;
264 }
265 else
266 {
267 throw Py::AttributeError( "commit_info_style value must be 0, 1 or 2" );
268 }
269 }
270
271 else
272 {
273 std::string msg( "Unknown attribute: " );
274 msg += name;
275 throw Py::AttributeError( msg );
276 }
277
278 return 0;
279 }
280
281
helper_boolean_auth_set(FunctionArguments & a_args,const char * a_arg_name,const char * a_param_name)282 Py::Object pysvn_client::helper_boolean_auth_set( FunctionArguments &a_args, const char *a_arg_name, const char *a_param_name )
283 {
284 a_args.check();
285
286 bool enable( a_args.getBoolean( a_arg_name ) );
287 try
288 {
289 void *param = 0;
290 if( !enable )
291 param = (void *)"1";
292
293 svn_auth_set_parameter
294 (
295 m_context.ctx()->auth_baton,
296 a_param_name,
297 param
298 );
299 }
300 catch( SvnException &e )
301 {
302 // use callback error over ClientException
303 m_context.checkForError( m_module.client_error );
304
305 throw_client_error( e );
306 }
307
308 return Py::None();
309 }
310
helper_boolean_auth_get(FunctionArguments & a_args,const char * a_param_name)311 Py::Object pysvn_client::helper_boolean_auth_get( FunctionArguments &a_args, const char *a_param_name )
312 {
313 a_args.check();
314
315 char *param = NULL;
316 try
317 {
318 param = (char *)svn_auth_get_parameter
319 (
320 m_context.ctx()->auth_baton,
321 a_param_name
322 );
323 }
324 catch( SvnException &e )
325 {
326 // use callback error over ClientException
327 m_context.checkForError( m_module.client_error );
328
329 throw_client_error( e );
330 }
331
332 bool not_set = param != NULL && param[0] == '1';
333 if( not_set )
334 return Py::Int( 0 );
335 return Py::Int( 1 );
336 }
337
helper_string_auth_set(FunctionArguments & a_args,const char * a_arg_name,const char * a_param_name,std::string & ctx_str)338 Py::Object pysvn_client::helper_string_auth_set
339 (
340 FunctionArguments &a_args,
341 const char *a_arg_name,
342 const char *a_param_name,
343 std::string &ctx_str
344 )
345 {
346 a_args.check();
347
348 const char *param = NULL;
349 Py::Object param_obj( a_args.getArg( a_arg_name ) );
350 if( !param_obj.is( Py::None() ) )
351 {
352 Py::String param_str( param_obj );
353 ctx_str = param_str.as_std_string( g_utf_8 );
354 param = ctx_str.c_str();
355 }
356
357 try
358 {
359 svn_auth_set_parameter
360 (
361 m_context.ctx()->auth_baton,
362 a_param_name,
363 param
364 );
365 }
366 catch( SvnException &e )
367 {
368 // use callback error over ClientException
369 m_context.checkForError( m_module.client_error );
370
371 throw_client_error( e );
372 }
373
374 return Py::None();
375 }
376
helper_string_auth_get(FunctionArguments & a_args,const char * a_param_name)377 Py::Object pysvn_client::helper_string_auth_get( FunctionArguments &a_args, const char *a_param_name )
378 {
379 a_args.check();
380
381 char *param = NULL;
382 try
383 {
384 param = (char *)svn_auth_get_parameter
385 (
386 m_context.ctx()->auth_baton,
387 a_param_name
388 );
389 }
390 catch( SvnException &e )
391 {
392 // use callback error over ClientException
393 m_context.checkForError( m_module.client_error );
394
395 throw_client_error( e );
396 }
397
398 if( param != NULL )
399 return Py::String( param );
400
401 return Py::None();
402 }
403
404 #if defined( PYSVN_HAS_WC_ADM_DIR )
get_adm_dir(const Py::Tuple & a_args,const Py::Dict & a_kws)405 Py::Object pysvn_client::get_adm_dir( const Py::Tuple &a_args, const Py::Dict &a_kws )
406 {
407 static argument_description args_desc[] =
408 {
409 { false, NULL }
410 };
411 FunctionArguments args( "get_adm_dir", args_desc, a_args, a_kws );
412 args.check();
413
414 const char *name = NULL;
415
416 try
417 {
418 name = svn_wc_get_adm_dir
419 (
420 m_context.getContextPool()
421 );
422 }
423 catch( SvnException &e )
424 {
425 // use callback error over ClientException
426 m_context.checkForError( m_module.client_error );
427
428 throw_client_error( e );
429 }
430
431 return Py::String( name );
432 }
433 #endif
434
get_auth_cache(const Py::Tuple & a_args,const Py::Dict & a_kws)435 Py::Object pysvn_client::get_auth_cache( const Py::Tuple &a_args, const Py::Dict &a_kws )
436 {
437 static argument_description args_desc[] =
438 {
439 { false, NULL }
440 };
441 FunctionArguments args( "get_auth_cache", args_desc, a_args, a_kws );
442
443 return helper_boolean_auth_get( args, SVN_AUTH_PARAM_NO_AUTH_CACHE );
444 }
445
get_interactive(const Py::Tuple & a_args,const Py::Dict & a_kws)446 Py::Object pysvn_client::get_interactive( const Py::Tuple &a_args, const Py::Dict &a_kws )
447 {
448 static argument_description args_desc[] =
449 {
450 { false, NULL }
451 };
452 FunctionArguments args( "get_interactive", args_desc, a_args, a_kws );
453
454 return helper_boolean_auth_get( args, SVN_AUTH_PARAM_NON_INTERACTIVE );
455 }
456
get_store_passwords(const Py::Tuple & a_args,const Py::Dict & a_kws)457 Py::Object pysvn_client::get_store_passwords( const Py::Tuple &a_args, const Py::Dict &a_kws )
458 {
459 static argument_description args_desc[] =
460 {
461 { false, NULL }
462 };
463 FunctionArguments args( "get_store_passwords", args_desc, a_args, a_kws );
464
465 return helper_boolean_auth_get( args, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS );
466 }
467
get_default_username(const Py::Tuple & a_args,const Py::Dict & a_kws)468 Py::Object pysvn_client::get_default_username( const Py::Tuple &a_args, const Py::Dict &a_kws )
469 {
470 static argument_description args_desc[] =
471 {
472 { false, NULL }
473 };
474 FunctionArguments args( "get_default_username", args_desc, a_args, a_kws );
475
476 return helper_string_auth_get( args, SVN_AUTH_PARAM_DEFAULT_USERNAME );
477 }
478
get_default_password(const Py::Tuple & a_args,const Py::Dict & a_kws)479 Py::Object pysvn_client::get_default_password( const Py::Tuple &a_args, const Py::Dict &a_kws )
480 {
481 static argument_description args_desc[] =
482 {
483 { false, NULL }
484 };
485 FunctionArguments args( "get_default_password", args_desc, a_args, a_kws );
486
487 return helper_string_auth_get( args, SVN_AUTH_PARAM_DEFAULT_PASSWORD );
488 }
489
490 #if defined( PYSVN_HAS_WC_ADM_DIR )
set_adm_dir(const Py::Tuple & a_args,const Py::Dict & a_kws)491 Py::Object pysvn_client::set_adm_dir( const Py::Tuple &a_args, const Py::Dict &a_kws )
492 {
493 static argument_description args_desc[] =
494 {
495 { true, name_name },
496 { false, NULL }
497 };
498 FunctionArguments args( "set_adm_dir", args_desc, a_args, a_kws );
499
500 args.check();
501
502 std::string name( args.getBytes( name_name ) );
503
504 try
505 {
506 svn_wc_set_adm_dir
507 (
508 name.c_str(),
509 m_context.getContextPool()
510 );
511 }
512 catch( SvnException &e )
513 {
514 // use callback error over ClientException
515 m_context.checkForError( m_module.client_error );
516
517 throw_client_error( e );
518 }
519
520 return Py::None();
521 }
522 #endif
523
set_auth_cache(const Py::Tuple & a_args,const Py::Dict & a_kws)524 Py::Object pysvn_client::set_auth_cache( const Py::Tuple &a_args, const Py::Dict &a_kws )
525 {
526 static argument_description args_desc[] =
527 {
528 { true, name_enable },
529 { false, NULL }
530 };
531 FunctionArguments args( "set_auth_cache", args_desc, a_args, a_kws );
532
533 return helper_boolean_auth_set( args, name_enable, SVN_AUTH_PARAM_NO_AUTH_CACHE );
534 }
535
set_interactive(const Py::Tuple & a_args,const Py::Dict & a_kws)536 Py::Object pysvn_client::set_interactive( const Py::Tuple &a_args, const Py::Dict &a_kws )
537 {
538 static argument_description args_desc[] =
539 {
540 { true, name_enable },
541 { false, NULL }
542 };
543 FunctionArguments args( "set_interactive", args_desc, a_args, a_kws );
544
545 return helper_boolean_auth_set( args, name_enable, SVN_AUTH_PARAM_NON_INTERACTIVE );
546 }
547
set_store_passwords(const Py::Tuple & a_args,const Py::Dict & a_kws)548 Py::Object pysvn_client::set_store_passwords( const Py::Tuple &a_args, const Py::Dict &a_kws )
549 {
550 static argument_description args_desc[] =
551 {
552 { true, name_enable },
553 { false, NULL }
554 };
555 FunctionArguments args( "set_store_passwords", args_desc, a_args, a_kws );
556
557 return helper_boolean_auth_set( args, name_enable, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS );
558 }
559
set_default_username(const Py::Tuple & a_args,const Py::Dict & a_kws)560 Py::Object pysvn_client::set_default_username( const Py::Tuple &a_args, const Py::Dict &a_kws )
561 {
562 static argument_description args_desc[] =
563 {
564 { true, name_username },
565 { false, NULL }
566 };
567 FunctionArguments args( "set_default_username", args_desc, a_args, a_kws );
568
569 return helper_string_auth_set( args, name_username, SVN_AUTH_PARAM_DEFAULT_USERNAME, m_context.m_default_username );
570 }
571
set_default_password(const Py::Tuple & a_args,const Py::Dict & a_kws)572 Py::Object pysvn_client::set_default_password( const Py::Tuple &a_args, const Py::Dict &a_kws )
573 {
574 static argument_description args_desc[] =
575 {
576 { true, name_password },
577 { false, NULL }
578 };
579 FunctionArguments args( "set_default_password", args_desc, a_args, a_kws );
580
581 return helper_string_auth_set( args, name_password, SVN_AUTH_PARAM_DEFAULT_PASSWORD, m_context.m_default_password );
582 }
583
get_auto_props(const Py::Tuple & a_args,const Py::Dict & a_kws)584 Py::Object pysvn_client::get_auto_props( const Py::Tuple &a_args, const Py::Dict &a_kws )
585 {
586 static argument_description args_desc[] =
587 {
588 { false, NULL }
589 };
590 FunctionArguments args( "get_auto_props", args_desc, a_args, a_kws );
591 args.check();
592
593 svn_boolean_t enable = false;
594 try
595 {
596 svn_config_t *cfg = (svn_config_t *)apr_hash_get
597 (
598 m_context.ctx()->config,
599 SVN_CONFIG_CATEGORY_CONFIG,
600 APR_HASH_KEY_STRING
601 );
602 svn_error_t *error = svn_config_get_bool
603 (
604 cfg,
605 &enable,
606 SVN_CONFIG_SECTION_MISCELLANY,
607 SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS,
608 enable
609 );
610 if( error != NULL )
611 throw SvnException( error );
612 }
613 catch( SvnException &e )
614 {
615 // use callback error over ClientException
616 m_context.checkForError( m_module.client_error );
617
618 throw_client_error( e );
619 }
620
621 return Py::Int( enable );
622 }
623
set_auto_props(const Py::Tuple & a_args,const Py::Dict & a_kws)624 Py::Object pysvn_client::set_auto_props( const Py::Tuple &a_args, const Py::Dict &a_kws )
625 {
626 static argument_description args_desc[] =
627 {
628 { true, name_enable },
629 { false, NULL }
630 };
631 FunctionArguments args( "set_auto_props", args_desc, a_args, a_kws );
632 args.check();
633
634 bool enable( args.getBoolean( name_enable ) );
635 try
636 {
637 svn_config_t *cfg = (svn_config_t *)apr_hash_get
638 (
639 m_context.ctx()->config,
640 SVN_CONFIG_CATEGORY_CONFIG,
641 APR_HASH_KEY_STRING
642 );
643 svn_config_set_bool
644 (
645 cfg,
646 SVN_CONFIG_SECTION_MISCELLANY,
647 SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS,
648 enable
649 );
650 }
651 catch( SvnException &e )
652 {
653 // use callback error over ClientException
654 m_context.checkForError( m_module.client_error );
655
656 throw_client_error( e );
657 }
658
659 return Py::None();
660 }
661
662 #if defined( PYSVN_HAS_WC_ADM_DIR )
is_adm_dir(const Py::Tuple & a_args,const Py::Dict & a_kws)663 Py::Object pysvn_client::is_adm_dir( const Py::Tuple &a_args, const Py::Dict &a_kws )
664 {
665 static argument_description args_desc[] =
666 {
667 { true, name_name },
668 { false, NULL }
669 };
670 FunctionArguments args( "is_adm_dir", args_desc, a_args, a_kws );
671
672 args.check();
673
674 std::string name( args.getBytes( name_name ) );
675
676 svn_boolean_t name_is_adm_dir = 0;
677 try
678 {
679 name_is_adm_dir = svn_wc_is_adm_dir
680 (
681 name.c_str(),
682 m_context.getContextPool()
683 );
684 }
685 catch( SvnException &e )
686 {
687 // use callback error over ClientException
688 m_context.checkForError( m_module.client_error );
689
690 throw_client_error( e );
691 }
692
693 return Py::Int( name_is_adm_dir );
694 }
695 #endif
696
is_url(const Py::Tuple & a_args,const Py::Dict & a_kws)697 Py::Object pysvn_client::is_url( const Py::Tuple &a_args, const Py::Dict &a_kws )
698 {
699 static argument_description args_desc[] =
700 {
701 { true, name_url },
702 { false, NULL }
703 };
704 FunctionArguments args( "is_url", args_desc, a_args, a_kws );
705 args.check();
706
707 Py::String path( args.getUtf8String( name_url ) );
708
709 Py::Int result( is_svn_url( path ) );
710 return result;
711 }
712
713 #if defined( PYSVN_HAS_CLIENT_ROOT_URL_FROM_PATH )
cmd_root_url_from_path(const Py::Tuple & a_args,const Py::Dict & a_kws)714 Py::Object pysvn_client::cmd_root_url_from_path( const Py::Tuple& a_args, const Py::Dict &a_kws )
715 {
716 static argument_description args_desc[] =
717 {
718 { true, name_url_or_path },
719 { false, NULL }
720 };
721 FunctionArguments args( "root_url_from_path", args_desc, a_args, a_kws );
722
723 args.check();
724
725 std::string path( args.getUtf8String( name_url_or_path ) );
726
727 SvnPool pool( m_context );
728 const char *root_url = NULL;
729 try
730 {
731 std::string norm_path( svnNormalisedIfPath( path, pool ) );
732
733 checkThreadPermission();
734
735 PythonAllowThreads permission( m_context );
736
737 // known to call back into pysvn
738 #if defined( PYSVN_HAS_CLIENT_GET_REPOS_ROOT )
739 const char *repos_uuid = NULL;
740 svn_error_t *error = svn_client_get_repos_root
741 (
742 &root_url,
743 &repos_uuid,
744 norm_path.c_str(),
745 m_context,
746 pool,
747 pool
748 );
749 #else
750 svn_error_t *error = svn_client_root_url_from_path
751 (
752 &root_url,
753 norm_path.c_str(),
754 m_context,
755 pool
756 );
757 #endif
758 if( error != NULL )
759 throw SvnException( error );
760 }
761 catch( SvnException &e )
762 {
763 // use callback error over ClientException
764 m_context.checkForError( m_module.client_error );
765
766 throw_client_error( e );
767 }
768
769 return Py::String( root_url );
770 }
771 #endif
772
773 // check that we are not in use on another thread
checkThreadPermission()774 void pysvn_client::checkThreadPermission()
775 {
776 if( m_context.hasPermission() )
777 {
778 throw Py::BaseException( m_module.client_error,
779 "client in use on another thread" );
780 }
781 }
782
throw_client_error(SvnException & e)783 void pysvn_client::throw_client_error( SvnException &e )
784 {
785 throw Py::BaseException(
786 m_module.client_error,
787 e.pythonExceptionArg( m_exception_style ) );
788 }
789
revisionKindCompatibleCheck(bool is_url,const svn_opt_revision_t & revision,const char * revision_name,const char * url_or_path_name)790 void revisionKindCompatibleCheck
791 (
792 bool is_url,
793 const svn_opt_revision_t &revision,
794 const char *revision_name,
795 const char *url_or_path_name
796 )
797 {
798 std::string message;
799 if( is_url )
800 {
801 // URL compatibility
802 switch( revision.kind )
803 {
804 case svn_opt_revision_number:
805 case svn_opt_revision_date:
806 case svn_opt_revision_committed:
807 case svn_opt_revision_previous:
808 case svn_opt_revision_head:
809 case svn_opt_revision_unspecified:
810 break;
811
812 case svn_opt_revision_working:
813 case svn_opt_revision_base:
814 default:
815 message += revision_name;
816 message += " is not compatible with URL ";
817 message += url_or_path_name;
818 throw Py::AttributeError( message );
819 }
820 }
821 #if defined( there_are_any_checks_for_path )
822 else
823 {
824 // PATH compatibility
825 switch( revision.kind )
826 {
827 case svn_opt_revision_working:
828 case svn_opt_revision_base:
829 case svn_opt_revision_unspecified:
830 break;
831
832 case svn_opt_revision_number:
833 case svn_opt_revision_date:
834 case svn_opt_revision_committed:
835 case svn_opt_revision_previous:
836 case svn_opt_revision_head:
837 default:
838 message += revision_name;
839 message += " is not compatible with path ";
840 message += url_or_path_name;
841 throw Py::AttributeError( message );
842 }
843 }
844 #endif
845 }
846
init_type()847 void pysvn_client::init_type()
848 {
849 behaviors().name("Client");
850 behaviors().doc( pysvn_client_doc );
851 behaviors().supportGetattr();
852 behaviors().supportSetattr();
853
854 add_keyword_method("add", &pysvn_client::cmd_add, pysvn_client_add_doc );
855 #if defined( PYSVN_HAS_CLIENT_ADD_TO_CHANGELIST )
856 add_keyword_method("add_to_changelist", &pysvn_client::cmd_add_to_changelist, pysvn_client_add_to_changelist_doc );
857 #endif
858 add_keyword_method("annotate", &pysvn_client::cmd_annotate, pysvn_client_annotate_doc );
859 #if defined( PYSVN_HAS_CLIENT_ANNOTATE5 )
860 add_keyword_method("annotate2", &pysvn_client::cmd_annotate2, pysvn_client_annotate2_doc );
861 #endif
862 add_keyword_method("cat", &pysvn_client::cmd_cat, pysvn_client_cat_doc );
863 add_keyword_method("checkin", &pysvn_client::cmd_checkin, pysvn_client_checkin_doc );
864 add_keyword_method("checkout", &pysvn_client::cmd_checkout, pysvn_client_checkout_doc );
865 add_keyword_method("cleanup", &pysvn_client::cmd_cleanup, pysvn_client_cleanup_doc );
866 add_keyword_method("copy", &pysvn_client::cmd_copy, pysvn_client_copy_doc );
867 #if defined( PYSVN_HAS_CLIENT_COPY4 )
868 add_keyword_method("copy2", &pysvn_client::cmd_copy2, pysvn_client_copy2_doc );
869 #endif
870 add_keyword_method("diff", &pysvn_client::cmd_diff, pysvn_client_diff_doc );
871 #if defined( PYSVN_HAS_CLIENT_DIFF_PEG )
872 add_keyword_method("diff_peg", &pysvn_client::cmd_diff_peg, pysvn_client_diff_peg_doc );
873 #endif
874 #if defined( PYSVN_HAS_CLIENT_DIFF_SUMMARIZE )
875 add_keyword_method("diff_summarize", &pysvn_client::cmd_diff_summarize, pysvn_client_diff_summarize_doc );
876 add_keyword_method("diff_summarize_peg", &pysvn_client::cmd_diff_summarize_peg, pysvn_client_diff_summarize_peg_doc );
877 #endif
878 add_keyword_method("export", &pysvn_client::cmd_export, pysvn_client_export_doc );
879 #if defined( PYSVN_HAS_CLIENT_GET_CHANGELIST )
880 add_keyword_method("get_changelist", &pysvn_client::cmd_get_changelist, pysvn_client_get_changelist_doc );
881 #endif
882 #if defined( PYSVN_HAS_WC_ADM_DIR )
883 add_keyword_method("get_adm_dir", &pysvn_client::get_adm_dir, pysvn_client_get_adm_dir_doc );
884 #endif
885 add_keyword_method("get_auth_cache", &pysvn_client::get_auth_cache, pysvn_client_get_auth_cache_doc );
886 add_keyword_method("get_auto_props", &pysvn_client::get_auto_props, pysvn_client_get_auto_props_doc );
887 add_keyword_method("get_default_password", &pysvn_client::get_default_password, pysvn_client_get_default_password_doc );
888 add_keyword_method("get_default_username", &pysvn_client::get_default_username, pysvn_client_get_default_username_doc );
889 add_keyword_method("get_interactive", &pysvn_client::get_interactive, pysvn_client_get_interactive_doc );
890 add_keyword_method("get_store_passwords", &pysvn_client::get_store_passwords, pysvn_client_get_store_passwords_doc );
891 add_keyword_method("import_", &pysvn_client::cmd_import, pysvn_client_import__doc );
892 add_keyword_method("info", &pysvn_client::cmd_info, pysvn_client_info_doc );
893 #if defined( PYSVN_HAS_CLIENT_INFO )
894 add_keyword_method("info2", &pysvn_client::cmd_info2, pysvn_client_info2_doc );
895 #endif
896 #if defined( PYSVN_HAS_WC_ADM_DIR )
897 add_keyword_method("is_adm_dir", &pysvn_client::is_adm_dir, pysvn_client_is_adm_dir_doc );
898 #endif
899 add_keyword_method("is_url", &pysvn_client::is_url, pysvn_client_is_url_doc );
900 #if defined( PYSVN_HAS_CLIENT_LOCK )
901 add_keyword_method("lock", &pysvn_client::cmd_lock, pysvn_client_lock_doc );
902 #endif
903 add_keyword_method("log", &pysvn_client::cmd_log, pysvn_client_log_doc );
904 #if defined( PYSVN_HAS_CLIENT_LIST )
905 add_keyword_method("list", &pysvn_client::cmd_list, pysvn_client_list_doc );
906 #endif
907 add_keyword_method("ls", &pysvn_client::cmd_ls, pysvn_client_ls_doc );
908 add_keyword_method("merge", &pysvn_client::cmd_merge, pysvn_client_merge_doc );
909 #if defined( PYSVN_HAS_CLIENT_MERGE_PEG )
910 add_keyword_method("merge_peg", &pysvn_client::cmd_merge_peg, pysvn_client_merge_peg_doc );
911 #endif
912 #if defined( PYSVN_HAS_CLIENT_MERGE_PEG3 )
913 add_keyword_method("merge_peg2", &pysvn_client::cmd_merge_peg2, pysvn_client_merge_peg2_doc );
914 #endif
915 #if defined( PYSVN_HAS_CLIENT_MERGE_REINTEGRATE )
916 add_keyword_method("merge_reintegrate", &pysvn_client::cmd_merge_reintegrate, pysvn_client_merge_reintegrate_doc );
917 #endif
918 add_keyword_method("mkdir", &pysvn_client::cmd_mkdir, pysvn_client_mkdir_doc );
919 #if defined( PYSVN_HAS_CLIENT_MOVE5 )
920 add_keyword_method("move2", &pysvn_client::cmd_move2, pysvn_client_move2_doc );
921 #endif
922 add_keyword_method("move", &pysvn_client::cmd_move, pysvn_client_move_doc );
923 #if defined( PYSVN_HAS_CLIENT_PATCH )
924 add_keyword_method("patch", &pysvn_client::cmd_patch, pysvn_client_patch_doc );
925 #endif
926 add_keyword_method("propdel", &pysvn_client::cmd_propdel, pysvn_client_propdel_doc );
927 add_keyword_method("propget", &pysvn_client::cmd_propget, pysvn_client_propget_doc );
928 add_keyword_method("proplist", &pysvn_client::cmd_proplist, pysvn_client_proplist_doc );
929 add_keyword_method("propset", &pysvn_client::cmd_propset, pysvn_client_propset_doc );
930 #if defined( PYSVN_HAS_CLIENT_PROPSET_LOCAL )
931 add_keyword_method("propdel_local", &pysvn_client::cmd_propdel_local, pysvn_client_propdel_local_doc );
932 add_keyword_method("propset_local", &pysvn_client::cmd_propset_local, pysvn_client_propset_local_doc );
933 #endif
934 #if defined( PYSVN_HAS_CLIENT_PROPSET_REMOTE )
935 add_keyword_method("propdel_remote", &pysvn_client::cmd_propdel_remote, pysvn_client_propdel_remote_doc );
936 add_keyword_method("propset_remote", &pysvn_client::cmd_propset_remote, pysvn_client_propset_remote_doc );
937 #endif
938 add_keyword_method("relocate", &pysvn_client::cmd_relocate, pysvn_client_relocate_doc );
939 add_keyword_method("remove", &pysvn_client::cmd_remove, pysvn_client_remove_doc );
940 #if defined( PYSVN_HAS_CLIENT_REMOVE_FROM_CHANGELISTS )
941 add_keyword_method("remove_from_changelists", &pysvn_client::cmd_remove_from_changelists, pysvn_client_remove_from_changelists_doc );
942 #endif
943 add_keyword_method("resolved", &pysvn_client::cmd_resolved, pysvn_client_resolved_doc );
944 add_keyword_method("revert", &pysvn_client::cmd_revert, pysvn_client_revert_doc );
945 add_keyword_method("revpropdel", &pysvn_client::cmd_revpropdel, pysvn_client_revpropdel_doc );
946 add_keyword_method("revpropget", &pysvn_client::cmd_revpropget, pysvn_client_revpropget_doc );
947 add_keyword_method("revproplist", &pysvn_client::cmd_revproplist, pysvn_client_revproplist_doc );
948 add_keyword_method("revpropset", &pysvn_client::cmd_revpropset, pysvn_client_revpropset_doc );
949 #if defined( PYSVN_HAS_CLIENT_ROOT_URL_FROM_PATH )
950 add_keyword_method("root_url_from_path", &pysvn_client::cmd_root_url_from_path, pysvn_client_root_url_from_path_doc );
951 #endif
952 #if defined( PYSVN_HAS_WC_ADM_DIR )
953 add_keyword_method("set_adm_dir", &pysvn_client::set_adm_dir, pysvn_client_set_adm_dir_doc );
954 #endif
955 add_keyword_method("set_auth_cache", &pysvn_client::set_auth_cache, pysvn_client_set_auth_cache_doc );
956 add_keyword_method("set_auto_props", &pysvn_client::set_auto_props, pysvn_client_set_auto_props_doc );
957 add_keyword_method("set_default_password", &pysvn_client::set_default_password, pysvn_client_set_default_password_doc );
958 add_keyword_method("set_default_username", &pysvn_client::set_default_username, pysvn_client_set_default_username_doc );
959 add_keyword_method("set_interactive", &pysvn_client::set_interactive, pysvn_client_set_interactive_doc );
960 add_keyword_method("set_store_passwords", &pysvn_client::set_store_passwords, pysvn_client_set_store_passwords_doc );
961 #if defined( PYSVN_HAS_CLIENT_STATUS5 )
962 add_keyword_method("status2", &pysvn_client::cmd_status2, pysvn_client_status2_doc );
963 #endif
964 add_keyword_method("status", &pysvn_client::cmd_status, pysvn_client_status_doc );
965 add_keyword_method("switch", &pysvn_client::cmd_switch, pysvn_client_switch_doc );
966 #if defined( PYSVN_HAS_CLIENT_LOCK )
967 add_keyword_method("unlock", &pysvn_client::cmd_unlock, pysvn_client_unlock_doc );
968 #endif
969 #if defined( PYSVN_HAS_CLIENT_UPGRADE )
970 add_keyword_method("upgrade", &pysvn_client::cmd_upgrade, pysvn_client_upgrade_doc );
971 #endif
972 add_keyword_method("update", &pysvn_client::cmd_update, pysvn_client_update_doc );
973 #if defined( PYSVN_HAS_CLIENT_VACUUM )
974 add_keyword_method("vacuum", &pysvn_client::cmd_vacuum, pysvn_client_vacuum_doc );
975 #endif
976 }
977