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 //
11 // pysvn_client_cmd_prop.cpp
12 //
13 #if defined( _MSC_VER )
14 // disable warning C4786: symbol greater than 255 character,
15 // nessesary to ignore as <map> causes lots of warning
16 #pragma warning(disable: 4786)
17 #endif
18
19 #include "pysvn.hpp"
20 #include "pysvn_svnenv.hpp"
21 #include "pysvn_static_strings.hpp"
22
cmd_add(const Py::Tuple & a_args,const Py::Dict & a_kws)23 Py::Object pysvn_client::cmd_add( const Py::Tuple &a_args, const Py::Dict &a_kws )
24 {
25 static argument_description args_desc[] =
26 {
27 { true, name_path },
28 { false, name_recurse },
29 #if defined( PYSVN_HAS_CLIENT_ADD2 )
30 { false, name_force },
31 #endif
32 #if defined( PYSVN_HAS_CLIENT_ADD3 )
33 { false, name_ignore },
34 #endif
35 #if defined( PYSVN_HAS_CLIENT_ADD4 )
36 { false, name_depth },
37 { false, name_add_parents },
38 #endif
39 #if defined( PYSVN_HAS_CLIENT_ADD5 )
40 { false, name_autoprops },
41 #endif
42
43 { false, NULL }
44 };
45 FunctionArguments args( "add", args_desc, a_args, a_kws );
46 args.check();
47
48 Py::List path_list( toListOfStrings( args.getArg( name_path ) ) );
49
50 #if defined( PYSVN_HAS_CLIENT_ADD2 )
51 bool force = args.getBoolean( name_force, false );
52 #endif
53 #if defined( PYSVN_HAS_CLIENT_ADD3 )
54 bool ignore = args.getBoolean( name_ignore, true );
55 #endif
56 #if defined( PYSVN_HAS_CLIENT_ADD4 )
57 svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_empty );
58 bool add_parents = args.getBoolean( name_add_parents, false );
59 #else
60 bool recurse = args.getBoolean( name_recurse, true );
61 #endif
62 #if defined( PYSVN_HAS_CLIENT_ADD5 )
63 bool autoprops = args.getBoolean( name_autoprops, true );
64 #endif
65
66 SvnPool pool( m_context );
67 try
68 {
69 for( Py::List::size_type i=0; i<path_list.length(); i++ )
70 {
71 Py::Bytes path_str( asUtf8Bytes( path_list[i] ) );
72 std::string norm_path( svnNormalisedIfPath( path_str.as_std_string(), pool ) );
73
74 checkThreadPermission();
75
76 PythonAllowThreads permission( m_context );
77
78 SvnPool pool( m_context );
79
80 #if defined( PYSVN_HAS_CLIENT_ADD5 )
81 svn_error_t * error = svn_client_add5
82 (
83 norm_path.c_str(),
84 depth,
85 force,
86 !ignore,
87 !autoprops,
88 add_parents,
89 m_context,
90 pool
91 );
92 #elif defined( PYSVN_HAS_CLIENT_ADD4 )
93 svn_error_t * error = svn_client_add4
94 (
95 norm_path.c_str(),
96 depth,
97 force,
98 !ignore,
99 add_parents,
100 m_context,
101 pool
102 );
103 #elif defined( PYSVN_HAS_CLIENT_ADD3 )
104 svn_error_t * error = svn_client_add3
105 (
106 norm_path.c_str(),
107 recurse,
108 force,
109 !ignore,
110 m_context,
111 pool
112 );
113 #elif defined( PYSVN_HAS_CLIENT_ADD2 )
114 svn_error_t * error = svn_client_add2
115 (
116 norm_path.c_str(),
117 recurse,
118 force,
119 m_context,
120 pool
121 );
122 #else
123 svn_error_t * error = svn_client_add
124 (
125 norm_path.c_str(),
126 recurse,
127 m_context,
128 pool
129 );
130 #endif
131 permission.allowThisThread();
132 if( error != NULL )
133 throw SvnException( error );
134 }
135 }
136 catch( SvnException &e )
137 {
138 // use callback error over ClientException
139 m_context.checkForError( m_module.client_error );
140
141 throw_client_error( e );
142 }
143
144 return Py::None();
145 }
146
cmd_cat(const Py::Tuple & a_args,const Py::Dict & a_kws)147 Py::Object pysvn_client::cmd_cat( const Py::Tuple &a_args, const Py::Dict &a_kws )
148 {
149 static argument_description args_desc[] =
150 {
151 { true, name_url_or_path },
152 { false, name_revision },
153 #if defined( PYSVN_HAS_CLIENT_CAT2 )
154 { false, name_peg_revision },
155 #endif
156 #if defined( PYSVN_HAS_CLIENT_CAT3 )
157 { false, name_expand_keywords },
158 { false, name_get_props },
159 #endif
160 { false, NULL }
161 };
162 FunctionArguments args( "cat", args_desc, a_args, a_kws );
163 args.check();
164
165 std::string path( args.getUtf8String( name_url_or_path ) );
166 svn_opt_revision_t revision = args.getRevision( name_revision, svn_opt_revision_head );
167 #if defined( PYSVN_HAS_CLIENT_CAT2 )
168 svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision );
169
170 #endif
171 bool is_url = is_svn_url( path );
172 #if defined( PYSVN_HAS_CLIENT_CAT2 )
173 revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path );
174 #endif
175 revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path );
176
177 SvnPool pool( m_context );
178
179 svn_stringbuf_t * stringbuf = svn_stringbuf_create( empty_string, pool );
180 svn_stream_t * stream = svn_stream_from_stringbuf( stringbuf, pool );
181
182 #if defined( PYSVN_HAS_CLIENT_CAT3 )
183 bool get_props = args.getBoolean( name_get_props, false );
184 bool expand_keywords = args.getBoolean( name_expand_keywords, false );
185
186 apr_hash_t *props = NULL;
187 apr_hash_t **props_ptr;
188 if( get_props )
189 {
190 props_ptr = &props;
191 }
192 else
193 {
194 props_ptr = NULL;
195 }
196 #endif
197
198 try
199 {
200 std::string norm_path( svnNormalisedIfPath( path, pool ) );
201
202 checkThreadPermission();
203
204 PythonAllowThreads permission( m_context );
205 #if defined( PYSVN_HAS_CLIENT_CAT3 )
206 svn_error_t *error = svn_client_cat3
207 (
208 props_ptr,
209 stream,
210 norm_path.c_str(),
211 &peg_revision,
212 &revision,
213 expand_keywords,
214 m_context,
215 pool,
216 pool
217 );
218 #elif defined( PYSVN_HAS_CLIENT_CAT2 )
219 svn_error_t *error = svn_client_cat2
220 (
221 stream,
222 norm_path.c_str(),
223 &peg_revision,
224 &revision,
225 m_context,
226 pool
227 );
228 #else
229 svn_error_t *error = svn_client_cat
230 (
231 stream,
232 norm_path.c_str(),
233 &revision,
234 m_context,
235 pool
236 );
237 #endif
238
239 permission.allowThisThread();
240 if (error != 0)
241 throw SvnException (error);
242 }
243 catch( SvnException &e )
244 {
245 // use callback error over ClientException
246 m_context.checkForError( m_module.client_error );
247
248 throw_client_error( e );
249 }
250
251 // return the bytes as is to the application
252 // we can assume nothing about them
253 Py::Bytes contents( stringbuf->data, (int)stringbuf->len );
254 #if defined( PYSVN_HAS_CLIENT_CAT3 )
255 if( get_props )
256 {
257 Py::Tuple result( 2 );
258
259 result[0] = contents;
260 result[1] = propsToObject( props, pool );
261
262 return result;
263 }
264 else
265 #endif
266 {
267 return contents;
268 }
269 }
270
cmd_mkdir(const Py::Tuple & a_args,const Py::Dict & a_kws)271 Py::Object pysvn_client::cmd_mkdir( const Py::Tuple &a_args, const Py::Dict &a_kws )
272 {
273 static argument_description args_desc[] =
274 {
275 { true, name_url_or_path },
276 { false, name_log_message },
277 #if defined( PYSVN_HAS_CLIENT_MKDIR3 )
278 { false, name_make_parents },
279 { false, name_revprops },
280 #endif
281 { false, NULL }
282 };
283 FunctionArguments args( "mkdir", args_desc, a_args, a_kws );
284 args.check();
285
286 // message that explains to the user the type error that may be thrown next
287 std::string type_error_message;
288
289 // args to the mkdir call
290 std::string message;
291 bool have_message = false;
292
293 SvnPool pool( m_context );
294
295 apr_array_header_t *targets = targetsFromStringOrList( args.getArg( name_url_or_path ), pool );
296
297 #if defined( PYSVN_HAS_CLIENT_MKDIR3 )
298 bool make_parents = args.getBoolean( name_make_parents, false );
299
300 apr_hash_t *revprops = NULL;
301 if( args.hasArg( name_revprops ) )
302 {
303 Py::Object py_revprop = args.getArg( name_revprops );
304 if( !py_revprop.isNone() )
305 {
306 revprops = hashOfStringsFromDictOfStrings( py_revprop, pool );
307 }
308 }
309 #endif
310
311 try
312 {
313 type_error_message = "expecting string message (arg 2)";
314 if( args.hasArg( name_log_message ) )
315 {
316 message = args.getUtf8String( name_log_message );
317 have_message = true;
318 }
319 }
320 catch( Py::TypeError & )
321 {
322 throw Py::TypeError( type_error_message );
323 }
324
325
326 #if defined( PYSVN_HAS_CLIENT_MKDIR4 )
327 CommitInfoResult commit_info( pool );
328 #else
329 pysvn_commit_info_t *commit_info = NULL;
330 #endif
331
332 try
333 {
334 checkThreadPermission();
335
336 PythonAllowThreads permission( m_context );
337
338 if( have_message )
339 {
340 m_context.setLogMessage( message.c_str() );
341 }
342
343 #if defined( PYSVN_HAS_CLIENT_MKDIR4 )
344 svn_error_t *error = svn_client_mkdir4
345 (
346 targets,
347 make_parents,
348 revprops,
349 commit_info.callback(),
350 commit_info.baton(),
351 m_context,
352 pool
353 );
354 #elif defined( PYSVN_HAS_CLIENT_MKDIR3 )
355 svn_error_t *error = svn_client_mkdir3
356 (
357 &commit_info, // changed type
358 targets,
359 make_parents,
360 revprops,
361 m_context,
362 pool
363 );
364 #elif defined( PYSVN_HAS_CLIENT_MKDIR2 )
365 svn_error_t *error = svn_client_mkdir2
366 (
367 &commit_info, // changed type
368 targets,
369 m_context,
370 pool
371 );
372 #else
373 svn_error_t *error = svn_client_mkdir
374 (
375 &commit_info,
376 targets,
377 m_context,
378 pool
379 );
380 #endif
381 permission.allowThisThread();
382 if( error != 0 )
383 throw SvnException( error );
384 }
385 catch( SvnException &e )
386 {
387 // use callback error over ClientException
388 m_context.checkForError( m_module.client_error );
389
390 throw_client_error( e );
391 }
392
393 #if defined( PYSVN_HAS_CLIENT_MKDIR4 )
394 return toObject( commit_info, m_wrapper_commit_info, m_commit_info_style );
395 #else
396 return toObject( commit_info, m_commit_info_style );
397 #endif
398 }
399
cmd_remove(const Py::Tuple & a_args,const Py::Dict & a_kws)400 Py::Object pysvn_client::cmd_remove( const Py::Tuple &a_args, const Py::Dict &a_kws )
401 {
402 static argument_description args_desc[] =
403 {
404 { true, name_url_or_path },
405 { false, name_force },
406 #if defined( PYSVN_HAS_CLIENT_DELETE3 )
407 { false, name_keep_local },
408 { false, name_revprops },
409 #endif
410 { false, NULL }
411 };
412 FunctionArguments args( "remove", args_desc, a_args, a_kws );
413 args.check();
414
415 SvnPool pool( m_context );
416
417 bool force = args.getBoolean( name_force, false );
418 #if defined( PYSVN_HAS_CLIENT_DELETE3 )
419
420 bool keep_local = args.getBoolean( name_keep_local, false );
421
422 apr_hash_t *revprops = NULL;
423 if( args.hasArg( name_revprops ) )
424 {
425 Py::Object py_revprop = args.getArg( name_revprops );
426 if( !py_revprop.isNone() )
427 {
428 revprops = hashOfStringsFromDictOfStrings( py_revprop, pool );
429 }
430 }
431 #endif
432
433 apr_array_header_t *targets = targetsFromStringOrList( args.getArg( name_url_or_path ), pool );
434
435 #if defined( PYSVN_HAS_CLIENT_MKDIR4 )
436 CommitInfoResult commit_info( pool );
437 #else
438 pysvn_commit_info_t *commit_info = NULL;
439 #endif
440
441 try
442 {
443 checkThreadPermission();
444
445 PythonAllowThreads permission( m_context );
446
447 #if defined( PYSVN_HAS_CLIENT_DELETE4 )
448 svn_error_t *error = svn_client_delete4
449 (
450 targets,
451 force,
452 keep_local,
453 revprops,
454 commit_info.callback(),
455 commit_info.baton(),
456 m_context,
457 pool
458 );
459 #elif defined( PYSVN_HAS_CLIENT_DELETE3 )
460 svn_error_t *error = svn_client_delete3
461 (
462 &commit_info,
463 targets,
464 force,
465 keep_local,
466 revprops,
467 m_context,
468 pool
469 );
470 #elif defined( PYSVN_HAS_CLIENT_DELETE2 )
471 svn_error_t *error = svn_client_delete2
472 (
473 &commit_info, // commit_info changed
474 targets,
475 force,
476 m_context,
477 pool
478 );
479 #else
480 svn_error_t *error = svn_client_delete
481 (
482 &commit_info,
483 targets,
484 force,
485 m_context,
486 pool
487 );
488 #endif
489 permission.allowThisThread();
490 if( error != NULL )
491 throw SvnException( error );
492 }
493 catch( SvnException &e )
494 {
495 // use callback error over ClientException
496 m_context.checkForError( m_module.client_error );
497
498 throw_client_error( e );
499 }
500
501 #if defined( PYSVN_HAS_CLIENT_MKDIR4 )
502 return toObject( commit_info, m_wrapper_commit_info, m_commit_info_style );
503 #else
504 return toObject( commit_info, m_commit_info_style );
505 #endif
506 }
507
cmd_revert(const Py::Tuple & a_args,const Py::Dict & a_kws)508 Py::Object pysvn_client::cmd_revert( const Py::Tuple &a_args, const Py::Dict &a_kws )
509 {
510 static argument_description args_desc[] =
511 {
512 { true, name_path },
513 { false, name_recurse },
514 #if defined( PYSVN_HAS_CLIENT_REVERT2 )
515 { false, name_depth },
516 { false, name_changelists },
517 #endif
518 #if defined( PYSVN_HAS_CLIENT_REVERT3 )
519 { false, name_clear_changelists },
520 { false, name_metadata_only },
521 #endif
522 { false, NULL }
523 };
524 FunctionArguments args( "revert", args_desc, a_args, a_kws );
525 args.check();
526
527 std::string type_error_message;
528
529 SvnPool pool( m_context );
530 apr_array_header_t *targets = targetsFromStringOrList( args.getArg( name_path ), pool );
531
532 try
533 {
534 #if defined( PYSVN_HAS_CLIENT_REVERT2 )
535 apr_array_header_t *changelists = NULL;
536
537 if( args.hasArg( name_changelists ) )
538 {
539 changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool );
540 }
541 svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_empty, svn_depth_infinity, svn_depth_empty );
542 #else
543 bool recurse = args.getBoolean( name_recurse, false );
544 #endif
545
546 #if defined( PYSVN_HAS_CLIENT_REVERT3 )
547 bool clear_changelists = args.getBoolean( name_clear_changelists, false );
548 bool metadata_only = args.getBoolean( name_metadata_only, false );
549 #endif
550 try
551 {
552 checkThreadPermission();
553
554 PythonAllowThreads permission( m_context );
555
556 #if defined( PYSVN_HAS_CLIENT_REVERT3 )
557 svn_error_t *error = svn_client_revert3
558 (
559 targets,
560 depth,
561 changelists,
562 clear_changelists,
563 metadata_only,
564 m_context,
565 pool
566 );
567 #elif defined( PYSVN_HAS_CLIENT_REVERT2 )
568 svn_error_t *error = svn_client_revert2
569 (
570 targets,
571 depth,
572 changelists,
573 m_context,
574 pool
575 );
576 #else
577 svn_error_t *error = svn_client_revert
578 (
579 targets,
580 recurse,
581 m_context,
582 pool
583 );
584 #endif
585 permission.allowThisThread();
586 if( error != NULL )
587 throw SvnException( error );
588 }
589 catch( SvnException &e )
590 {
591 // use callback error over ClientException
592 m_context.checkForError( m_module.client_error );
593
594 throw_client_error( e );
595 }
596 }
597 catch( Py::TypeError & )
598 {
599 throw Py::TypeError( type_error_message );
600 }
601
602 return Py::None();
603 }
604
605