deprecated.c revision 299742
1/* 2 * deprecated.c: holding file for all deprecated APIs. 3 * "we can't lose 'em, but we can shun 'em!" 4 * 5 * ==================================================================== 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 * ==================================================================== 23 */ 24 25/* ==================================================================== */ 26 27 28 29/*** Includes. ***/ 30 31/* We define this here to remove any further warnings about the usage of 32 deprecated functions in this file. */ 33#define SVN_DEPRECATED 34 35#include <string.h> 36#include "svn_client.h" 37#include "svn_path.h" 38#include "svn_compat.h" 39#include "svn_hash.h" 40#include "svn_props.h" 41#include "svn_utf.h" 42#include "svn_string.h" 43#include "svn_pools.h" 44 45#include "client.h" 46#include "mergeinfo.h" 47 48#include "private/svn_opt_private.h" 49#include "private/svn_wc_private.h" 50#include "svn_private_config.h" 51 52 53 54 55/*** Code. ***/ 56 57 58/* Baton for capture_commit_info() */ 59struct capture_baton_t { 60 svn_commit_info_t **info; 61 apr_pool_t *pool; 62}; 63 64 65/* Callback which implements svn_commit_callback2_t for use with some 66 backward compat functions. */ 67static svn_error_t * 68capture_commit_info(const svn_commit_info_t *commit_info, 69 void *baton, 70 apr_pool_t *pool) 71{ 72 struct capture_baton_t *cb = baton; 73 74 *(cb->info) = svn_commit_info_dup(commit_info, cb->pool); 75 76 return SVN_NO_ERROR; 77} 78 79 80/*** From add.c ***/ 81svn_error_t * 82svn_client_add4(const char *path, 83 svn_depth_t depth, 84 svn_boolean_t force, 85 svn_boolean_t no_ignore, 86 svn_boolean_t add_parents, 87 svn_client_ctx_t *ctx, 88 apr_pool_t *pool) 89{ 90 return svn_client_add5(path, depth, force, no_ignore, FALSE, add_parents, 91 ctx, pool); 92} 93 94svn_error_t * 95svn_client_add3(const char *path, 96 svn_boolean_t recursive, 97 svn_boolean_t force, 98 svn_boolean_t no_ignore, 99 svn_client_ctx_t *ctx, 100 apr_pool_t *pool) 101{ 102 return svn_client_add4(path, SVN_DEPTH_INFINITY_OR_EMPTY(recursive), 103 force, no_ignore, FALSE, ctx, 104 pool); 105} 106 107svn_error_t * 108svn_client_add2(const char *path, 109 svn_boolean_t recursive, 110 svn_boolean_t force, 111 svn_client_ctx_t *ctx, 112 apr_pool_t *pool) 113{ 114 return svn_client_add3(path, recursive, force, FALSE, ctx, pool); 115} 116 117svn_error_t * 118svn_client_add(const char *path, 119 svn_boolean_t recursive, 120 svn_client_ctx_t *ctx, 121 apr_pool_t *pool) 122{ 123 return svn_client_add3(path, recursive, FALSE, FALSE, ctx, pool); 124} 125 126svn_error_t * 127svn_client_mkdir3(svn_commit_info_t **commit_info_p, 128 const apr_array_header_t *paths, 129 svn_boolean_t make_parents, 130 const apr_hash_t *revprop_table, 131 svn_client_ctx_t *ctx, 132 apr_pool_t *pool) 133{ 134 struct capture_baton_t cb; 135 136 cb.info = commit_info_p; 137 cb.pool = pool; 138 139 return svn_client_mkdir4(paths, make_parents, revprop_table, 140 capture_commit_info, &cb, ctx, pool); 141} 142 143svn_error_t * 144svn_client_mkdir2(svn_commit_info_t **commit_info_p, 145 const apr_array_header_t *paths, 146 svn_client_ctx_t *ctx, 147 apr_pool_t *pool) 148{ 149 return svn_client_mkdir3(commit_info_p, paths, FALSE, NULL, ctx, pool); 150} 151 152 153svn_error_t * 154svn_client_mkdir(svn_client_commit_info_t **commit_info_p, 155 const apr_array_header_t *paths, 156 svn_client_ctx_t *ctx, 157 apr_pool_t *pool) 158{ 159 svn_commit_info_t *commit_info = NULL; 160 svn_error_t *err; 161 162 err = svn_client_mkdir2(&commit_info, paths, ctx, pool); 163 /* These structs have the same layout for the common fields. */ 164 *commit_info_p = (svn_client_commit_info_t *) commit_info; 165 return svn_error_trace(err); 166} 167 168/*** From blame.c ***/ 169 170struct blame_receiver_wrapper_baton2 { 171 void *baton; 172 svn_client_blame_receiver2_t receiver; 173}; 174 175static svn_error_t * 176blame_wrapper_receiver2(void *baton, 177 svn_revnum_t start_revnum, 178 svn_revnum_t end_revnum, 179 apr_int64_t line_no, 180 svn_revnum_t revision, 181 apr_hash_t *rev_props, 182 svn_revnum_t merged_revision, 183 apr_hash_t *merged_rev_props, 184 const char *merged_path, 185 const char *line, 186 svn_boolean_t local_change, 187 apr_pool_t *pool) 188{ 189 struct blame_receiver_wrapper_baton2 *brwb = baton; 190 const char *author = NULL; 191 const char *date = NULL; 192 const char *merged_author = NULL; 193 const char *merged_date = NULL; 194 195 if (rev_props != NULL) 196 { 197 author = svn_prop_get_value(rev_props, SVN_PROP_REVISION_AUTHOR); 198 date = svn_prop_get_value(rev_props, SVN_PROP_REVISION_DATE); 199 } 200 if (merged_rev_props != NULL) 201 { 202 merged_author = svn_prop_get_value(merged_rev_props, 203 SVN_PROP_REVISION_AUTHOR); 204 merged_date = svn_prop_get_value(merged_rev_props, 205 SVN_PROP_REVISION_DATE); 206 } 207 208 if (brwb->receiver) 209 return brwb->receiver(brwb->baton, line_no, revision, author, date, 210 merged_revision, merged_author, merged_date, 211 merged_path, line, pool); 212 213 return SVN_NO_ERROR; 214} 215 216svn_error_t * 217svn_client_blame4(const char *target, 218 const svn_opt_revision_t *peg_revision, 219 const svn_opt_revision_t *start, 220 const svn_opt_revision_t *end, 221 const svn_diff_file_options_t *diff_options, 222 svn_boolean_t ignore_mime_type, 223 svn_boolean_t include_merged_revisions, 224 svn_client_blame_receiver2_t receiver, 225 void *receiver_baton, 226 svn_client_ctx_t *ctx, 227 apr_pool_t *pool) 228{ 229 struct blame_receiver_wrapper_baton2 baton; 230 231 baton.receiver = receiver; 232 baton.baton = receiver_baton; 233 234 return svn_client_blame5(target, peg_revision, start, end, diff_options, 235 ignore_mime_type, include_merged_revisions, 236 blame_wrapper_receiver2, &baton, ctx, pool); 237} 238 239 240/* Baton for use with wrap_blame_receiver */ 241struct blame_receiver_wrapper_baton { 242 void *baton; 243 svn_client_blame_receiver_t receiver; 244}; 245 246/* This implements svn_client_blame_receiver2_t */ 247static svn_error_t * 248blame_wrapper_receiver(void *baton, 249 apr_int64_t line_no, 250 svn_revnum_t revision, 251 const char *author, 252 const char *date, 253 svn_revnum_t merged_revision, 254 const char *merged_author, 255 const char *merged_date, 256 const char *merged_path, 257 const char *line, 258 apr_pool_t *pool) 259{ 260 struct blame_receiver_wrapper_baton *brwb = baton; 261 262 if (brwb->receiver) 263 return brwb->receiver(brwb->baton, 264 line_no, revision, author, date, line, pool); 265 266 return SVN_NO_ERROR; 267} 268 269static void 270wrap_blame_receiver(svn_client_blame_receiver2_t *receiver2, 271 void **receiver2_baton, 272 svn_client_blame_receiver_t receiver, 273 void *receiver_baton, 274 apr_pool_t *pool) 275{ 276 struct blame_receiver_wrapper_baton *brwb = apr_palloc(pool, sizeof(*brwb)); 277 278 /* Set the user provided old format callback in the baton. */ 279 brwb->baton = receiver_baton; 280 brwb->receiver = receiver; 281 282 *receiver2_baton = brwb; 283 *receiver2 = blame_wrapper_receiver; 284} 285 286svn_error_t * 287svn_client_blame3(const char *target, 288 const svn_opt_revision_t *peg_revision, 289 const svn_opt_revision_t *start, 290 const svn_opt_revision_t *end, 291 const svn_diff_file_options_t *diff_options, 292 svn_boolean_t ignore_mime_type, 293 svn_client_blame_receiver_t receiver, 294 void *receiver_baton, 295 svn_client_ctx_t *ctx, 296 apr_pool_t *pool) 297{ 298 svn_client_blame_receiver2_t receiver2; 299 void *receiver2_baton; 300 301 wrap_blame_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton, 302 pool); 303 304 return svn_client_blame4(target, peg_revision, start, end, diff_options, 305 ignore_mime_type, FALSE, receiver2, receiver2_baton, 306 ctx, pool); 307} 308 309/* svn_client_blame3 guarantees 'no EOL chars' as part of the receiver 310 LINE argument. Older versions depend on the fact that if a CR is 311 required, that CR is already part of the LINE data. 312 313 Because of this difference, we need to trap old receivers and append 314 a CR to LINE before passing it on to the actual receiver on platforms 315 which want CRLF line termination. 316 317*/ 318 319struct wrapped_receiver_baton_s 320{ 321 svn_client_blame_receiver_t orig_receiver; 322 void *orig_baton; 323}; 324 325static svn_error_t * 326wrapped_receiver(void *baton, 327 apr_int64_t line_no, 328 svn_revnum_t revision, 329 const char *author, 330 const char *date, 331 const char *line, 332 apr_pool_t *pool) 333{ 334 struct wrapped_receiver_baton_s *b = baton; 335 svn_stringbuf_t *expanded_line = svn_stringbuf_create(line, pool); 336 337 svn_stringbuf_appendbyte(expanded_line, '\r'); 338 339 return b->orig_receiver(b->orig_baton, line_no, revision, author, 340 date, expanded_line->data, pool); 341} 342 343static void 344wrap_pre_blame3_receiver(svn_client_blame_receiver_t *receiver, 345 void **receiver_baton, 346 apr_pool_t *pool) 347{ 348 if (sizeof(APR_EOL_STR) == 3) 349 { 350 struct wrapped_receiver_baton_s *b = apr_palloc(pool,sizeof(*b)); 351 352 b->orig_receiver = *receiver; 353 b->orig_baton = *receiver_baton; 354 355 *receiver_baton = b; 356 *receiver = wrapped_receiver; 357 } 358} 359 360svn_error_t * 361svn_client_blame2(const char *target, 362 const svn_opt_revision_t *peg_revision, 363 const svn_opt_revision_t *start, 364 const svn_opt_revision_t *end, 365 svn_client_blame_receiver_t receiver, 366 void *receiver_baton, 367 svn_client_ctx_t *ctx, 368 apr_pool_t *pool) 369{ 370 wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool); 371 return svn_client_blame3(target, peg_revision, start, end, 372 svn_diff_file_options_create(pool), FALSE, 373 receiver, receiver_baton, ctx, pool); 374} 375svn_error_t * 376svn_client_blame(const char *target, 377 const svn_opt_revision_t *start, 378 const svn_opt_revision_t *end, 379 svn_client_blame_receiver_t receiver, 380 void *receiver_baton, 381 svn_client_ctx_t *ctx, 382 apr_pool_t *pool) 383{ 384 wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool); 385 return svn_client_blame2(target, end, start, end, 386 receiver, receiver_baton, ctx, pool); 387} 388 389/*** From cmdline.c ***/ 390svn_error_t * 391svn_client_args_to_target_array(apr_array_header_t **targets_p, 392 apr_getopt_t *os, 393 const apr_array_header_t *known_targets, 394 svn_client_ctx_t *ctx, 395 apr_pool_t *pool) 396{ 397 return svn_client_args_to_target_array2(targets_p, os, known_targets, ctx, 398 FALSE, pool); 399} 400 401/*** From commit.c ***/ 402svn_error_t * 403svn_client_import4(const char *path, 404 const char *url, 405 svn_depth_t depth, 406 svn_boolean_t no_ignore, 407 svn_boolean_t ignore_unknown_node_types, 408 const apr_hash_t *revprop_table, 409 svn_commit_callback2_t commit_callback, 410 void *commit_baton, 411 svn_client_ctx_t *ctx, 412 apr_pool_t *pool) 413{ 414 return svn_error_trace(svn_client_import5(path, url, depth, no_ignore, 415 FALSE, ignore_unknown_node_types, 416 revprop_table, 417 NULL, NULL, 418 commit_callback, commit_baton, 419 ctx, pool)); 420} 421 422 423svn_error_t * 424svn_client_import3(svn_commit_info_t **commit_info_p, 425 const char *path, 426 const char *url, 427 svn_depth_t depth, 428 svn_boolean_t no_ignore, 429 svn_boolean_t ignore_unknown_node_types, 430 const apr_hash_t *revprop_table, 431 svn_client_ctx_t *ctx, 432 apr_pool_t *pool) 433{ 434 struct capture_baton_t cb; 435 436 cb.info = commit_info_p; 437 cb.pool = pool; 438 439 return svn_client_import4(path, url, depth, no_ignore, 440 ignore_unknown_node_types, revprop_table, 441 capture_commit_info, &cb, ctx, pool); 442} 443 444svn_error_t * 445svn_client_import2(svn_commit_info_t **commit_info_p, 446 const char *path, 447 const char *url, 448 svn_boolean_t nonrecursive, 449 svn_boolean_t no_ignore, 450 svn_client_ctx_t *ctx, 451 apr_pool_t *pool) 452{ 453 return svn_client_import3(commit_info_p, 454 path, url, 455 SVN_DEPTH_INFINITY_OR_FILES(! nonrecursive), 456 no_ignore, FALSE, NULL, ctx, pool); 457} 458 459svn_error_t * 460svn_client_import(svn_client_commit_info_t **commit_info_p, 461 const char *path, 462 const char *url, 463 svn_boolean_t nonrecursive, 464 svn_client_ctx_t *ctx, 465 apr_pool_t *pool) 466{ 467 svn_commit_info_t *commit_info = NULL; 468 svn_error_t *err; 469 470 err = svn_client_import2(&commit_info, 471 path, url, nonrecursive, 472 FALSE, ctx, pool); 473 /* These structs have the same layout for the common fields. */ 474 *commit_info_p = (svn_client_commit_info_t *) commit_info; 475 return svn_error_trace(err); 476} 477 478 479/* Wrapper notify_func2 function and baton for downgrading 480 svn_wc_notify_commit_copied and svn_wc_notify_commit_copied_replaced 481 to svn_wc_notify_commit_added and svn_wc_notify_commit_replaced, 482 respectively. */ 483struct downgrade_commit_copied_notify_baton 484{ 485 svn_wc_notify_func2_t orig_notify_func2; 486 void *orig_notify_baton2; 487}; 488 489static void 490downgrade_commit_copied_notify_func(void *baton, 491 const svn_wc_notify_t *notify, 492 apr_pool_t *pool) 493{ 494 struct downgrade_commit_copied_notify_baton *b = baton; 495 496 if (notify->action == svn_wc_notify_commit_copied) 497 { 498 svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool); 499 my_notify->action = svn_wc_notify_commit_added; 500 notify = my_notify; 501 } 502 else if (notify->action == svn_wc_notify_commit_copied_replaced) 503 { 504 svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool); 505 my_notify->action = svn_wc_notify_commit_replaced; 506 notify = my_notify; 507 } 508 509 /* Call the wrapped notification system (if any) with MY_NOTIFY, 510 which is either the original NOTIFY object, or a tweaked deep 511 copy thereof. */ 512 if (b->orig_notify_func2) 513 b->orig_notify_func2(b->orig_notify_baton2, notify, pool); 514} 515 516svn_error_t * 517svn_client_commit5(const apr_array_header_t *targets, 518 svn_depth_t depth, 519 svn_boolean_t keep_locks, 520 svn_boolean_t keep_changelists, 521 svn_boolean_t commit_as_operations, 522 const apr_array_header_t *changelists, 523 const apr_hash_t *revprop_table, 524 svn_commit_callback2_t commit_callback, 525 void *commit_baton, 526 svn_client_ctx_t *ctx, 527 apr_pool_t *pool) 528{ 529 return svn_client_commit6(targets, depth, keep_locks, keep_changelists, 530 commit_as_operations, 531 FALSE, /* include_file_externals */ 532 FALSE, /* include_dir_externals */ 533 changelists, revprop_table, commit_callback, 534 commit_baton, ctx, pool); 535} 536 537svn_error_t * 538svn_client_commit4(svn_commit_info_t **commit_info_p, 539 const apr_array_header_t *targets, 540 svn_depth_t depth, 541 svn_boolean_t keep_locks, 542 svn_boolean_t keep_changelists, 543 const apr_array_header_t *changelists, 544 const apr_hash_t *revprop_table, 545 svn_client_ctx_t *ctx, 546 apr_pool_t *pool) 547{ 548 struct capture_baton_t cb; 549 struct downgrade_commit_copied_notify_baton notify_baton; 550 svn_error_t *err; 551 552 notify_baton.orig_notify_func2 = ctx->notify_func2; 553 notify_baton.orig_notify_baton2 = ctx->notify_baton2; 554 555 *commit_info_p = NULL; 556 cb.info = commit_info_p; 557 cb.pool = pool; 558 559 /* Swap out the notification system (if any) with a thin filtering 560 wrapper. */ 561 if (ctx->notify_func2) 562 { 563 ctx->notify_func2 = downgrade_commit_copied_notify_func; 564 ctx->notify_baton2 = ¬ify_baton; 565 } 566 567 err = svn_client_commit5(targets, depth, keep_locks, keep_changelists, FALSE, 568 changelists, revprop_table, 569 capture_commit_info, &cb, ctx, pool); 570 571 /* Ensure that the original notification system is in place. */ 572 ctx->notify_func2 = notify_baton.orig_notify_func2; 573 ctx->notify_baton2 = notify_baton.orig_notify_baton2; 574 575 SVN_ERR(err); 576 577 if (! *commit_info_p) 578 *commit_info_p = svn_create_commit_info(pool); 579 580 return SVN_NO_ERROR; 581} 582 583svn_error_t * 584svn_client_commit3(svn_commit_info_t **commit_info_p, 585 const apr_array_header_t *targets, 586 svn_boolean_t recurse, 587 svn_boolean_t keep_locks, 588 svn_client_ctx_t *ctx, 589 apr_pool_t *pool) 590{ 591 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recurse); 592 593 return svn_client_commit4(commit_info_p, targets, depth, keep_locks, 594 FALSE, NULL, NULL, ctx, pool); 595} 596 597svn_error_t * 598svn_client_commit2(svn_client_commit_info_t **commit_info_p, 599 const apr_array_header_t *targets, 600 svn_boolean_t recurse, 601 svn_boolean_t keep_locks, 602 svn_client_ctx_t *ctx, 603 apr_pool_t *pool) 604{ 605 svn_commit_info_t *commit_info = NULL; 606 svn_error_t *err; 607 608 err = svn_client_commit3(&commit_info, targets, recurse, keep_locks, 609 ctx, pool); 610 /* These structs have the same layout for the common fields. */ 611 *commit_info_p = (svn_client_commit_info_t *) commit_info; 612 return svn_error_trace(err); 613} 614 615svn_error_t * 616svn_client_commit(svn_client_commit_info_t **commit_info_p, 617 const apr_array_header_t *targets, 618 svn_boolean_t nonrecursive, 619 svn_client_ctx_t *ctx, 620 apr_pool_t *pool) 621{ 622 return svn_client_commit2(commit_info_p, targets, 623 ! nonrecursive, 624 TRUE, 625 ctx, pool); 626} 627 628/*** From copy.c ***/ 629svn_error_t * 630svn_client_copy6(const apr_array_header_t *sources, 631 const char *dst_path, 632 svn_boolean_t copy_as_child, 633 svn_boolean_t make_parents, 634 svn_boolean_t ignore_externals, 635 const apr_hash_t *revprop_table, 636 svn_commit_callback2_t commit_callback, 637 void *commit_baton, 638 svn_client_ctx_t *ctx, 639 apr_pool_t *pool) 640{ 641 return svn_error_trace(svn_client_copy7(sources, dst_path, copy_as_child, 642 make_parents, ignore_externals, 643 FALSE /* metadata_only */, 644 FALSE /* pin_externals */, 645 NULL /* externals_to_pin */, 646 revprop_table, 647 commit_callback, commit_baton, 648 ctx, pool)); 649} 650 651svn_error_t * 652svn_client_copy5(svn_commit_info_t **commit_info_p, 653 const apr_array_header_t *sources, 654 const char *dst_path, 655 svn_boolean_t copy_as_child, 656 svn_boolean_t make_parents, 657 svn_boolean_t ignore_externals, 658 const apr_hash_t *revprop_table, 659 svn_client_ctx_t *ctx, 660 apr_pool_t *pool) 661{ 662 struct capture_baton_t cb; 663 664 cb.info = commit_info_p; 665 cb.pool = pool; 666 667 return svn_client_copy6(sources, dst_path, copy_as_child, make_parents, 668 ignore_externals, revprop_table, 669 capture_commit_info, &cb, ctx, pool); 670} 671 672svn_error_t * 673svn_client_copy4(svn_commit_info_t **commit_info_p, 674 const apr_array_header_t *sources, 675 const char *dst_path, 676 svn_boolean_t copy_as_child, 677 svn_boolean_t make_parents, 678 const apr_hash_t *revprop_table, 679 svn_client_ctx_t *ctx, 680 apr_pool_t *pool) 681{ 682 return svn_client_copy5(commit_info_p, sources, dst_path, copy_as_child, 683 make_parents, FALSE, revprop_table, ctx, pool); 684} 685 686svn_error_t * 687svn_client_copy3(svn_commit_info_t **commit_info_p, 688 const char *src_path, 689 const svn_opt_revision_t *src_revision, 690 const char *dst_path, 691 svn_client_ctx_t *ctx, 692 apr_pool_t *pool) 693{ 694 apr_array_header_t *sources = apr_array_make(pool, 1, 695 sizeof(const svn_client_copy_source_t *)); 696 svn_client_copy_source_t copy_source; 697 698 copy_source.path = src_path; 699 copy_source.revision = src_revision; 700 copy_source.peg_revision = src_revision; 701 702 APR_ARRAY_PUSH(sources, const svn_client_copy_source_t *) = ©_source; 703 704 return svn_client_copy4(commit_info_p, sources, dst_path, FALSE, FALSE, 705 NULL, ctx, pool); 706} 707 708svn_error_t * 709svn_client_copy2(svn_commit_info_t **commit_info_p, 710 const char *src_path, 711 const svn_opt_revision_t *src_revision, 712 const char *dst_path, 713 svn_client_ctx_t *ctx, 714 apr_pool_t *pool) 715{ 716 svn_error_t *err; 717 718 err = svn_client_copy3(commit_info_p, src_path, src_revision, 719 dst_path, ctx, pool); 720 721 /* If the target exists, try to copy the source as a child of the target. 722 This will obviously fail if target is not a directory, but that's exactly 723 what we want. */ 724 if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS 725 || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS)) 726 { 727 const char *src_basename = svn_path_basename(src_path, pool); 728 729 svn_error_clear(err); 730 731 return svn_client_copy3(commit_info_p, src_path, src_revision, 732 svn_path_join(dst_path, src_basename, pool), 733 ctx, pool); 734 } 735 736 return svn_error_trace(err); 737} 738 739svn_error_t * 740svn_client_copy(svn_client_commit_info_t **commit_info_p, 741 const char *src_path, 742 const svn_opt_revision_t *src_revision, 743 const char *dst_path, 744 svn_client_ctx_t *ctx, 745 apr_pool_t *pool) 746{ 747 svn_commit_info_t *commit_info = NULL; 748 svn_error_t *err; 749 750 err = svn_client_copy2(&commit_info, src_path, src_revision, dst_path, 751 ctx, pool); 752 /* These structs have the same layout for the common fields. */ 753 *commit_info_p = (svn_client_commit_info_t *) commit_info; 754 return svn_error_trace(err); 755} 756 757svn_error_t * 758svn_client_move6(const apr_array_header_t *src_paths, 759 const char *dst_path, 760 svn_boolean_t move_as_child, 761 svn_boolean_t make_parents, 762 const apr_hash_t *revprop_table, 763 svn_commit_callback2_t commit_callback, 764 void *commit_baton, 765 svn_client_ctx_t *ctx, 766 apr_pool_t *pool) 767{ 768 return svn_error_trace(svn_client_move7(src_paths, dst_path, 769 move_as_child, make_parents, 770 TRUE /* allow_mixed_revisions */, 771 FALSE /* metadata_only */, 772 revprop_table, 773 commit_callback, commit_baton, 774 ctx, pool)); 775} 776 777svn_error_t * 778svn_client_move5(svn_commit_info_t **commit_info_p, 779 const apr_array_header_t *src_paths, 780 const char *dst_path, 781 svn_boolean_t force, 782 svn_boolean_t move_as_child, 783 svn_boolean_t make_parents, 784 const apr_hash_t *revprop_table, 785 svn_client_ctx_t *ctx, 786 apr_pool_t *pool) 787{ 788 struct capture_baton_t cb; 789 790 cb.info = commit_info_p; 791 cb.pool = pool; 792 793 return svn_client_move6(src_paths, dst_path, move_as_child, 794 make_parents, revprop_table, 795 capture_commit_info, &cb, ctx, pool); 796} 797 798svn_error_t * 799svn_client_move4(svn_commit_info_t **commit_info_p, 800 const char *src_path, 801 const char *dst_path, 802 svn_boolean_t force, 803 svn_client_ctx_t *ctx, 804 apr_pool_t *pool) 805{ 806 apr_array_header_t *src_paths = 807 apr_array_make(pool, 1, sizeof(const char *)); 808 APR_ARRAY_PUSH(src_paths, const char *) = src_path; 809 810 811 return svn_client_move5(commit_info_p, src_paths, dst_path, force, FALSE, 812 FALSE, NULL, ctx, pool); 813} 814 815svn_error_t * 816svn_client_move3(svn_commit_info_t **commit_info_p, 817 const char *src_path, 818 const char *dst_path, 819 svn_boolean_t force, 820 svn_client_ctx_t *ctx, 821 apr_pool_t *pool) 822{ 823 svn_error_t *err; 824 825 err = svn_client_move4(commit_info_p, src_path, dst_path, force, ctx, pool); 826 827 /* If the target exists, try to move the source as a child of the target. 828 This will obviously fail if target is not a directory, but that's exactly 829 what we want. */ 830 if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS 831 || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS)) 832 { 833 const char *src_basename = svn_path_basename(src_path, pool); 834 835 svn_error_clear(err); 836 837 return svn_client_move4(commit_info_p, src_path, 838 svn_path_join(dst_path, src_basename, pool), 839 force, ctx, pool); 840 } 841 842 return svn_error_trace(err); 843} 844 845svn_error_t * 846svn_client_move2(svn_client_commit_info_t **commit_info_p, 847 const char *src_path, 848 const char *dst_path, 849 svn_boolean_t force, 850 svn_client_ctx_t *ctx, 851 apr_pool_t *pool) 852{ 853 svn_commit_info_t *commit_info = NULL; 854 svn_error_t *err; 855 856 err = svn_client_move3(&commit_info, src_path, dst_path, force, ctx, pool); 857 /* These structs have the same layout for the common fields. */ 858 *commit_info_p = (svn_client_commit_info_t *) commit_info; 859 return svn_error_trace(err); 860} 861 862 863svn_error_t * 864svn_client_move(svn_client_commit_info_t **commit_info_p, 865 const char *src_path, 866 const svn_opt_revision_t *src_revision, 867 const char *dst_path, 868 svn_boolean_t force, 869 svn_client_ctx_t *ctx, 870 apr_pool_t *pool) 871{ 872 /* It doesn't make sense to specify revisions in a move. */ 873 874 /* ### todo: this check could fail wrongly. For example, 875 someone could pass in an svn_opt_revision_number that just 876 happens to be the HEAD. It's fair enough to punt then, IMHO, 877 and just demand that the user not specify a revision at all; 878 beats mucking up this function with RA calls and such. */ 879 if (src_revision->kind != svn_opt_revision_unspecified 880 && src_revision->kind != svn_opt_revision_head) 881 { 882 return svn_error_create 883 (SVN_ERR_UNSUPPORTED_FEATURE, NULL, 884 _("Cannot specify revisions (except HEAD) with move operations")); 885 } 886 887 return svn_client_move2(commit_info_p, src_path, dst_path, force, ctx, pool); 888} 889 890/*** From delete.c ***/ 891svn_error_t * 892svn_client_delete3(svn_commit_info_t **commit_info_p, 893 const apr_array_header_t *paths, 894 svn_boolean_t force, 895 svn_boolean_t keep_local, 896 const apr_hash_t *revprop_table, 897 svn_client_ctx_t *ctx, 898 apr_pool_t *pool) 899{ 900 struct capture_baton_t cb; 901 902 cb.info = commit_info_p; 903 cb.pool = pool; 904 905 return svn_client_delete4(paths, force, keep_local, revprop_table, 906 capture_commit_info, &cb, ctx, pool); 907} 908 909svn_error_t * 910svn_client_delete2(svn_commit_info_t **commit_info_p, 911 const apr_array_header_t *paths, 912 svn_boolean_t force, 913 svn_client_ctx_t *ctx, 914 apr_pool_t *pool) 915{ 916 return svn_client_delete3(commit_info_p, paths, force, FALSE, NULL, 917 ctx, pool); 918} 919 920svn_error_t * 921svn_client_delete(svn_client_commit_info_t **commit_info_p, 922 const apr_array_header_t *paths, 923 svn_boolean_t force, 924 svn_client_ctx_t *ctx, 925 apr_pool_t *pool) 926{ 927 svn_commit_info_t *commit_info = NULL; 928 svn_error_t *err = NULL; 929 930 err = svn_client_delete2(&commit_info, paths, force, ctx, pool); 931 /* These structs have the same layout for the common fields. */ 932 *commit_info_p = (svn_client_commit_info_t *) commit_info; 933 return svn_error_trace(err); 934} 935 936/*** From diff.c ***/ 937 938svn_error_t * 939svn_client_diff5(const apr_array_header_t *diff_options, 940 const char *path1, 941 const svn_opt_revision_t *revision1, 942 const char *path2, 943 const svn_opt_revision_t *revision2, 944 const char *relative_to_dir, 945 svn_depth_t depth, 946 svn_boolean_t ignore_ancestry, 947 svn_boolean_t no_diff_deleted, 948 svn_boolean_t show_copies_as_adds, 949 svn_boolean_t ignore_content_type, 950 svn_boolean_t use_git_diff_format, 951 const char *header_encoding, 952 apr_file_t *outfile, 953 apr_file_t *errfile, 954 const apr_array_header_t *changelists, 955 svn_client_ctx_t *ctx, 956 apr_pool_t *pool) 957{ 958 svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool); 959 svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool); 960 961 return svn_client_diff6(diff_options, path1, revision1, path2, 962 revision2, relative_to_dir, depth, 963 ignore_ancestry, FALSE /* no_diff_added */, 964 no_diff_deleted, show_copies_as_adds, 965 ignore_content_type, FALSE /* ignore_properties */, 966 FALSE /* properties_only */, use_git_diff_format, 967 header_encoding, 968 outstream, errstream, changelists, ctx, pool); 969} 970 971svn_error_t * 972svn_client_diff4(const apr_array_header_t *options, 973 const char *path1, 974 const svn_opt_revision_t *revision1, 975 const char *path2, 976 const svn_opt_revision_t *revision2, 977 const char *relative_to_dir, 978 svn_depth_t depth, 979 svn_boolean_t ignore_ancestry, 980 svn_boolean_t no_diff_deleted, 981 svn_boolean_t ignore_content_type, 982 const char *header_encoding, 983 apr_file_t *outfile, 984 apr_file_t *errfile, 985 const apr_array_header_t *changelists, 986 svn_client_ctx_t *ctx, 987 apr_pool_t *pool) 988{ 989 return svn_client_diff5(options, path1, revision1, path2, 990 revision2, relative_to_dir, depth, 991 ignore_ancestry, no_diff_deleted, FALSE, 992 ignore_content_type, FALSE, header_encoding, 993 outfile, errfile, changelists, ctx, pool); 994} 995 996svn_error_t * 997svn_client_diff3(const apr_array_header_t *options, 998 const char *path1, 999 const svn_opt_revision_t *revision1, 1000 const char *path2, 1001 const svn_opt_revision_t *revision2, 1002 svn_boolean_t recurse, 1003 svn_boolean_t ignore_ancestry, 1004 svn_boolean_t no_diff_deleted, 1005 svn_boolean_t ignore_content_type, 1006 const char *header_encoding, 1007 apr_file_t *outfile, 1008 apr_file_t *errfile, 1009 svn_client_ctx_t *ctx, 1010 apr_pool_t *pool) 1011{ 1012 return svn_client_diff4(options, path1, revision1, path2, 1013 revision2, NULL, 1014 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1015 ignore_ancestry, no_diff_deleted, 1016 ignore_content_type, header_encoding, 1017 outfile, errfile, NULL, ctx, pool); 1018} 1019 1020svn_error_t * 1021svn_client_diff2(const apr_array_header_t *options, 1022 const char *path1, 1023 const svn_opt_revision_t *revision1, 1024 const char *path2, 1025 const svn_opt_revision_t *revision2, 1026 svn_boolean_t recurse, 1027 svn_boolean_t ignore_ancestry, 1028 svn_boolean_t no_diff_deleted, 1029 svn_boolean_t ignore_content_type, 1030 apr_file_t *outfile, 1031 apr_file_t *errfile, 1032 svn_client_ctx_t *ctx, 1033 apr_pool_t *pool) 1034{ 1035 return svn_client_diff3(options, path1, revision1, path2, revision2, 1036 recurse, ignore_ancestry, no_diff_deleted, 1037 ignore_content_type, SVN_APR_LOCALE_CHARSET, 1038 outfile, errfile, ctx, pool); 1039} 1040 1041svn_error_t * 1042svn_client_diff(const apr_array_header_t *options, 1043 const char *path1, 1044 const svn_opt_revision_t *revision1, 1045 const char *path2, 1046 const svn_opt_revision_t *revision2, 1047 svn_boolean_t recurse, 1048 svn_boolean_t ignore_ancestry, 1049 svn_boolean_t no_diff_deleted, 1050 apr_file_t *outfile, 1051 apr_file_t *errfile, 1052 svn_client_ctx_t *ctx, 1053 apr_pool_t *pool) 1054{ 1055 return svn_client_diff2(options, path1, revision1, path2, revision2, 1056 recurse, ignore_ancestry, no_diff_deleted, FALSE, 1057 outfile, errfile, ctx, pool); 1058} 1059 1060svn_error_t * 1061svn_client_diff_peg5(const apr_array_header_t *diff_options, 1062 const char *path, 1063 const svn_opt_revision_t *peg_revision, 1064 const svn_opt_revision_t *start_revision, 1065 const svn_opt_revision_t *end_revision, 1066 const char *relative_to_dir, 1067 svn_depth_t depth, 1068 svn_boolean_t ignore_ancestry, 1069 svn_boolean_t no_diff_deleted, 1070 svn_boolean_t show_copies_as_adds, 1071 svn_boolean_t ignore_content_type, 1072 svn_boolean_t use_git_diff_format, 1073 const char *header_encoding, 1074 apr_file_t *outfile, 1075 apr_file_t *errfile, 1076 const apr_array_header_t *changelists, 1077 svn_client_ctx_t *ctx, 1078 apr_pool_t *pool) 1079{ 1080 svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool); 1081 svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool); 1082 1083 return svn_client_diff_peg6(diff_options, 1084 path, 1085 peg_revision, 1086 start_revision, 1087 end_revision, 1088 relative_to_dir, 1089 depth, 1090 ignore_ancestry, 1091 FALSE /* no_diff_added */, 1092 no_diff_deleted, 1093 show_copies_as_adds, 1094 ignore_content_type, 1095 FALSE /* ignore_properties */, 1096 FALSE /* properties_only */, 1097 use_git_diff_format, 1098 header_encoding, 1099 outstream, 1100 errstream, 1101 changelists, 1102 ctx, 1103 pool); 1104} 1105 1106svn_error_t * 1107svn_client_diff_peg4(const apr_array_header_t *options, 1108 const char *path, 1109 const svn_opt_revision_t *peg_revision, 1110 const svn_opt_revision_t *start_revision, 1111 const svn_opt_revision_t *end_revision, 1112 const char *relative_to_dir, 1113 svn_depth_t depth, 1114 svn_boolean_t ignore_ancestry, 1115 svn_boolean_t no_diff_deleted, 1116 svn_boolean_t ignore_content_type, 1117 const char *header_encoding, 1118 apr_file_t *outfile, 1119 apr_file_t *errfile, 1120 const apr_array_header_t *changelists, 1121 svn_client_ctx_t *ctx, 1122 apr_pool_t *pool) 1123{ 1124 return svn_client_diff_peg5(options, 1125 path, 1126 peg_revision, 1127 start_revision, 1128 end_revision, 1129 relative_to_dir, 1130 depth, 1131 ignore_ancestry, 1132 no_diff_deleted, 1133 FALSE, 1134 ignore_content_type, 1135 FALSE, 1136 header_encoding, 1137 outfile, 1138 errfile, 1139 changelists, 1140 ctx, 1141 pool); 1142} 1143 1144svn_error_t * 1145svn_client_diff_peg3(const apr_array_header_t *options, 1146 const char *path, 1147 const svn_opt_revision_t *peg_revision, 1148 const svn_opt_revision_t *start_revision, 1149 const svn_opt_revision_t *end_revision, 1150 svn_boolean_t recurse, 1151 svn_boolean_t ignore_ancestry, 1152 svn_boolean_t no_diff_deleted, 1153 svn_boolean_t ignore_content_type, 1154 const char *header_encoding, 1155 apr_file_t *outfile, 1156 apr_file_t *errfile, 1157 svn_client_ctx_t *ctx, 1158 apr_pool_t *pool) 1159{ 1160 return svn_client_diff_peg4(options, 1161 path, 1162 peg_revision, 1163 start_revision, 1164 end_revision, 1165 NULL, 1166 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1167 ignore_ancestry, 1168 no_diff_deleted, 1169 ignore_content_type, 1170 header_encoding, 1171 outfile, 1172 errfile, 1173 NULL, 1174 ctx, 1175 pool); 1176} 1177 1178svn_error_t * 1179svn_client_diff_peg2(const apr_array_header_t *options, 1180 const char *path, 1181 const svn_opt_revision_t *peg_revision, 1182 const svn_opt_revision_t *start_revision, 1183 const svn_opt_revision_t *end_revision, 1184 svn_boolean_t recurse, 1185 svn_boolean_t ignore_ancestry, 1186 svn_boolean_t no_diff_deleted, 1187 svn_boolean_t ignore_content_type, 1188 apr_file_t *outfile, 1189 apr_file_t *errfile, 1190 svn_client_ctx_t *ctx, 1191 apr_pool_t *pool) 1192{ 1193 return svn_client_diff_peg3(options, path, peg_revision, start_revision, 1194 end_revision, 1195 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1196 ignore_ancestry, no_diff_deleted, 1197 ignore_content_type, SVN_APR_LOCALE_CHARSET, 1198 outfile, errfile, ctx, pool); 1199} 1200 1201svn_error_t * 1202svn_client_diff_peg(const apr_array_header_t *options, 1203 const char *path, 1204 const svn_opt_revision_t *peg_revision, 1205 const svn_opt_revision_t *start_revision, 1206 const svn_opt_revision_t *end_revision, 1207 svn_boolean_t recurse, 1208 svn_boolean_t ignore_ancestry, 1209 svn_boolean_t no_diff_deleted, 1210 apr_file_t *outfile, 1211 apr_file_t *errfile, 1212 svn_client_ctx_t *ctx, 1213 apr_pool_t *pool) 1214{ 1215 return svn_client_diff_peg2(options, path, peg_revision, 1216 start_revision, end_revision, recurse, 1217 ignore_ancestry, no_diff_deleted, FALSE, 1218 outfile, errfile, ctx, pool); 1219} 1220 1221svn_error_t * 1222svn_client_diff_summarize(const char *path1, 1223 const svn_opt_revision_t *revision1, 1224 const char *path2, 1225 const svn_opt_revision_t *revision2, 1226 svn_boolean_t recurse, 1227 svn_boolean_t ignore_ancestry, 1228 svn_client_diff_summarize_func_t summarize_func, 1229 void *summarize_baton, 1230 svn_client_ctx_t *ctx, 1231 apr_pool_t *pool) 1232{ 1233 return svn_client_diff_summarize2(path1, revision1, path2, 1234 revision2, 1235 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1236 ignore_ancestry, NULL, summarize_func, 1237 summarize_baton, ctx, pool); 1238} 1239 1240svn_error_t * 1241svn_client_diff_summarize_peg(const char *path, 1242 const svn_opt_revision_t *peg_revision, 1243 const svn_opt_revision_t *start_revision, 1244 const svn_opt_revision_t *end_revision, 1245 svn_boolean_t recurse, 1246 svn_boolean_t ignore_ancestry, 1247 svn_client_diff_summarize_func_t summarize_func, 1248 void *summarize_baton, 1249 svn_client_ctx_t *ctx, 1250 apr_pool_t *pool) 1251{ 1252 return svn_client_diff_summarize_peg2(path, peg_revision, 1253 start_revision, end_revision, 1254 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1255 ignore_ancestry, NULL, 1256 summarize_func, summarize_baton, 1257 ctx, pool); 1258} 1259 1260/*** From export.c ***/ 1261svn_error_t * 1262svn_client_export4(svn_revnum_t *result_rev, 1263 const char *from_path_or_url, 1264 const char *to_path, 1265 const svn_opt_revision_t *peg_revision, 1266 const svn_opt_revision_t *revision, 1267 svn_boolean_t overwrite, 1268 svn_boolean_t ignore_externals, 1269 svn_depth_t depth, 1270 const char *native_eol, 1271 svn_client_ctx_t *ctx, 1272 apr_pool_t *pool) 1273{ 1274 return svn_client_export5(result_rev, from_path_or_url, to_path, 1275 peg_revision, revision, overwrite, ignore_externals, 1276 FALSE, depth, native_eol, ctx, pool); 1277} 1278 1279svn_error_t * 1280svn_client_export3(svn_revnum_t *result_rev, 1281 const char *from_path_or_url, 1282 const char *to_path, 1283 const svn_opt_revision_t *peg_revision, 1284 const svn_opt_revision_t *revision, 1285 svn_boolean_t overwrite, 1286 svn_boolean_t ignore_externals, 1287 svn_boolean_t recurse, 1288 const char *native_eol, 1289 svn_client_ctx_t *ctx, 1290 apr_pool_t *pool) 1291{ 1292 return svn_client_export4(result_rev, from_path_or_url, to_path, 1293 peg_revision, revision, overwrite, ignore_externals, 1294 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1295 native_eol, ctx, pool); 1296} 1297 1298svn_error_t * 1299svn_client_export2(svn_revnum_t *result_rev, 1300 const char *from_path_or_url, 1301 const char *to_path, 1302 svn_opt_revision_t *revision, 1303 svn_boolean_t force, 1304 const char *native_eol, 1305 svn_client_ctx_t *ctx, 1306 apr_pool_t *pool) 1307{ 1308 svn_opt_revision_t peg_revision; 1309 1310 peg_revision.kind = svn_opt_revision_unspecified; 1311 1312 return svn_client_export3(result_rev, from_path_or_url, to_path, 1313 &peg_revision, revision, force, FALSE, TRUE, 1314 native_eol, ctx, pool); 1315} 1316 1317 1318svn_error_t * 1319svn_client_export(svn_revnum_t *result_rev, 1320 const char *from_path_or_url, 1321 const char *to_path, 1322 svn_opt_revision_t *revision, 1323 svn_boolean_t force, 1324 svn_client_ctx_t *ctx, 1325 apr_pool_t *pool) 1326{ 1327 return svn_client_export2(result_rev, from_path_or_url, to_path, revision, 1328 force, NULL, ctx, pool); 1329} 1330 1331/*** From list.c ***/ 1332 1333/* Baton for use with wrap_list_func */ 1334struct list_func_wrapper_baton { 1335 void *list_func1_baton; 1336 svn_client_list_func_t list_func1; 1337}; 1338 1339/* This implements svn_client_list_func2_t */ 1340static svn_error_t * 1341list_func_wrapper(void *baton, 1342 const char *path, 1343 const svn_dirent_t *dirent, 1344 const svn_lock_t *lock, 1345 const char *abs_path, 1346 const char *external_parent_url, 1347 const char *external_target, 1348 apr_pool_t *scratch_pool) 1349{ 1350 struct list_func_wrapper_baton *lfwb = baton; 1351 1352 if (lfwb->list_func1) 1353 return lfwb->list_func1(lfwb->list_func1_baton, path, dirent, 1354 lock, abs_path, scratch_pool); 1355 1356 return SVN_NO_ERROR; 1357} 1358 1359/* Helper function for svn_client_list2(). It wraps old format baton 1360 and callback function in list_func_wrapper_baton and 1361 returns new baton and callback to use with svn_client_list3(). */ 1362static void 1363wrap_list_func(svn_client_list_func2_t *list_func2, 1364 void **list_func2_baton, 1365 svn_client_list_func_t list_func, 1366 void *baton, 1367 apr_pool_t *result_pool) 1368{ 1369 struct list_func_wrapper_baton *lfwb = apr_palloc(result_pool, 1370 sizeof(*lfwb)); 1371 1372 /* Set the user provided old format callback in the baton. */ 1373 lfwb->list_func1_baton = baton; 1374 lfwb->list_func1 = list_func; 1375 1376 *list_func2_baton = lfwb; 1377 *list_func2 = list_func_wrapper; 1378} 1379 1380svn_error_t * 1381svn_client_list2(const char *path_or_url, 1382 const svn_opt_revision_t *peg_revision, 1383 const svn_opt_revision_t *revision, 1384 svn_depth_t depth, 1385 apr_uint32_t dirent_fields, 1386 svn_boolean_t fetch_locks, 1387 svn_client_list_func_t list_func, 1388 void *baton, 1389 svn_client_ctx_t *ctx, 1390 apr_pool_t *pool) 1391{ 1392 svn_client_list_func2_t list_func2; 1393 void *list_func2_baton; 1394 1395 wrap_list_func(&list_func2, &list_func2_baton, list_func, baton, pool); 1396 1397 return svn_client_list3(path_or_url, peg_revision, revision, depth, 1398 dirent_fields, fetch_locks, 1399 FALSE /* include externals */, 1400 list_func2, list_func2_baton, ctx, pool); 1401} 1402 1403svn_error_t * 1404svn_client_list(const char *path_or_url, 1405 const svn_opt_revision_t *peg_revision, 1406 const svn_opt_revision_t *revision, 1407 svn_boolean_t recurse, 1408 apr_uint32_t dirent_fields, 1409 svn_boolean_t fetch_locks, 1410 svn_client_list_func_t list_func, 1411 void *baton, 1412 svn_client_ctx_t *ctx, 1413 apr_pool_t *pool) 1414{ 1415 return svn_client_list2(path_or_url, 1416 peg_revision, 1417 revision, 1418 SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse), 1419 dirent_fields, 1420 fetch_locks, 1421 list_func, 1422 baton, 1423 ctx, 1424 pool); 1425} 1426 1427/* Baton used by compatibility wrapper svn_client_ls3. */ 1428struct ls_baton { 1429 apr_hash_t *dirents; 1430 apr_hash_t *locks; 1431 apr_pool_t *pool; 1432}; 1433 1434/* This implements svn_client_list_func_t. */ 1435static svn_error_t * 1436store_dirent(void *baton, const char *path, const svn_dirent_t *dirent, 1437 const svn_lock_t *lock, const char *abs_path, apr_pool_t *pool) 1438{ 1439 struct ls_baton *lb = baton; 1440 1441 /* The dirent is allocated in a temporary pool, so duplicate it into the 1442 correct pool. Note, however, that the locks are stored in the correct 1443 pool already. */ 1444 dirent = svn_dirent_dup(dirent, lb->pool); 1445 1446 /* An empty path means we are called for the target of the operation. 1447 For compatibility, we only store the target if it is a file, and we 1448 store it under the basename of the URL. Note that this makes it 1449 impossible to differentiate between the target being a directory with a 1450 child with the same basename as the target and the target being a file, 1451 but that's how it was implemented. */ 1452 if (path[0] == '\0') 1453 { 1454 if (dirent->kind == svn_node_file) 1455 { 1456 const char *base_name = svn_path_basename(abs_path, lb->pool); 1457 svn_hash_sets(lb->dirents, base_name, dirent); 1458 if (lock) 1459 svn_hash_sets(lb->locks, base_name, lock); 1460 } 1461 } 1462 else 1463 { 1464 path = apr_pstrdup(lb->pool, path); 1465 svn_hash_sets(lb->dirents, path, dirent); 1466 if (lock) 1467 svn_hash_sets(lb->locks, path, lock); 1468 } 1469 1470 return SVN_NO_ERROR; 1471} 1472 1473svn_error_t * 1474svn_client_ls3(apr_hash_t **dirents, 1475 apr_hash_t **locks, 1476 const char *path_or_url, 1477 const svn_opt_revision_t *peg_revision, 1478 const svn_opt_revision_t *revision, 1479 svn_boolean_t recurse, 1480 svn_client_ctx_t *ctx, 1481 apr_pool_t *pool) 1482{ 1483 struct ls_baton lb; 1484 1485 *dirents = lb.dirents = apr_hash_make(pool); 1486 if (locks) 1487 *locks = lb.locks = apr_hash_make(pool); 1488 lb.pool = pool; 1489 1490 return svn_client_list(path_or_url, peg_revision, revision, recurse, 1491 SVN_DIRENT_ALL, locks != NULL, 1492 store_dirent, &lb, ctx, pool); 1493} 1494 1495svn_error_t * 1496svn_client_ls2(apr_hash_t **dirents, 1497 const char *path_or_url, 1498 const svn_opt_revision_t *peg_revision, 1499 const svn_opt_revision_t *revision, 1500 svn_boolean_t recurse, 1501 svn_client_ctx_t *ctx, 1502 apr_pool_t *pool) 1503{ 1504 1505 return svn_client_ls3(dirents, NULL, path_or_url, peg_revision, 1506 revision, recurse, ctx, pool); 1507} 1508 1509 1510svn_error_t * 1511svn_client_ls(apr_hash_t **dirents, 1512 const char *path_or_url, 1513 svn_opt_revision_t *revision, 1514 svn_boolean_t recurse, 1515 svn_client_ctx_t *ctx, 1516 apr_pool_t *pool) 1517{ 1518 return svn_client_ls2(dirents, path_or_url, revision, 1519 revision, recurse, ctx, pool); 1520} 1521 1522/*** From log.c ***/ 1523 1524svn_error_t * 1525svn_client_log4(const apr_array_header_t *targets, 1526 const svn_opt_revision_t *peg_revision, 1527 const svn_opt_revision_t *start, 1528 const svn_opt_revision_t *end, 1529 int limit, 1530 svn_boolean_t discover_changed_paths, 1531 svn_boolean_t strict_node_history, 1532 svn_boolean_t include_merged_revisions, 1533 const apr_array_header_t *revprops, 1534 svn_log_entry_receiver_t receiver, 1535 void *receiver_baton, 1536 svn_client_ctx_t *ctx, 1537 apr_pool_t *pool) 1538{ 1539 apr_array_header_t *revision_ranges; 1540 1541 revision_ranges = apr_array_make(pool, 1, 1542 sizeof(svn_opt_revision_range_t *)); 1543 APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) 1544 = svn_opt__revision_range_create(start, end, pool); 1545 1546 return svn_client_log5(targets, peg_revision, revision_ranges, limit, 1547 discover_changed_paths, strict_node_history, 1548 include_merged_revisions, revprops, receiver, 1549 receiver_baton, ctx, pool); 1550} 1551 1552 1553svn_error_t * 1554svn_client_log3(const apr_array_header_t *targets, 1555 const svn_opt_revision_t *peg_revision, 1556 const svn_opt_revision_t *start, 1557 const svn_opt_revision_t *end, 1558 int limit, 1559 svn_boolean_t discover_changed_paths, 1560 svn_boolean_t strict_node_history, 1561 svn_log_message_receiver_t receiver, 1562 void *receiver_baton, 1563 svn_client_ctx_t *ctx, 1564 apr_pool_t *pool) 1565{ 1566 svn_log_entry_receiver_t receiver2; 1567 void *receiver2_baton; 1568 1569 svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton, 1570 receiver, receiver_baton, 1571 pool); 1572 1573 return svn_client_log4(targets, peg_revision, start, end, limit, 1574 discover_changed_paths, strict_node_history, FALSE, 1575 svn_compat_log_revprops_in(pool), 1576 receiver2, receiver2_baton, ctx, pool); 1577} 1578 1579svn_error_t * 1580svn_client_log2(const apr_array_header_t *targets, 1581 const svn_opt_revision_t *start, 1582 const svn_opt_revision_t *end, 1583 int limit, 1584 svn_boolean_t discover_changed_paths, 1585 svn_boolean_t strict_node_history, 1586 svn_log_message_receiver_t receiver, 1587 void *receiver_baton, 1588 svn_client_ctx_t *ctx, 1589 apr_pool_t *pool) 1590{ 1591 svn_opt_revision_t peg_revision; 1592 peg_revision.kind = svn_opt_revision_unspecified; 1593 return svn_client_log3(targets, &peg_revision, start, end, limit, 1594 discover_changed_paths, strict_node_history, 1595 receiver, receiver_baton, ctx, pool); 1596} 1597 1598svn_error_t * 1599svn_client_log(const apr_array_header_t *targets, 1600 const svn_opt_revision_t *start, 1601 const svn_opt_revision_t *end, 1602 svn_boolean_t discover_changed_paths, 1603 svn_boolean_t strict_node_history, 1604 svn_log_message_receiver_t receiver, 1605 void *receiver_baton, 1606 svn_client_ctx_t *ctx, 1607 apr_pool_t *pool) 1608{ 1609 svn_error_t *err = SVN_NO_ERROR; 1610 1611 err = svn_client_log2(targets, start, end, 0, discover_changed_paths, 1612 strict_node_history, receiver, receiver_baton, ctx, 1613 pool); 1614 1615 /* Special case: If there have been no commits, we'll get an error 1616 * for requesting log of a revision higher than 0. But the 1617 * default behavior of "svn log" is to give revisions HEAD through 1618 * 1, on the assumption that HEAD >= 1. 1619 * 1620 * So if we got that error for that reason, and it looks like the 1621 * user was just depending on the defaults (rather than explicitly 1622 * requesting the log for revision 1), then we don't error. Instead 1623 * we just invoke the receiver manually on a hand-constructed log 1624 * message for revision 0. 1625 * 1626 * See also http://subversion.tigris.org/issues/show_bug.cgi?id=692. 1627 */ 1628 if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION) 1629 && (start->kind == svn_opt_revision_head) 1630 && ((end->kind == svn_opt_revision_number) 1631 && (end->value.number == 1))) 1632 { 1633 1634 /* We don't need to check if HEAD is 0, because that must be the case, 1635 * by logical deduction: The revision range specified is HEAD:1. 1636 * HEAD cannot not exist, so the revision to which "no such revision" 1637 * applies is 1. If revision 1 does not exist, then HEAD is 0. 1638 * Hence, we deduce the repository is empty without needing access 1639 * to further information. */ 1640 1641 svn_error_clear(err); 1642 err = SVN_NO_ERROR; 1643 1644 /* Log receivers are free to handle revision 0 specially... But 1645 just in case some don't, we make up a message here. */ 1646 SVN_ERR(receiver(receiver_baton, 1647 NULL, 0, "", "", _("No commits in repository"), 1648 pool)); 1649 } 1650 1651 return svn_error_trace(err); 1652} 1653 1654/*** From merge.c ***/ 1655 1656svn_error_t * 1657svn_client_merge4(const char *source1, 1658 const svn_opt_revision_t *revision1, 1659 const char *source2, 1660 const svn_opt_revision_t *revision2, 1661 const char *target_wcpath, 1662 svn_depth_t depth, 1663 svn_boolean_t ignore_ancestry, 1664 svn_boolean_t force_delete, 1665 svn_boolean_t record_only, 1666 svn_boolean_t dry_run, 1667 svn_boolean_t allow_mixed_rev, 1668 const apr_array_header_t *merge_options, 1669 svn_client_ctx_t *ctx, 1670 apr_pool_t *pool) 1671{ 1672 SVN_ERR(svn_client_merge5(source1, revision1, 1673 source2, revision2, 1674 target_wcpath, 1675 depth, 1676 ignore_ancestry /*ignore_mergeinfo*/, 1677 ignore_ancestry /*diff_ignore_ancestry*/, 1678 force_delete, record_only, 1679 dry_run, allow_mixed_rev, 1680 merge_options, ctx, pool)); 1681 return SVN_NO_ERROR; 1682} 1683 1684svn_error_t * 1685svn_client_merge3(const char *source1, 1686 const svn_opt_revision_t *revision1, 1687 const char *source2, 1688 const svn_opt_revision_t *revision2, 1689 const char *target_wcpath, 1690 svn_depth_t depth, 1691 svn_boolean_t ignore_ancestry, 1692 svn_boolean_t force, 1693 svn_boolean_t record_only, 1694 svn_boolean_t dry_run, 1695 const apr_array_header_t *merge_options, 1696 svn_client_ctx_t *ctx, 1697 apr_pool_t *pool) 1698{ 1699 return svn_client_merge4(source1, revision1, source2, revision2, 1700 target_wcpath, depth, ignore_ancestry, force, 1701 record_only, dry_run, TRUE, merge_options, 1702 ctx, pool); 1703} 1704 1705svn_error_t * 1706svn_client_merge2(const char *source1, 1707 const svn_opt_revision_t *revision1, 1708 const char *source2, 1709 const svn_opt_revision_t *revision2, 1710 const char *target_wcpath, 1711 svn_boolean_t recurse, 1712 svn_boolean_t ignore_ancestry, 1713 svn_boolean_t force, 1714 svn_boolean_t dry_run, 1715 const apr_array_header_t *merge_options, 1716 svn_client_ctx_t *ctx, 1717 apr_pool_t *pool) 1718{ 1719 return svn_client_merge3(source1, revision1, source2, revision2, 1720 target_wcpath, 1721 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1722 ignore_ancestry, force, FALSE, dry_run, 1723 merge_options, ctx, pool); 1724} 1725 1726svn_error_t * 1727svn_client_merge(const char *source1, 1728 const svn_opt_revision_t *revision1, 1729 const char *source2, 1730 const svn_opt_revision_t *revision2, 1731 const char *target_wcpath, 1732 svn_boolean_t recurse, 1733 svn_boolean_t ignore_ancestry, 1734 svn_boolean_t force, 1735 svn_boolean_t dry_run, 1736 svn_client_ctx_t *ctx, 1737 apr_pool_t *pool) 1738{ 1739 return svn_client_merge2(source1, revision1, source2, revision2, 1740 target_wcpath, recurse, ignore_ancestry, force, 1741 dry_run, NULL, ctx, pool); 1742} 1743 1744svn_error_t * 1745svn_client_merge_peg4(const char *source_path_or_url, 1746 const apr_array_header_t *ranges_to_merge, 1747 const svn_opt_revision_t *source_peg_revision, 1748 const char *target_wcpath, 1749 svn_depth_t depth, 1750 svn_boolean_t ignore_ancestry, 1751 svn_boolean_t force_delete, 1752 svn_boolean_t record_only, 1753 svn_boolean_t dry_run, 1754 svn_boolean_t allow_mixed_rev, 1755 const apr_array_header_t *merge_options, 1756 svn_client_ctx_t *ctx, 1757 apr_pool_t *pool) 1758{ 1759 SVN_ERR(svn_client_merge_peg5(source_path_or_url, 1760 ranges_to_merge, 1761 source_peg_revision, 1762 target_wcpath, 1763 depth, 1764 ignore_ancestry /*ignore_mergeinfo*/, 1765 ignore_ancestry /*diff_ignore_ancestry*/, 1766 force_delete, record_only, 1767 dry_run, allow_mixed_rev, 1768 merge_options, ctx, pool)); 1769 return SVN_NO_ERROR; 1770} 1771 1772svn_error_t * 1773svn_client_merge_peg3(const char *source, 1774 const apr_array_header_t *ranges_to_merge, 1775 const svn_opt_revision_t *peg_revision, 1776 const char *target_wcpath, 1777 svn_depth_t depth, 1778 svn_boolean_t ignore_ancestry, 1779 svn_boolean_t force, 1780 svn_boolean_t record_only, 1781 svn_boolean_t dry_run, 1782 const apr_array_header_t *merge_options, 1783 svn_client_ctx_t *ctx, 1784 apr_pool_t *pool) 1785{ 1786 return svn_client_merge_peg4(source, ranges_to_merge, peg_revision, 1787 target_wcpath, depth, ignore_ancestry, force, 1788 record_only, dry_run, TRUE, merge_options, 1789 ctx, pool); 1790} 1791 1792svn_error_t * 1793svn_client_merge_peg2(const char *source, 1794 const svn_opt_revision_t *revision1, 1795 const svn_opt_revision_t *revision2, 1796 const svn_opt_revision_t *peg_revision, 1797 const char *target_wcpath, 1798 svn_boolean_t recurse, 1799 svn_boolean_t ignore_ancestry, 1800 svn_boolean_t force, 1801 svn_boolean_t dry_run, 1802 const apr_array_header_t *merge_options, 1803 svn_client_ctx_t *ctx, 1804 apr_pool_t *pool) 1805{ 1806 apr_array_header_t *ranges_to_merge = 1807 apr_array_make(pool, 1, sizeof(svn_opt_revision_range_t *)); 1808 1809 APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) 1810 = svn_opt__revision_range_create(revision1, revision2, pool); 1811 return svn_client_merge_peg3(source, ranges_to_merge, 1812 peg_revision, 1813 target_wcpath, 1814 SVN_DEPTH_INFINITY_OR_FILES(recurse), 1815 ignore_ancestry, force, FALSE, dry_run, 1816 merge_options, ctx, pool); 1817} 1818 1819svn_error_t * 1820svn_client_merge_peg(const char *source, 1821 const svn_opt_revision_t *revision1, 1822 const svn_opt_revision_t *revision2, 1823 const svn_opt_revision_t *peg_revision, 1824 const char *target_wcpath, 1825 svn_boolean_t recurse, 1826 svn_boolean_t ignore_ancestry, 1827 svn_boolean_t force, 1828 svn_boolean_t dry_run, 1829 svn_client_ctx_t *ctx, 1830 apr_pool_t *pool) 1831{ 1832 return svn_client_merge_peg2(source, revision1, revision2, peg_revision, 1833 target_wcpath, recurse, ignore_ancestry, force, 1834 dry_run, NULL, ctx, pool); 1835} 1836 1837/*** From prop_commands.c ***/ 1838svn_error_t * 1839svn_client_propset3(svn_commit_info_t **commit_info_p, 1840 const char *propname, 1841 const svn_string_t *propval, 1842 const char *target, 1843 svn_depth_t depth, 1844 svn_boolean_t skip_checks, 1845 svn_revnum_t base_revision_for_url, 1846 const apr_array_header_t *changelists, 1847 const apr_hash_t *revprop_table, 1848 svn_client_ctx_t *ctx, 1849 apr_pool_t *pool) 1850{ 1851 if (svn_path_is_url(target)) 1852 { 1853 struct capture_baton_t cb; 1854 1855 cb.info = commit_info_p; 1856 cb.pool = pool; 1857 1858 SVN_ERR(svn_client_propset_remote(propname, propval, target, skip_checks, 1859 base_revision_for_url, revprop_table, 1860 capture_commit_info, &cb, ctx, pool)); 1861 } 1862 else 1863 { 1864 apr_array_header_t *targets = apr_array_make(pool, 1, 1865 sizeof(const char *)); 1866 1867 APR_ARRAY_PUSH(targets, const char *) = target; 1868 SVN_ERR(svn_client_propset_local(propname, propval, targets, depth, 1869 skip_checks, changelists, ctx, pool)); 1870 } 1871 1872 return SVN_NO_ERROR; 1873} 1874 1875svn_error_t * 1876svn_client_propset2(const char *propname, 1877 const svn_string_t *propval, 1878 const char *target, 1879 svn_boolean_t recurse, 1880 svn_boolean_t skip_checks, 1881 svn_client_ctx_t *ctx, 1882 apr_pool_t *pool) 1883{ 1884 return svn_client_propset3(NULL, propname, propval, target, 1885 SVN_DEPTH_INFINITY_OR_EMPTY(recurse), 1886 skip_checks, SVN_INVALID_REVNUM, 1887 NULL, NULL, ctx, pool); 1888} 1889 1890 1891svn_error_t * 1892svn_client_propset(const char *propname, 1893 const svn_string_t *propval, 1894 const char *target, 1895 svn_boolean_t recurse, 1896 apr_pool_t *pool) 1897{ 1898 svn_client_ctx_t *ctx; 1899 1900 SVN_ERR(svn_client_create_context(&ctx, pool)); 1901 1902 return svn_client_propset2(propname, propval, target, recurse, FALSE, 1903 ctx, pool); 1904} 1905 1906svn_error_t * 1907svn_client_revprop_set(const char *propname, 1908 const svn_string_t *propval, 1909 const char *URL, 1910 const svn_opt_revision_t *revision, 1911 svn_revnum_t *set_rev, 1912 svn_boolean_t force, 1913 svn_client_ctx_t *ctx, 1914 apr_pool_t *pool) 1915{ 1916 return svn_client_revprop_set2(propname, propval, NULL, URL, 1917 revision, set_rev, force, ctx, pool); 1918 1919} 1920 1921svn_error_t * 1922svn_client_propget4(apr_hash_t **props, 1923 const char *propname, 1924 const char *target, 1925 const svn_opt_revision_t *peg_revision, 1926 const svn_opt_revision_t *revision, 1927 svn_revnum_t *actual_revnum, 1928 svn_depth_t depth, 1929 const apr_array_header_t *changelists, 1930 svn_client_ctx_t *ctx, 1931 apr_pool_t *result_pool, 1932 apr_pool_t *scratch_pool) 1933{ 1934 return svn_error_trace(svn_client_propget5(props, NULL, propname, target, 1935 peg_revision, revision, 1936 actual_revnum, depth, 1937 changelists, ctx, 1938 result_pool, scratch_pool)); 1939} 1940 1941svn_error_t * 1942svn_client_propget3(apr_hash_t **props, 1943 const char *propname, 1944 const char *path_or_url, 1945 const svn_opt_revision_t *peg_revision, 1946 const svn_opt_revision_t *revision, 1947 svn_revnum_t *actual_revnum, 1948 svn_depth_t depth, 1949 const apr_array_header_t *changelists, 1950 svn_client_ctx_t *ctx, 1951 apr_pool_t *pool) 1952{ 1953 const char *target; 1954 apr_hash_t *temp_props; 1955 svn_error_t *err; 1956 1957 if (svn_path_is_url(path_or_url)) 1958 target = path_or_url; 1959 else 1960 SVN_ERR(svn_dirent_get_absolute(&target, path_or_url, pool)); 1961 1962 err = svn_client_propget4(&temp_props, propname, target, 1963 peg_revision, revision, actual_revnum, 1964 depth, changelists, ctx, pool, pool); 1965 1966 if (err && err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) 1967 { 1968 err->apr_err = SVN_ERR_ENTRY_NOT_FOUND; 1969 return svn_error_trace(err); 1970 } 1971 else 1972 SVN_ERR(err); 1973 1974 if (actual_revnum 1975 && !svn_path_is_url(path_or_url) 1976 && !SVN_IS_VALID_REVNUM(*actual_revnum)) 1977 { 1978 /* Get the actual_revnum; added nodes have no revision yet, and old 1979 * callers expected the mock-up revision of 0. */ 1980 svn_boolean_t added; 1981 1982 SVN_ERR(svn_wc__node_is_added(&added, ctx->wc_ctx, target, pool)); 1983 if (added) 1984 *actual_revnum = 0; 1985 } 1986 1987 /* We may need to fix up our hash keys for legacy callers. */ 1988 if (!svn_path_is_url(path_or_url) && strcmp(target, path_or_url) != 0) 1989 { 1990 apr_hash_index_t *hi; 1991 1992 *props = apr_hash_make(pool); 1993 for (hi = apr_hash_first(pool, temp_props); hi; 1994 hi = apr_hash_next(hi)) 1995 { 1996 const char *abspath = apr_hash_this_key(hi); 1997 svn_string_t *value = apr_hash_this_val(hi); 1998 const char *relpath = svn_dirent_join(path_or_url, 1999 svn_dirent_skip_ancestor(target, abspath), 2000 pool); 2001 2002 svn_hash_sets(*props, relpath, value); 2003 } 2004 } 2005 else 2006 *props = temp_props; 2007 2008 return SVN_NO_ERROR; 2009} 2010 2011svn_error_t * 2012svn_client_propget2(apr_hash_t **props, 2013 const char *propname, 2014 const char *target, 2015 const svn_opt_revision_t *peg_revision, 2016 const svn_opt_revision_t *revision, 2017 svn_boolean_t recurse, 2018 svn_client_ctx_t *ctx, 2019 apr_pool_t *pool) 2020{ 2021 return svn_client_propget3(props, 2022 propname, 2023 target, 2024 peg_revision, 2025 revision, 2026 NULL, 2027 SVN_DEPTH_INFINITY_OR_EMPTY(recurse), 2028 NULL, 2029 ctx, 2030 pool); 2031} 2032 2033svn_error_t * 2034svn_client_propget(apr_hash_t **props, 2035 const char *propname, 2036 const char *target, 2037 const svn_opt_revision_t *revision, 2038 svn_boolean_t recurse, 2039 svn_client_ctx_t *ctx, 2040 apr_pool_t *pool) 2041{ 2042 return svn_client_propget2(props, propname, target, revision, revision, 2043 recurse, ctx, pool); 2044} 2045 2046 2047/* Duplicate a HASH containing (char * -> svn_string_t *) key/value 2048 pairs using POOL. */ 2049static apr_hash_t * 2050string_hash_dup(apr_hash_t *hash, apr_pool_t *pool) 2051{ 2052 apr_hash_index_t *hi; 2053 apr_hash_t *new_hash = apr_hash_make(pool); 2054 2055 for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi)) 2056 { 2057 const char *key = apr_pstrdup(pool, apr_hash_this_key(hi)); 2058 apr_ssize_t klen = apr_hash_this_key_len(hi); 2059 svn_string_t *val = svn_string_dup(apr_hash_this_val(hi), pool); 2060 2061 apr_hash_set(new_hash, key, klen, val); 2062 } 2063 return new_hash; 2064} 2065 2066svn_client_proplist_item_t * 2067svn_client_proplist_item_dup(const svn_client_proplist_item_t *item, 2068 apr_pool_t * pool) 2069{ 2070 svn_client_proplist_item_t *new_item = apr_pcalloc(pool, sizeof(*new_item)); 2071 2072 if (item->node_name) 2073 new_item->node_name = svn_stringbuf_dup(item->node_name, pool); 2074 2075 if (item->prop_hash) 2076 new_item->prop_hash = string_hash_dup(item->prop_hash, pool); 2077 2078 return new_item; 2079} 2080 2081/* Baton for use with wrap_proplist_receiver */ 2082struct proplist_receiver_wrapper_baton { 2083 void *baton; 2084 svn_proplist_receiver_t receiver; 2085}; 2086 2087/* This implements svn_client_proplist_receiver2_t */ 2088static svn_error_t * 2089proplist_wrapper_receiver(void *baton, 2090 const char *path, 2091 apr_hash_t *prop_hash, 2092 apr_array_header_t *inherited_props, 2093 apr_pool_t *pool) 2094{ 2095 struct proplist_receiver_wrapper_baton *plrwb = baton; 2096 2097 if (plrwb->receiver) 2098 return plrwb->receiver(plrwb->baton, path, prop_hash, pool); 2099 2100 return SVN_NO_ERROR; 2101} 2102 2103static void 2104wrap_proplist_receiver(svn_proplist_receiver2_t *receiver2, 2105 void **receiver2_baton, 2106 svn_proplist_receiver_t receiver, 2107 void *receiver_baton, 2108 apr_pool_t *pool) 2109{ 2110 struct proplist_receiver_wrapper_baton *plrwb = apr_palloc(pool, 2111 sizeof(*plrwb)); 2112 2113 /* Set the user provided old format callback in the baton. */ 2114 plrwb->baton = receiver_baton; 2115 plrwb->receiver = receiver; 2116 2117 *receiver2_baton = plrwb; 2118 *receiver2 = proplist_wrapper_receiver; 2119} 2120 2121svn_error_t * 2122svn_client_proplist3(const char *target, 2123 const svn_opt_revision_t *peg_revision, 2124 const svn_opt_revision_t *revision, 2125 svn_depth_t depth, 2126 const apr_array_header_t *changelists, 2127 svn_proplist_receiver_t receiver, 2128 void *receiver_baton, 2129 svn_client_ctx_t *ctx, 2130 apr_pool_t *pool) 2131{ 2132 2133 svn_proplist_receiver2_t receiver2; 2134 void *receiver2_baton; 2135 2136 wrap_proplist_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton, 2137 pool); 2138 2139 return svn_error_trace(svn_client_proplist4(target, peg_revision, revision, 2140 depth, changelists, FALSE, 2141 receiver2, receiver2_baton, 2142 ctx, pool)); 2143} 2144 2145/* Receiver baton used by proplist2() */ 2146struct proplist_receiver_baton { 2147 apr_array_header_t *props; 2148 apr_pool_t *pool; 2149}; 2150 2151/* Receiver function used by proplist2(). */ 2152static svn_error_t * 2153proplist_receiver_cb(void *baton, 2154 const char *path, 2155 apr_hash_t *prop_hash, 2156 apr_pool_t *pool) 2157{ 2158 struct proplist_receiver_baton *pl_baton = 2159 (struct proplist_receiver_baton *) baton; 2160 svn_client_proplist_item_t *tmp_item = apr_palloc(pool, sizeof(*tmp_item)); 2161 svn_client_proplist_item_t *item; 2162 2163 /* Because the pool passed to the receiver function is likely to be a 2164 temporary pool of some kind, we need to make copies of *path and 2165 *prop_hash in the pool provided by the baton. */ 2166 tmp_item->node_name = svn_stringbuf_create(path, pl_baton->pool); 2167 tmp_item->prop_hash = prop_hash; 2168 2169 item = svn_client_proplist_item_dup(tmp_item, pl_baton->pool); 2170 2171 APR_ARRAY_PUSH(pl_baton->props, const svn_client_proplist_item_t *) = item; 2172 2173 return SVN_NO_ERROR; 2174} 2175 2176svn_error_t * 2177svn_client_proplist2(apr_array_header_t **props, 2178 const char *target, 2179 const svn_opt_revision_t *peg_revision, 2180 const svn_opt_revision_t *revision, 2181 svn_boolean_t recurse, 2182 svn_client_ctx_t *ctx, 2183 apr_pool_t *pool) 2184{ 2185 struct proplist_receiver_baton pl_baton; 2186 2187 *props = apr_array_make(pool, 5, sizeof(svn_client_proplist_item_t *)); 2188 pl_baton.props = *props; 2189 pl_baton.pool = pool; 2190 2191 return svn_client_proplist3(target, peg_revision, revision, 2192 SVN_DEPTH_INFINITY_OR_EMPTY(recurse), NULL, 2193 proplist_receiver_cb, &pl_baton, ctx, pool); 2194} 2195 2196 2197svn_error_t * 2198svn_client_proplist(apr_array_header_t **props, 2199 const char *target, 2200 const svn_opt_revision_t *revision, 2201 svn_boolean_t recurse, 2202 svn_client_ctx_t *ctx, 2203 apr_pool_t *pool) 2204{ 2205 return svn_client_proplist2(props, target, revision, revision, 2206 recurse, ctx, pool); 2207} 2208 2209/*** From status.c ***/ 2210 2211svn_error_t * 2212svn_client_status5(svn_revnum_t *result_rev, 2213 svn_client_ctx_t *ctx, 2214 const char *path, 2215 const svn_opt_revision_t *revision, 2216 svn_depth_t depth, 2217 svn_boolean_t get_all, 2218 svn_boolean_t update, 2219 svn_boolean_t no_ignore, 2220 svn_boolean_t ignore_externals, 2221 svn_boolean_t depth_as_sticky, 2222 const apr_array_header_t *changelists, 2223 svn_client_status_func_t status_func, 2224 void *status_baton, 2225 apr_pool_t *scratch_pool) 2226{ 2227 return svn_client_status6(result_rev, ctx, path, revision, depth, 2228 get_all, update, TRUE, no_ignore, 2229 ignore_externals, depth_as_sticky, changelists, 2230 status_func, status_baton, scratch_pool); 2231} 2232 2233struct status4_wrapper_baton 2234{ 2235 svn_wc_context_t *wc_ctx; 2236 svn_wc_status_func3_t old_func; 2237 void *old_baton; 2238}; 2239 2240/* Implements svn_client_status_func_t */ 2241static svn_error_t * 2242status4_wrapper_func(void *baton, 2243 const char *path, 2244 const svn_client_status_t *status, 2245 apr_pool_t *scratch_pool) 2246{ 2247 struct status4_wrapper_baton *swb = baton; 2248 svn_wc_status2_t *dup; 2249 const char *local_abspath; 2250 const svn_wc_status3_t *wc_status = status->backwards_compatibility_baton; 2251 2252 SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool)); 2253 SVN_ERR(svn_wc__status2_from_3(&dup, wc_status, swb->wc_ctx, 2254 local_abspath, scratch_pool, 2255 scratch_pool)); 2256 2257 return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool); 2258} 2259 2260svn_error_t * 2261svn_client_status4(svn_revnum_t *result_rev, 2262 const char *path, 2263 const svn_opt_revision_t *revision, 2264 svn_wc_status_func3_t status_func, 2265 void *status_baton, 2266 svn_depth_t depth, 2267 svn_boolean_t get_all, 2268 svn_boolean_t update, 2269 svn_boolean_t no_ignore, 2270 svn_boolean_t ignore_externals, 2271 const apr_array_header_t *changelists, 2272 svn_client_ctx_t *ctx, 2273 apr_pool_t *pool) 2274{ 2275 struct status4_wrapper_baton swb; 2276 2277 swb.wc_ctx = ctx->wc_ctx; 2278 swb.old_func = status_func; 2279 swb.old_baton = status_baton; 2280 2281 return svn_client_status5(result_rev, ctx, path, revision, depth, get_all, 2282 update, no_ignore, ignore_externals, TRUE, 2283 changelists, status4_wrapper_func, &swb, pool); 2284} 2285 2286struct status3_wrapper_baton 2287{ 2288 svn_wc_status_func2_t old_func; 2289 void *old_baton; 2290}; 2291 2292static svn_error_t * 2293status3_wrapper_func(void *baton, 2294 const char *path, 2295 svn_wc_status2_t *status, 2296 apr_pool_t *pool) 2297{ 2298 struct status3_wrapper_baton *swb = baton; 2299 2300 swb->old_func(swb->old_baton, path, status); 2301 return SVN_NO_ERROR; 2302} 2303 2304svn_error_t * 2305svn_client_status3(svn_revnum_t *result_rev, 2306 const char *path, 2307 const svn_opt_revision_t *revision, 2308 svn_wc_status_func2_t status_func, 2309 void *status_baton, 2310 svn_depth_t depth, 2311 svn_boolean_t get_all, 2312 svn_boolean_t update, 2313 svn_boolean_t no_ignore, 2314 svn_boolean_t ignore_externals, 2315 const apr_array_header_t *changelists, 2316 svn_client_ctx_t *ctx, 2317 apr_pool_t *pool) 2318{ 2319 struct status3_wrapper_baton swb = { 0 }; 2320 swb.old_func = status_func; 2321 swb.old_baton = status_baton; 2322 return svn_client_status4(result_rev, path, revision, status3_wrapper_func, 2323 &swb, depth, get_all, update, no_ignore, 2324 ignore_externals, changelists, ctx, pool); 2325} 2326 2327svn_error_t * 2328svn_client_status2(svn_revnum_t *result_rev, 2329 const char *path, 2330 const svn_opt_revision_t *revision, 2331 svn_wc_status_func2_t status_func, 2332 void *status_baton, 2333 svn_boolean_t recurse, 2334 svn_boolean_t get_all, 2335 svn_boolean_t update, 2336 svn_boolean_t no_ignore, 2337 svn_boolean_t ignore_externals, 2338 svn_client_ctx_t *ctx, 2339 apr_pool_t *pool) 2340{ 2341 return svn_client_status3(result_rev, path, revision, 2342 status_func, status_baton, 2343 SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse), 2344 get_all, update, no_ignore, ignore_externals, NULL, 2345 ctx, pool); 2346} 2347 2348 2349/* Baton for old_status_func_cb; does what you think it does. */ 2350struct old_status_func_cb_baton 2351{ 2352 svn_wc_status_func_t original_func; 2353 void *original_baton; 2354}; 2355 2356/* Help svn_client_status() accept an old-style status func and baton, 2357 by wrapping them before passing along to svn_client_status2(). 2358 2359 This implements the 'svn_wc_status_func2_t' function type. */ 2360static void old_status_func_cb(void *baton, 2361 const char *path, 2362 svn_wc_status2_t *status) 2363{ 2364 struct old_status_func_cb_baton *b = baton; 2365 svn_wc_status_t *stat = (svn_wc_status_t *) status; 2366 2367 b->original_func(b->original_baton, path, stat); 2368} 2369 2370 2371svn_error_t * 2372svn_client_status(svn_revnum_t *result_rev, 2373 const char *path, 2374 svn_opt_revision_t *revision, 2375 svn_wc_status_func_t status_func, 2376 void *status_baton, 2377 svn_boolean_t recurse, 2378 svn_boolean_t get_all, 2379 svn_boolean_t update, 2380 svn_boolean_t no_ignore, 2381 svn_client_ctx_t *ctx, 2382 apr_pool_t *pool) 2383{ 2384 struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b)); 2385 b->original_func = status_func; 2386 b->original_baton = status_baton; 2387 2388 return svn_client_status2(result_rev, path, revision, 2389 old_status_func_cb, b, 2390 recurse, get_all, update, no_ignore, FALSE, 2391 ctx, pool); 2392} 2393 2394/*** From update.c ***/ 2395svn_error_t * 2396svn_client_update3(apr_array_header_t **result_revs, 2397 const apr_array_header_t *paths, 2398 const svn_opt_revision_t *revision, 2399 svn_depth_t depth, 2400 svn_boolean_t depth_is_sticky, 2401 svn_boolean_t ignore_externals, 2402 svn_boolean_t allow_unver_obstructions, 2403 svn_client_ctx_t *ctx, 2404 apr_pool_t *pool) 2405{ 2406 return svn_client_update4(result_revs, paths, revision, 2407 depth, depth_is_sticky, ignore_externals, 2408 allow_unver_obstructions, TRUE, FALSE, 2409 ctx, pool); 2410} 2411 2412svn_error_t * 2413svn_client_update2(apr_array_header_t **result_revs, 2414 const apr_array_header_t *paths, 2415 const svn_opt_revision_t *revision, 2416 svn_boolean_t recurse, 2417 svn_boolean_t ignore_externals, 2418 svn_client_ctx_t *ctx, 2419 apr_pool_t *pool) 2420{ 2421 return svn_client_update3(result_revs, paths, revision, 2422 SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE, 2423 ignore_externals, FALSE, ctx, pool); 2424} 2425 2426svn_error_t * 2427svn_client_update(svn_revnum_t *result_rev, 2428 const char *path, 2429 const svn_opt_revision_t *revision, 2430 svn_boolean_t recurse, 2431 svn_client_ctx_t *ctx, 2432 apr_pool_t *pool) 2433{ 2434 apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *)); 2435 apr_array_header_t *result_revs; 2436 2437 APR_ARRAY_PUSH(paths, const char *) = path; 2438 2439 SVN_ERR(svn_client_update2(&result_revs, paths, revision, recurse, FALSE, 2440 ctx, pool)); 2441 2442 *result_rev = APR_ARRAY_IDX(result_revs, 0, svn_revnum_t); 2443 2444 return SVN_NO_ERROR; 2445} 2446 2447/*** From switch.c ***/ 2448svn_error_t * 2449svn_client_switch2(svn_revnum_t *result_rev, 2450 const char *path, 2451 const char *switch_url, 2452 const svn_opt_revision_t *peg_revision, 2453 const svn_opt_revision_t *revision, 2454 svn_depth_t depth, 2455 svn_boolean_t depth_is_sticky, 2456 svn_boolean_t ignore_externals, 2457 svn_boolean_t allow_unver_obstructions, 2458 svn_client_ctx_t *ctx, 2459 apr_pool_t *pool) 2460{ 2461 return svn_client_switch3(result_rev, path, switch_url, peg_revision, 2462 revision, depth, depth_is_sticky, ignore_externals, 2463 allow_unver_obstructions, 2464 TRUE /* ignore_ancestry */, 2465 ctx, pool); 2466} 2467 2468svn_error_t * 2469svn_client_switch(svn_revnum_t *result_rev, 2470 const char *path, 2471 const char *switch_url, 2472 const svn_opt_revision_t *revision, 2473 svn_boolean_t recurse, 2474 svn_client_ctx_t *ctx, 2475 apr_pool_t *pool) 2476{ 2477 svn_opt_revision_t peg_revision; 2478 peg_revision.kind = svn_opt_revision_unspecified; 2479 return svn_client_switch2(result_rev, path, switch_url, 2480 &peg_revision, revision, 2481 SVN_DEPTH_INFINITY_OR_FILES(recurse), 2482 FALSE, FALSE, FALSE, ctx, pool); 2483} 2484 2485/*** From cat.c ***/ 2486svn_error_t * 2487svn_client_cat2(svn_stream_t *out, 2488 const char *path_or_url, 2489 const svn_opt_revision_t *peg_revision, 2490 const svn_opt_revision_t *revision, 2491 svn_client_ctx_t *ctx, 2492 apr_pool_t *pool) 2493{ 2494 return svn_client_cat3(NULL /* props */, 2495 out, path_or_url, peg_revision, revision, 2496 TRUE /* expand_keywords */, 2497 ctx, pool, pool); 2498} 2499 2500 2501svn_error_t * 2502svn_client_cat(svn_stream_t *out, 2503 const char *path_or_url, 2504 const svn_opt_revision_t *revision, 2505 svn_client_ctx_t *ctx, 2506 apr_pool_t *pool) 2507{ 2508 return svn_client_cat2(out, path_or_url, revision, revision, 2509 ctx, pool); 2510} 2511 2512/*** From checkout.c ***/ 2513svn_error_t * 2514svn_client_checkout2(svn_revnum_t *result_rev, 2515 const char *URL, 2516 const char *path, 2517 const svn_opt_revision_t *peg_revision, 2518 const svn_opt_revision_t *revision, 2519 svn_boolean_t recurse, 2520 svn_boolean_t ignore_externals, 2521 svn_client_ctx_t *ctx, 2522 apr_pool_t *pool) 2523{ 2524 return svn_error_trace(svn_client_checkout3(result_rev, URL, path, 2525 peg_revision, revision, 2526 SVN_DEPTH_INFINITY_OR_FILES(recurse), 2527 ignore_externals, FALSE, ctx, pool)); 2528} 2529 2530svn_error_t * 2531svn_client_checkout(svn_revnum_t *result_rev, 2532 const char *URL, 2533 const char *path, 2534 const svn_opt_revision_t *revision, 2535 svn_boolean_t recurse, 2536 svn_client_ctx_t *ctx, 2537 apr_pool_t *pool) 2538{ 2539 svn_opt_revision_t peg_revision; 2540 2541 peg_revision.kind = svn_opt_revision_unspecified; 2542 2543 return svn_error_trace(svn_client_checkout2(result_rev, URL, path, 2544 &peg_revision, revision, recurse, 2545 FALSE, ctx, pool)); 2546} 2547 2548/*** From info.c ***/ 2549 2550svn_error_t * 2551svn_client_info3(const char *abspath_or_url, 2552 const svn_opt_revision_t *peg_revision, 2553 const svn_opt_revision_t *revision, 2554 svn_depth_t depth, 2555 svn_boolean_t fetch_excluded, 2556 svn_boolean_t fetch_actual_only, 2557 const apr_array_header_t *changelists, 2558 svn_client_info_receiver2_t receiver, 2559 void *receiver_baton, 2560 svn_client_ctx_t *ctx, 2561 apr_pool_t *pool) 2562{ 2563 return svn_error_trace( 2564 svn_client_info4(abspath_or_url, 2565 peg_revision, 2566 revision, 2567 depth, 2568 fetch_excluded, 2569 fetch_actual_only, 2570 FALSE /* include_externals */, 2571 changelists, 2572 receiver, receiver_baton, 2573 ctx, pool)); 2574} 2575 2576svn_info_t * 2577svn_info_dup(const svn_info_t *info, apr_pool_t *pool) 2578{ 2579 svn_info_t *dupinfo = apr_palloc(pool, sizeof(*dupinfo)); 2580 2581 /* Perform a trivial copy ... */ 2582 *dupinfo = *info; 2583 2584 /* ...and then re-copy stuff that needs to be duped into our pool. */ 2585 if (info->URL) 2586 dupinfo->URL = apr_pstrdup(pool, info->URL); 2587 if (info->repos_root_URL) 2588 dupinfo->repos_root_URL = apr_pstrdup(pool, info->repos_root_URL); 2589 if (info->repos_UUID) 2590 dupinfo->repos_UUID = apr_pstrdup(pool, info->repos_UUID); 2591 if (info->last_changed_author) 2592 dupinfo->last_changed_author = apr_pstrdup(pool, 2593 info->last_changed_author); 2594 if (info->lock) 2595 dupinfo->lock = svn_lock_dup(info->lock, pool); 2596 if (info->copyfrom_url) 2597 dupinfo->copyfrom_url = apr_pstrdup(pool, info->copyfrom_url); 2598 if (info->checksum) 2599 dupinfo->checksum = apr_pstrdup(pool, info->checksum); 2600 if (info->conflict_old) 2601 dupinfo->conflict_old = apr_pstrdup(pool, info->conflict_old); 2602 if (info->conflict_new) 2603 dupinfo->conflict_new = apr_pstrdup(pool, info->conflict_new); 2604 if (info->conflict_wrk) 2605 dupinfo->conflict_wrk = apr_pstrdup(pool, info->conflict_wrk); 2606 if (info->prejfile) 2607 dupinfo->prejfile = apr_pstrdup(pool, info->prejfile); 2608 2609 return dupinfo; 2610} 2611 2612/* Convert an svn_client_info2_t to an svn_info_t, doing shallow copies. */ 2613static svn_error_t * 2614info_from_info2(svn_info_t **new_info, 2615 svn_wc_context_t *wc_ctx, 2616 const svn_client_info2_t *info2, 2617 apr_pool_t *pool) 2618{ 2619 svn_info_t *info = apr_pcalloc(pool, sizeof(*info)); 2620 2621 info->URL = info2->URL; 2622 /* Goofy backward compat handling for added nodes. */ 2623 if (SVN_IS_VALID_REVNUM(info2->rev)) 2624 info->rev = info2->rev; 2625 else 2626 info->rev = 0; 2627 2628 info->kind = info2->kind; 2629 info->repos_root_URL = info2->repos_root_URL; 2630 info->repos_UUID = info2->repos_UUID; 2631 info->last_changed_rev = info2->last_changed_rev; 2632 info->last_changed_date = info2->last_changed_date; 2633 info->last_changed_author = info2->last_changed_author; 2634 2635 /* Stupid old structure has a non-const LOCK member. Sigh. */ 2636 info->lock = (svn_lock_t *)info2->lock; 2637 2638 info->size64 = info2->size; 2639 if (info2->size == SVN_INVALID_FILESIZE) 2640 info->size = SVN_INFO_SIZE_UNKNOWN; 2641 else if (((svn_filesize_t)(apr_size_t)info->size64) == info->size64) 2642 info->size = (apr_size_t)info->size64; 2643 else /* >= 4GB */ 2644 info->size = SVN_INFO_SIZE_UNKNOWN; 2645 2646 if (info2->wc_info) 2647 { 2648 info->has_wc_info = TRUE; 2649 info->schedule = info2->wc_info->schedule; 2650 info->copyfrom_url = info2->wc_info->copyfrom_url; 2651 info->copyfrom_rev = info2->wc_info->copyfrom_rev; 2652 info->text_time = info2->wc_info->recorded_time; 2653 info->prop_time = 0; 2654 if (info2->wc_info->checksum 2655 && info2->wc_info->checksum->kind == svn_checksum_md5) 2656 info->checksum = svn_checksum_to_cstring( 2657 info2->wc_info->checksum, pool); 2658 else 2659 info->checksum = NULL; 2660 info->changelist = info2->wc_info->changelist; 2661 info->depth = info2->wc_info->depth; 2662 2663 if (info->depth == svn_depth_unknown && info->kind == svn_node_file) 2664 info->depth = svn_depth_infinity; 2665 2666 info->working_size64 = info2->wc_info->recorded_size; 2667 if (((svn_filesize_t)(apr_size_t)info->working_size64) == info->working_size64) 2668 info->working_size = (apr_size_t)info->working_size64; 2669 else /* >= 4GB */ 2670 info->working_size = SVN_INFO_SIZE_UNKNOWN; 2671 } 2672 else 2673 { 2674 info->has_wc_info = FALSE; 2675 info->working_size = SVN_INFO_SIZE_UNKNOWN; 2676 info->working_size64 = SVN_INVALID_FILESIZE; 2677 info->depth = svn_depth_unknown; 2678 } 2679 2680 /* Populate conflict fields. */ 2681 if (info2->wc_info && info2->wc_info->conflicts) 2682 { 2683 int i; 2684 2685 for (i = 0; i < info2->wc_info->conflicts->nelts; i++) 2686 { 2687 const svn_wc_conflict_description2_t *conflict 2688 = APR_ARRAY_IDX(info2->wc_info->conflicts, i, 2689 const svn_wc_conflict_description2_t *); 2690 2691 /* ### Not really sure what we should do if we get multiple 2692 ### conflicts of the same type. */ 2693 switch (conflict->kind) 2694 { 2695 case svn_wc_conflict_kind_tree: 2696 info->tree_conflict = svn_wc__cd2_to_cd(conflict, pool); 2697 break; 2698 2699 case svn_wc_conflict_kind_text: 2700 info->conflict_old = conflict->base_abspath; 2701 info->conflict_new = conflict->my_abspath; 2702 info->conflict_wrk = conflict->their_abspath; 2703 break; 2704 2705 case svn_wc_conflict_kind_property: 2706 info->prejfile = conflict->their_abspath; 2707 break; 2708 } 2709 } 2710 } 2711 2712 if (info2->wc_info && info2->wc_info->checksum) 2713 { 2714 const svn_checksum_t *md5_checksum; 2715 2716 SVN_ERR(svn_wc__node_get_md5_from_sha1(&md5_checksum, 2717 wc_ctx, 2718 info2->wc_info->wcroot_abspath, 2719 info2->wc_info->checksum, 2720 pool, pool)); 2721 2722 info->checksum = svn_checksum_to_cstring(md5_checksum, pool); 2723 } 2724 2725 *new_info = info; 2726 return SVN_NO_ERROR; 2727} 2728 2729struct info_to_relpath_baton 2730{ 2731 const char *anchor_abspath; 2732 const char *anchor_relpath; 2733 svn_info_receiver_t info_receiver; 2734 void *info_baton; 2735 svn_wc_context_t *wc_ctx; 2736}; 2737 2738static svn_error_t * 2739info_receiver_relpath_wrapper(void *baton, 2740 const char *abspath_or_url, 2741 const svn_client_info2_t *info2, 2742 apr_pool_t *scratch_pool) 2743{ 2744 struct info_to_relpath_baton *rb = baton; 2745 const char *path = abspath_or_url; 2746 svn_info_t *info; 2747 2748 if (rb->anchor_relpath && 2749 svn_dirent_is_ancestor(rb->anchor_abspath, abspath_or_url)) 2750 { 2751 path = svn_dirent_join(rb->anchor_relpath, 2752 svn_dirent_skip_ancestor(rb->anchor_abspath, 2753 abspath_or_url), 2754 scratch_pool); 2755 } 2756 2757 SVN_ERR(info_from_info2(&info, rb->wc_ctx, info2, scratch_pool)); 2758 2759 SVN_ERR(rb->info_receiver(rb->info_baton, 2760 path, 2761 info, 2762 scratch_pool)); 2763 2764 return SVN_NO_ERROR; 2765} 2766 2767svn_error_t * 2768svn_client_info2(const char *path_or_url, 2769 const svn_opt_revision_t *peg_revision, 2770 const svn_opt_revision_t *revision, 2771 svn_info_receiver_t receiver, 2772 void *receiver_baton, 2773 svn_depth_t depth, 2774 const apr_array_header_t *changelists, 2775 svn_client_ctx_t *ctx, 2776 apr_pool_t *pool) 2777{ 2778 struct info_to_relpath_baton rb; 2779 const char *abspath_or_url = path_or_url; 2780 2781 rb.anchor_relpath = NULL; 2782 rb.info_receiver = receiver; 2783 rb.info_baton = receiver_baton; 2784 rb.wc_ctx = ctx->wc_ctx; 2785 2786 if (!svn_path_is_url(path_or_url)) 2787 { 2788 SVN_ERR(svn_dirent_get_absolute(&abspath_or_url, path_or_url, pool)); 2789 rb.anchor_abspath = abspath_or_url; 2790 rb.anchor_relpath = path_or_url; 2791 } 2792 2793 SVN_ERR(svn_client_info3(abspath_or_url, 2794 peg_revision, 2795 revision, 2796 depth, 2797 FALSE, TRUE, 2798 changelists, 2799 info_receiver_relpath_wrapper, 2800 &rb, 2801 ctx, 2802 pool)); 2803 2804 return SVN_NO_ERROR; 2805} 2806 2807svn_error_t * 2808svn_client_info(const char *path_or_url, 2809 const svn_opt_revision_t *peg_revision, 2810 const svn_opt_revision_t *revision, 2811 svn_info_receiver_t receiver, 2812 void *receiver_baton, 2813 svn_boolean_t recurse, 2814 svn_client_ctx_t *ctx, 2815 apr_pool_t *pool) 2816{ 2817 return svn_client_info2(path_or_url, peg_revision, revision, 2818 receiver, receiver_baton, 2819 SVN_DEPTH_INFINITY_OR_EMPTY(recurse), 2820 NULL, ctx, pool); 2821} 2822 2823/*** From resolved.c ***/ 2824svn_error_t * 2825svn_client_resolved(const char *path, 2826 svn_boolean_t recursive, 2827 svn_client_ctx_t *ctx, 2828 apr_pool_t *pool) 2829{ 2830 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recursive); 2831 return svn_client_resolve(path, depth, 2832 svn_wc_conflict_choose_merged, ctx, pool); 2833} 2834/*** From revert.c ***/ 2835svn_error_t * 2836svn_client_revert2(const apr_array_header_t *paths, 2837 svn_depth_t depth, 2838 const apr_array_header_t *changelists, 2839 svn_client_ctx_t *ctx, 2840 apr_pool_t *pool) 2841{ 2842 return svn_error_trace(svn_client_revert3(paths, 2843 depth, 2844 changelists, 2845 FALSE /* clear_changelists */, 2846 FALSE /* metadata_only */, 2847 ctx, 2848 pool)); 2849} 2850 2851svn_error_t * 2852svn_client_revert(const apr_array_header_t *paths, 2853 svn_boolean_t recursive, 2854 svn_client_ctx_t *ctx, 2855 apr_pool_t *pool) 2856{ 2857 return svn_client_revert2(paths, SVN_DEPTH_INFINITY_OR_EMPTY(recursive), 2858 NULL, ctx, pool); 2859} 2860 2861/*** From ra.c ***/ 2862svn_error_t * 2863svn_client_open_ra_session(svn_ra_session_t **session, 2864 const char *url, 2865 svn_client_ctx_t *ctx, 2866 apr_pool_t *pool) 2867{ 2868 return svn_error_trace( 2869 svn_client_open_ra_session2(session, url, 2870 NULL, ctx, 2871 pool, pool)); 2872} 2873 2874svn_error_t * 2875svn_client_uuid_from_url(const char **uuid, 2876 const char *url, 2877 svn_client_ctx_t *ctx, 2878 apr_pool_t *pool) 2879{ 2880 svn_error_t *err; 2881 apr_pool_t *subpool = svn_pool_create(pool); 2882 2883 err = svn_client_get_repos_root(NULL, uuid, url, 2884 ctx, pool, subpool); 2885 /* destroy the RA session */ 2886 svn_pool_destroy(subpool); 2887 2888 return svn_error_trace(err); 2889} 2890 2891svn_error_t * 2892svn_client_uuid_from_path2(const char **uuid, 2893 const char *local_abspath, 2894 svn_client_ctx_t *ctx, 2895 apr_pool_t *result_pool, 2896 apr_pool_t *scratch_pool) 2897{ 2898 return svn_error_trace( 2899 svn_client_get_repos_root(NULL, uuid, 2900 local_abspath, ctx, 2901 result_pool, scratch_pool)); 2902} 2903 2904svn_error_t * 2905svn_client_uuid_from_path(const char **uuid, 2906 const char *path, 2907 svn_wc_adm_access_t *adm_access, 2908 svn_client_ctx_t *ctx, 2909 apr_pool_t *pool) 2910{ 2911 const char *local_abspath; 2912 2913 SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); 2914 return svn_error_trace( 2915 svn_client_uuid_from_path2(uuid, local_abspath, ctx, pool, pool)); 2916} 2917 2918/*** From url.c ***/ 2919svn_error_t * 2920svn_client_root_url_from_path(const char **url, 2921 const char *path_or_url, 2922 svn_client_ctx_t *ctx, 2923 apr_pool_t *pool) 2924{ 2925 apr_pool_t *subpool = svn_pool_create(pool); 2926 svn_error_t *err; 2927 if (!svn_path_is_url(path_or_url)) 2928 SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool)); 2929 2930 err = svn_client_get_repos_root(url, NULL, path_or_url, 2931 ctx, pool, subpool); 2932 2933 /* close ra session */ 2934 svn_pool_destroy(subpool); 2935 return svn_error_trace(err); 2936} 2937 2938svn_error_t * 2939svn_client_url_from_path(const char **url, 2940 const char *path_or_url, 2941 apr_pool_t *pool) 2942{ 2943 svn_client_ctx_t *ctx; 2944 2945 SVN_ERR(svn_client_create_context(&ctx, pool)); 2946 2947 return svn_client_url_from_path2(url, path_or_url, ctx, pool, pool); 2948} 2949 2950/*** From mergeinfo.c ***/ 2951svn_error_t * 2952svn_client_mergeinfo_log(svn_boolean_t finding_merged, 2953 const char *target_path_or_url, 2954 const svn_opt_revision_t *target_peg_revision, 2955 const char *source_path_or_url, 2956 const svn_opt_revision_t *source_peg_revision, 2957 svn_log_entry_receiver_t receiver, 2958 void *receiver_baton, 2959 svn_boolean_t discover_changed_paths, 2960 svn_depth_t depth, 2961 const apr_array_header_t *revprops, 2962 svn_client_ctx_t *ctx, 2963 apr_pool_t *scratch_pool) 2964{ 2965 svn_opt_revision_t start_revision, end_revision; 2966 2967 start_revision.kind = svn_opt_revision_unspecified; 2968 end_revision.kind = svn_opt_revision_unspecified; 2969 2970 return svn_client_mergeinfo_log2(finding_merged, 2971 target_path_or_url, target_peg_revision, 2972 source_path_or_url, source_peg_revision, 2973 &start_revision, &end_revision, 2974 receiver, receiver_baton, 2975 discover_changed_paths, depth, revprops, 2976 ctx, scratch_pool); 2977} 2978 2979svn_error_t * 2980svn_client_mergeinfo_log_merged(const char *path_or_url, 2981 const svn_opt_revision_t *peg_revision, 2982 const char *merge_source_path_or_url, 2983 const svn_opt_revision_t *src_peg_revision, 2984 svn_log_entry_receiver_t log_receiver, 2985 void *log_receiver_baton, 2986 svn_boolean_t discover_changed_paths, 2987 const apr_array_header_t *revprops, 2988 svn_client_ctx_t *ctx, 2989 apr_pool_t *pool) 2990{ 2991 return svn_client_mergeinfo_log(TRUE, path_or_url, peg_revision, 2992 merge_source_path_or_url, 2993 src_peg_revision, 2994 log_receiver, log_receiver_baton, 2995 discover_changed_paths, 2996 svn_depth_empty, revprops, ctx, 2997 pool); 2998} 2999 3000svn_error_t * 3001svn_client_mergeinfo_log_eligible(const char *path_or_url, 3002 const svn_opt_revision_t *peg_revision, 3003 const char *merge_source_path_or_url, 3004 const svn_opt_revision_t *src_peg_revision, 3005 svn_log_entry_receiver_t log_receiver, 3006 void *log_receiver_baton, 3007 svn_boolean_t discover_changed_paths, 3008 const apr_array_header_t *revprops, 3009 svn_client_ctx_t *ctx, 3010 apr_pool_t *pool) 3011{ 3012 return svn_client_mergeinfo_log(FALSE, path_or_url, peg_revision, 3013 merge_source_path_or_url, 3014 src_peg_revision, 3015 log_receiver, log_receiver_baton, 3016 discover_changed_paths, 3017 svn_depth_empty, revprops, ctx, 3018 pool); 3019} 3020 3021/*** From relocate.c ***/ 3022svn_error_t * 3023svn_client_relocate(const char *path, 3024 const char *from_prefix, 3025 const char *to_prefix, 3026 svn_boolean_t recurse, 3027 svn_client_ctx_t *ctx, 3028 apr_pool_t *pool) 3029{ 3030 if (! recurse) 3031 SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, 3032 _("Non-recursive relocation not supported"))); 3033 return svn_client_relocate2(path, from_prefix, to_prefix, TRUE, ctx, pool); 3034} 3035 3036/*** From util.c ***/ 3037svn_error_t * 3038svn_client_commit_item_create(const svn_client_commit_item3_t **item, 3039 apr_pool_t *pool) 3040{ 3041 *item = svn_client_commit_item3_create(pool); 3042 return SVN_NO_ERROR; 3043} 3044 3045svn_client_commit_item2_t * 3046svn_client_commit_item2_dup(const svn_client_commit_item2_t *item, 3047 apr_pool_t *pool) 3048{ 3049 svn_client_commit_item2_t *new_item = apr_palloc(pool, sizeof(*new_item)); 3050 3051 *new_item = *item; 3052 3053 if (new_item->path) 3054 new_item->path = apr_pstrdup(pool, new_item->path); 3055 3056 if (new_item->url) 3057 new_item->url = apr_pstrdup(pool, new_item->url); 3058 3059 if (new_item->copyfrom_url) 3060 new_item->copyfrom_url = apr_pstrdup(pool, new_item->copyfrom_url); 3061 3062 if (new_item->wcprop_changes) 3063 new_item->wcprop_changes = svn_prop_array_dup(new_item->wcprop_changes, 3064 pool); 3065 3066 return new_item; 3067} 3068 3069svn_error_t * 3070svn_client_cleanup(const char *path, 3071 svn_client_ctx_t *ctx, 3072 apr_pool_t *scratch_pool) 3073{ 3074 const char *local_abspath; 3075 3076 if (svn_path_is_url(path)) 3077 return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, 3078 _("'%s' is not a local path"), path); 3079 3080 SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool)); 3081 3082 return svn_error_trace(svn_client_cleanup2(local_abspath, 3083 TRUE /* break_locks */, 3084 TRUE /* fix_recorded_timestamps */, 3085 TRUE /* clear_dav_cache */, 3086 TRUE /* vacuum_pristines */, 3087 FALSE /* include_externals */, 3088 ctx, scratch_pool)); 3089} 3090