1# Licensed to the Apache Software Foundation (ASF) under one 2# or more contributor license agreements. See the NOTICE file 3# distributed with this work for additional information 4# regarding copyright ownership. The ASF licenses this file 5# to you under the Apache License, Version 2.0 (the 6# "License"); you may not use this file except in compliance 7# with the License. You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, 12# software distributed under the License is distributed on an 13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14# KIND, either express or implied. See the License for the 15# specific language governing permissions and limitations 16# under the License. 17 18 19from csvn.core import * 20from csvn.auth import * 21from ctypes import * 22import csvn.types as _types 23import os, sys 24 25class WC(object): 26 """A SVN working copy.""" 27 28 def __init__(self, path="", user=None): 29 """Open a working copy directory relative to path. 30 31 Keyword arguments: 32 path -- path to the working copy (default current working directory) 33 user -- object implementing the user interface representing the user 34 performing the operation (defaults to an instance of the User class) 35 """ 36 if user is None: 37 user = User() 38 39 self.pool = Pool() 40 self.iterpool = Pool() 41 self.path = path.replace(os.sep, "/") 42 self.user = user 43 44 self.client = POINTER(svn_client_ctx_t)() 45 svn_client_create_context(byref(self.client), self.pool) 46 self._as_parameter_ = POINTER(svn_ra_session_t)() 47 48 self.user.setup_auth_baton(pointer(self.client.contents.auth_baton)) 49 50 self.client[0].notify_func2 = \ 51 svn_wc_notify_func2_t(self._notify_func_wrapper) 52 self.client[0].notify_baton2 = c_void_p() 53 self._notify_func = None 54 55 self.client[0].cancel_func = \ 56 svn_cancel_func_t(self._cancel_func_wrapper) 57 self.client[0].cancel_baton = c_void_p() 58 self._cancel_func = None 59 60 self.client[0].progress_func = \ 61 svn_ra_progress_notify_func_t(self._progress_func_wrapper) 62 self.client[0].progress_baton = c_void_p() 63 self._progress_func = None 64 65 self._status_func = \ 66 svn_wc_status_func2_t(self._status_wrapper) 67 self._status = None 68 69 self._info_func = \ 70 svn_info_receiver_t(self._info_wrapper) 71 self._info = None 72 73 self._list_func = \ 74 svn_client_list_func_t(self._list_wrapper) 75 self._list = None 76 77 self.client[0].log_msg_func2 = \ 78 svn_client_get_commit_log2_t(self._log_func_wrapper) 79 self.client[0].log_msg_baton2 = c_void_p() 80 self._log_func = None 81 82 def close(self): 83 """Close this WC object, releasing any resources.""" 84 self.pool.clear() 85 86 def copy(self, src, dest, rev = ""): 87 """Copy src to dest. 88 89 Keyword arguments: 90 src -- current file name 91 dest -- new file name""" 92 opt_rev = svn_opt_revision_t() 93 dummy_rev = svn_opt_revision_t() 94 info = POINTER(svn_commit_info_t)() 95 svn_opt_parse_revision(byref(opt_rev), byref(dummy_rev), 96 str(rev), self.iterpool) 97 98 svn_client_copy3(byref(info), 99 self._build_path(src), 100 byref(opt_rev), 101 self._build_path(dest), 102 self.client, self.iterpool) 103 self.iterpool.clear() 104 105 def move(self, src, dest, force = False): 106 """Move src to dest. 107 108 Keyword arguments: 109 src -- current file name 110 dest -- new file name 111 force -- if True, operation will be forced (default False)""" 112 113 info = POINTER(svn_commit_info_t)() 114 svn_client_move3(byref(info), 115 self._build_path(src), 116 self._build_path(dest), 117 force, 118 self.client, self.iterpool) 119 self.iterpool.clear() 120 121 def delete(self, paths, force = False): 122 """Schedule paths to be deleted. 123 124 Keyword arguments: 125 paths -- list of paths to marked for deletion 126 force -- if True, operation will be forced (default False)""" 127 128 info = POINTER(svn_commit_info_t)() 129 svn_client_delete2(byref(info), self._build_path_list(paths), 130 force, self.client, self.iterpool) 131 self.iterpool.clear() 132 133 def add(self, path, recurse = True, force = False, no_ignore = False): 134 """Schedule path to be added. 135 136 Keyword arguments: 137 path -- path to be marked for addition 138 recurse -- if True, the contents of directories will also be 139 added (default True) 140 force -- if True, the operation will be forced (default False) 141 no_ignore -- if True, nothing will be ignored (default False)""" 142 143 svn_client_add3(self._build_path(path), 144 recurse, force, no_ignore, self.client, 145 self.iterpool) 146 self.iterpool.clear() 147 148 def resolve(self, path, recurse = True): 149 """Resolve a conflict on path. 150 151 This operation does not actually change path at all, it just marks the 152 conflict as resolved. 153 154 Keyword arguments: 155 path -- path to be marked as resolved 156 recurse -- if True, directories will be recursed (default True)""" 157 158 svn_client_resolved(path, recurse, self.client, self.iterpool) 159 self.iterpool.clear() 160 161 def revert(self, paths, recurse = False): 162 """Revert paths to the most recent version. 163 164 Keyword arguments: 165 paths -- list of paths to be reverted 166 recurse -- if True, directories will be recursed (default True)""" 167 168 svn_client_revert(self._build_path_list(paths), recurse, 169 self.client, self.iterpool) 170 self.iterpool.clear() 171 172 def _build_path_list(self, paths): 173 """Build a list of canonicalized WC paths. 174 175 In general, the user does not need to call this method, paths will be 176 canonicalized as needed for you. 177 178 Returns an array of canonicalized paths. 179 180 Keyword arguments: 181 paths -- list of paths to be canonicalized""" 182 183 # If the user passed in a string, the user made a mistake. 184 # The user should be passing in a list of paths. 185 assert not isinstance(paths, str) 186 187 canonicalized_paths = [self._build_path(path) for path in paths] 188 return _types.Array(String, canonicalized_paths) 189 190 def _build_path(self, path): 191 """Build a canonicalized path. 192 193 In general, the user does not need to call this method, paths will be 194 canonicalized as needed for you. 195 196 Returns a canonical path. 197 198 Keyword arguments: 199 path -- path to be canonicalized""" 200 joined_path = os.path.join(self.path.replace("/", os.sep), path.replace("/", os.sep)) 201 return svn_path_canonicalize(joined_path.replace(os.sep, "/"), self.iterpool) 202 203 def set_notify_func(self, notify_func): 204 """Setup a callback so that you can be notified when paths are 205 affected by WC operations. 206 207 When paths are affected, we will call the function with an 208 svn_wc_notify_t object. For details on the contents of an 209 svn_wc_notify_t object, see the documentation for svn_wc_notify_t. 210 211 Keyword arguments: 212 notify_func -- function to be used in the callback""" 213 self._notify_func = notify_func 214 215 # A helper function which invokes the user notify function with 216 # the appropriate arguments. 217 def _notify_func_wrapper(self, baton, notify, pool): 218 """Used to wrap the user callback.""" 219 if self._notify_func: 220 pool = Pool() 221 notify = svn_wc_dup_notify(notify, pool)[0] 222 notify.pool = pool 223 self._notify_func(notify[0]) 224 225 def set_cancel_func(self, cancel_func): 226 """Setup a callback so that you can cancel operations. 227 228 At various times the cancel function will be called, giving 229 the option of cancelling the operation. 230 231 Keyword arguments: 232 cancel_func -- function to be used in the callback""" 233 234 self._cancel_func = cancel_func 235 236 #Just like _notify_func_wrapper, above. 237 def _cancel_func_wrapper(self, baton): 238 """Used to wrap the cancel callback.""" 239 if self._cancel_func: 240 self._cancel_func() 241 242 def set_progress_func(self, progress_func): 243 """Setup a callback for network progress information. 244 245 This callback should accept two integers, being the number of bytes 246 sent and the number of bytes to send. 247 248 Keyword arguments: 249 progress_func -- function to be used in the callback""" 250 251 self._progress_func = progress_func 252 253 def _progress_func_wrapper(self, progress, total, baton, pool): 254 if self._progress_func: 255 self._progress_func(progress, total) 256 257 def diff(self, path1="", revnum1=None, path2=None, revnum2=None, 258 diff_options=[], recurse=True, ignore_ancestry=True, 259 no_diff_deleted=False, ignore_content_type=False, 260 header_encoding="", outfile = sys.stdout, errfile = sys.stderr): 261 """Produce svn diff output that describes the difference between 262 PATH1 at REVISION1 and PATH2 at REVISION2. 263 264 Keyword arguments: 265 path1 -- path to compare in diff (defaults to working copy root) 266 revnum1 -- revision to look at path1 at (defaults to base revision) 267 path2 -- second path to compare in diff (defaults to path1) 268 revnum2 -- revision to look at path2 at (defaults to working revision) 269 diff_options -- list of options to be passed to the diff process 270 (defaults to an empty list) 271 recurse -- if True, contents of directories will also be diffed 272 (default True) 273 ignore_ancestry -- if True then items will not be checked for 274 relatedness before being diffed (default True) 275 no_diff_deleted -- if True then deleted items will not be included in 276 the diff (default False) 277 ignore_content_type -- if True diffs will be generated for binary file 278 types (default False) 279 header_encoding -- generated headers will be encoded using this 280 encoding (defaults to "") 281 outfile -- file to save output to, which can be a file like object 282 (defaults to sys.stdout) 283 errfile -- file to save output to, which can be a file like object 284 (defaults to sys.stderr)""" 285 286 diff_options = self._build_path_list(diff_options) 287 288 rev1 = svn_opt_revision_t() 289 if revnum1: 290 rev1.kind = svn_opt_revision_number 291 rev1.value.number = revnum1 292 else: 293 rev1.kind = svn_opt_revision_base 294 295 rev2 = svn_opt_revision_t() 296 if revnum2: 297 rev2.kind = svn_opt_revision_number 298 rev2.value.number = revnum2 299 else: 300 rev2.kind = svn_opt_revision_working 301 302 path1 = self._build_path(path1) 303 if path2: 304 path2 = self._build_path(path2) 305 else: 306 path2 = path1 307 308 # Create temporary objects for output and errors 309 apr_outfile = _types.APRFile(outfile) 310 apr_errfile = _types.APRFile(errfile) 311 312 svn_client_diff3(diff_options, path1, byref(rev1), path2, byref(rev2), recurse, 313 ignore_ancestry, no_diff_deleted, ignore_content_type, 314 header_encoding, apr_outfile, apr_errfile, self.client, 315 self.iterpool) 316 317 # Close the APR wrappers 318 apr_outfile.close() 319 apr_errfile.close() 320 321 self.iterpool.clear() 322 323 def cleanup(self, path=""): 324 """Recursively cleanup the working copy. 325 326 Cleanup means: finish any incomplete operations and release all locks. 327 328 Keyword arguments: 329 path -- path to cleanup (defaults to WC root)""" 330 svn_client_cleanup(self._build_path(path), self.client, 331 self.iterpool) 332 333 self.iterpool.clear() 334 335 def export(self, from_path, to_path, overwrite=False, 336 ignore_externals=True, recurse=True, eol=NULL): 337 """Export from_path to to_path. 338 339 An export creates a clean copy of the exported items, with no 340 subversion metadata. 341 342 Keyword arguments: 343 from_path -- path to export 344 to_path -- location to export to 345 overwrite -- if True, existing items at to_path will be overwritten 346 (default False) 347 ignore_externals -- if True, export does not include externals (default 348 True) 349 recurse -- if True, directory contents will also be exported (default 350 True) 351 eol -- End of line character to use (defaults to standard eol marker)""" 352 353 rev = svn_opt_revision_t() 354 peg_rev = svn_opt_revision_t() 355 356 svn_client_export3(POINTER(svn_revnum_t)(), 357 self._build_path(from_path), 358 self._build_path(to_path), byref(peg_rev), 359 byref(rev), overwrite, ignore_externals, recurse, 360 eol, self.client, self.iterpool) 361 362 self.iterpool.clear() 363 364 def resolved(self, path="", recursive=True): 365 """Resolve a conflict on PATH. Marks the conflict as resolved, does 366 not change the text of PATH. 367 368 If RECURSIVE is True (True by default) then directories will be 369 recursed.""" 370 svn_client_resolved(self._build_path(path), recursive, self.client, 371 self.iterpool) 372 self.iterpool.clear() 373 374 def mkdir(self, paths): 375 """Create directories in the working copy. 376 377 Keyword arguments: 378 paths -- list of paths to be created""" 379 paths = self._build_path_list(paths) 380 381 # The commit info shouldn't matter, this is a method of the WC 382 # class, so it isn't intended for remote operations. 383 info = POINTER(svn_commit_info_t)() 384 385 svn_client_mkdir2(byref(info), paths, self.client, self.iterpool) 386 387 self.iterpool.clear() 388 389 def propset(self, propname, propval, target="", recurse=True, 390 skip_checks=False): 391 """Set propname to propval for target. 392 393 Keyword arguments: 394 propname -- name of property to be set 395 propval -- value to set property to 396 target -- path to set property for (default WC root) 397 recurse -- if True and target is a directory the operation will recurse 398 setting the property for the contents of that directory (default 399 True) 400 skip_checks -- if True, no sanity checks will be performed on propname 401 (default False)""" 402 403 svn_client_propset2(propname, 404 svn_string_create(propval, self.iterpool), 405 self._build_path(target), recurse, skip_checks, 406 self.client, self.iterpool) 407 408 self.iterpool.clear() 409 410 def proplist(self, target="", recurse=True): 411 """List the values of the normal properties of target. 412 413 Returns an array of svn_client_proplist_item_t objects. 414 415 Keyword arguments: 416 target -- path to list properties for (defaults to WC root) 417 recurse -- if True, the operation will recurse (default True)""" 418 peg_revision = svn_opt_revision_t() 419 peg_revision.kind = svn_opt_revision_unspecified 420 421 revision = svn_opt_revision_t() 422 revision.kind = svn_opt_revision_working 423 424 props = _types.Array(svn_client_proplist_item_t) 425 426 svn_client_proplist2(byref(props.header), self._build_path(target), 427 byref(peg_revision), byref(revision), recurse, 428 self.client, props.pool) 429 430 self.iterpool.clear() 431 432 return props 433 434 def propget(self, propname, target="", recurse=True): 435 """Get the value of propname for target. 436 437 Returns a hash the keys of which are file paths and the values are the 438 value of PROPNAME for the corresponding file. The values of the hash 439 are c_char_p objects, which can be treated much like strings. 440 441 Keyword arguments: 442 propname -- name of property to get 443 target -- item to get properties for (defaults to Wc root) 444 recurse -- if True, operation will recurse into directories (default 445 True)""" 446 peg_revision = svn_opt_revision_t() 447 peg_revision.kind = svn_opt_revision_unspecified 448 449 revision = svn_opt_revision_t() 450 revision.kind = svn_opt_revision_working 451 452 props = _types.Hash(c_char_p) 453 454 svn_client_propget2(byref(props.hash), propname, 455 self._build_path(target), byref(peg_revision), 456 byref(revision), recurse, self.client, props.pool) 457 458 self.iterpool.clear() 459 return props 460 461 # Internal method to wrap status callback. 462 def _status_wrapper(self, baton, path, status): 463 """Wrapper for status callback.""" 464 if self._status: 465 pool = Pool() 466 status = svn_wc_dup_status2(status, pool)[0] 467 status.pool = pool 468 self._status(path, status) 469 470 def set_status_func(self, status): 471 """Set a callback function to be used the next time the status method 472 is called. 473 474 Keyword arguments: 475 status -- function to be used in status callback""" 476 self._status = status 477 478 def status(self, path="", status=None, recurse=True, 479 get_all=False, update=False, no_ignore=False, 480 ignore_externals=False): 481 """Get the status on path using callback to status. 482 483 The status callback (which can be set when this method is called or 484 earlier) will be called for each item. 485 486 Keyword arguments: 487 path -- items to get status for (defaults to WC root) 488 status -- callback to be used (defaults to previously registered 489 callback) 490 recurse -- if True, the contents of directories will also be checked 491 (default True) 492 get_all -- if True, all entries will be retrieved, otherwise only 493 interesting entries (local modifications and/or out-of-date) will 494 be retrieved (default False) 495 update -- if True, the repository will be contacted to get information 496 about out-of-dateness and a revision number will be returned to 497 indicate which revision the Wc was compared against (default False) 498 no_ignore -- if True, nothing is ignored (default False) 499 ignore_externals -- if True, externals will be ignored (default False) 500 """ 501 rev = svn_opt_revision_t() 502 rev.kind = svn_opt_revision_working 503 504 if status: 505 self.set_status_func(status) 506 507 result_rev = svn_revnum_t() 508 svn_client_status2(byref(result_rev), self._build_path(path), 509 byref(rev), self._status_func, 510 c_void_p(), recurse, get_all, 511 update, no_ignore, ignore_externals, self.client, 512 self.iterpool) 513 514 self.iterpool.clear() 515 516 return result_rev 517 518 def _info_wrapper(self, baton, path, info, pool): 519 """Internal wrapper for info method callbacks.""" 520 if self._info: 521 pool = Pool() 522 info = svn_info_dup(info, pool)[0] 523 info.pool = pool 524 self._info(path, info) 525 526 def set_info_func(self, info): 527 """Set a callback to be used to process svn_info_t objects during 528 calls to the info method. 529 530 The callback function should accept a path and a svn_info_t object as 531 arguments. 532 533 Keyword arguments: 534 info -- callback to be used to process information during a call to 535 the info method.""" 536 self._info = info 537 538 def info(self, path="", recurse=True, info_func=None): 539 """Get info about path. 540 541 Keyword arguments: 542 path -- path to get info about (defaults to WC root) 543 recurse -- if True, directories will be recursed 544 info_func -- callback function to use (defaults to previously 545 registered callback)""" 546 547 if info_func: 548 self.set_info_func(info_func) 549 550 svn_client_info(self._build_path(path), NULL, NULL, self._info_func, 551 c_void_p(), recurse, self.client, 552 self.iterpool) 553 554 self.iterpool.clear() 555 556 def checkout(self, url, revnum=None, path=None, recurse=True, 557 ignore_externals=False): 558 """Checkout a new working copy. 559 560 Keyword arguments: 561 url -- url to check out from, should be of the form url@peg_revision 562 revnum -- revision number to check out 563 path -- location to checkout to (defaults to WC root) 564 ignore_externals -- if True, externals will not be included in checkout 565 (default False)""" 566 rev = svn_opt_revision_t() 567 if revnum is not None: 568 rev.kind = svn_opt_revision_number 569 rev.value.number = revnum 570 else: 571 rev.kind = svn_opt_revision_head 572 573 peg_rev = svn_opt_revision_t() 574 URL = String("") 575 svn_opt_parse_path(byref(peg_rev), byref(URL), url, self.iterpool) 576 577 if not path: 578 path = self.path 579 canon_path = svn_path_canonicalize(path, self.iterpool) 580 581 result_rev = svn_revnum_t() 582 583 svn_client_checkout2(byref(result_rev), URL, canon_path, 584 byref(peg_rev), byref(rev), recurse, 585 ignore_externals, self.client, self.iterpool) 586 self.iterpool.clear() 587 588 def set_log_func(self, log_func): 589 """Register a callback to get a log message for commit and commit-like 590 operations. 591 592 LOG_FUNC should take an array as an argument, which holds the files to 593 be committed. It should return a list of the form [LOG, FILE] where LOG 594 is a log message and FILE is the temporary file, if one was created 595 instead of a log message. If LOG is None, the operation will be 596 canceled and FILE will be treated as the temporary file holding the 597 temporary commit message. 598 599 Keyword arguments: 600 log_func -- callback to be used for getting log messages""" 601 self._log_func = log_func 602 603 def _log_func_wrapper(self, log_msg, tmp_file, commit_items, baton, pool): 604 """Internal wrapper for log function callback.""" 605 if self._log_func: 606 [log, file] = self._log_func(_types.Array(String, commit_items)) 607 608 if log: 609 log_msg = pointer(c_char_p(log)) 610 else: 611 log_msg = NULL 612 613 if file: 614 tmp_file = pointer(c_char_p(file)) 615 else: 616 tmp_file = NULL 617 618 def commit(self, paths=[""], recurse=True, keep_locks=False): 619 """Commit changes in the working copy. 620 621 Keyword arguments: 622 paths -- list of paths that should be committed (defaults to WC root) 623 recurse -- if True, the contents of directories to be committed will 624 also be committed (default True) 625 keep_locks -- if True, locks will not be released during commit 626 (default False)""" 627 commit_info = POINTER(svn_commit_info_t)() 628 pool = Pool() 629 svn_client_commit3(byref(commit_info), self._build_path_list(paths), 630 recurse, keep_locks, self.client, pool) 631 commit_info[0].pool = pool 632 return commit_info[0] 633 634 def update(self, paths=[""], revnum=None, recurse=True, 635 ignore_externals=True): 636 """Update paths to a given revision number. 637 638 Returns an array of revision numbers to which the revision number was 639 resolved. 640 641 Keyword arguments: 642 paths -- list of path to be updated (defaults to WC root) 643 revnum -- revision number to update to (defaults to head revision) 644 recurse -- if True, the contents of directories will also be updated 645 (default True) 646 ignore_externals -- if True, externals will not be updated (default 647 True)""" 648 649 rev = svn_opt_revision_t() 650 if revnum is not None: 651 rev.kind = svn_opt_revision_number 652 rev.value.number = revnum 653 else: 654 rev.kind = svn_opt_revision_head 655 656 result_revs = _types.Array(svn_revnum_t, svn_revnum_t()) 657 658 svn_client_update2(byref(result_revs.header), 659 self._build_path_list(paths), byref(rev), recurse, 660 ignore_externals, self.client, self.iterpool) 661 662 self.iterpool.clear() 663 return result_revs 664 665 #internal method to wrap ls callbacks 666 def _list_wrapper(self, baton, path, dirent, abs_path, pool): 667 """Internal method to wrap list callback.""" 668 if self._list: 669 pool = Pool() 670 dirent = svn_dirent_dup(dirent, pool)[0] 671 lock = svn_lock_dup(lock, pool)[0] 672 dirent.pool = pool 673 lock.pool = pool 674 self._list(path, dirent, lock, abs_path) 675 676 def set_list_func(self, list_func): 677 """Set the callback function for list operations. 678 679 Keyword arguments: 680 list_func -- function to be used for callbacks""" 681 self._list = list_func 682 683 def list(self, path="", recurse=True, fetch_locks=False, list_func=None): 684 """List items in the working copy using a callback. 685 686 Keyword arguments: 687 path -- path to list (defaults to WC root) 688 recurse -- if True, list contents of directories as well (default True) 689 fetch_locks -- if True, get information from the repository about locks 690 (default False) 691 list_func -- callback to be used (defaults to previously registered 692 callback)""" 693 peg = svn_opt_revision_t() 694 peg.kind = svn_opt_revision_working 695 696 rev = svn_opt_revision_t() 697 rev.kind = svn_opt_revision_working 698 699 if list_func: 700 self.set_list_func(list_func) 701 702 svn_client_list(self._build_path(path), byref(peg), byref(rev), 703 recurse, SVN_DIRENT_ALL, fetch_locks, self._list_func, 704 c_void_p(), self.client, self.iterpool) 705 706 self.iterpool.clear() 707 708 def relocate(self, from_url, to_url, dir="", recurse=True): 709 """Modify a working copy directory, changing repository URLs that begin 710 with FROM_URL to begin with TO_URL instead, recursing into 711 subdirectories if RECURSE is True (True by default). 712 713 Keyword arguments: 714 from_url -- url to be replaced, if this url is matched at the beginning 715 of a url it will be replaced with to_url 716 to_url -- url to replace from_url 717 dir -- directory to relocate (defaults to WC root) 718 recurse -- if True, directories will be recursed (default True)""" 719 720 svn_client_relocate(self._build_path(dir), from_url, to_url, recurse, 721 self.client, self.iterpool) 722 723 self.iterpool.clear() 724 725 def switch(self, path, url, revnum=None, recurse=True): 726 """Switch part of a working copy to a new url. 727 728 Keyword arguments: 729 path -- path to be changed to a new url 730 url -- url to be used 731 revnum -- revision to be switched to (defaults to head revision) 732 recurse -- if True, the operation will recurse (default True)""" 733 result_rev = svn_revnum_t() 734 735 revision = svn_opt_revision_t() 736 if revnum: 737 revision.kind = svn_opt_revision_number 738 revision.value.number = revnum 739 else: 740 revision.kind = svn_opt_revision_head 741 742 svn_client_switch(byref(result_rev), 743 self._build_path(path), url, byref(revision), 744 recurse, self.client, self.iterpool) 745 self.iterpool.clear() 746 747 def lock(self, paths, comment=NULL, steal_lock=False): 748 """Lock items. 749 750 Keyword arguments: 751 paths -- list of paths to be locked, may be WC paths (in which 752 case this is a local operation) or urls (in which case this is a 753 network operation) 754 comment -- comment for the lock (default no comment) 755 steal_lock -- if True, the lock will be created even if the file is 756 already locked (default False)""" 757 targets = self._build_path_list(paths) 758 svn_client_lock(targets, comment, steal_lock, self.client, self.iterpool) 759 self.iterpool.clear() 760 761 def unlock(self, paths, break_lock=False): 762 """Unlock items. 763 764 Keyword arguments: 765 paths - list of paths to be unlocked, may be WC paths (in which 766 case this is a local operation) or urls (in which case this is a 767 network operation) 768 break_lock -- if True, locks will be broken (default False)""" 769 targets = self._build_path_list(paths) 770 svn_client_unlock(targets, break_lock, self.client, self.iterpool) 771 self.iterpool.clear() 772 773 def merge(self, source1, revnum1, source2, revnum2, target_wcpath, 774 recurse=True, ignore_ancestry=False, force=False, 775 dry_run=False, merge_options=[]): 776 """Merge changes. 777 778 This method merges the changes from source1@revnum1 to 779 source2@revnum2 into target_wcpath. 780 781 Keyword arguments: 782 source1 -- path for beginning revision of changes to be merged 783 revnum1 -- starting revnum 784 source2 -- path for ending revision of changes to merge 785 revnum2 -- ending revnum 786 target_wcpath -- path to apply changes to 787 recurse -- if True, apply changes recursively 788 ignore_ancestry -- if True, relatedness will not be checked (False by 789 default) 790 force -- if False and the merge involves deleting locally modified 791 files the merge will fail (default False) 792 dry_run -- if True, notification will be provided but no local files 793 will be modified (default False) 794 merge_options -- a list of options to be passed to the diff process 795 (default no options)""" 796 revision1 = svn_opt_revision_t() 797 revision1.kind = svn_opt_revision_number 798 revision1.value.number = revnum1 799 800 revision2 = svn_opt_revision_t() 801 revision2.kind = svn_opt_revision_number 802 revision2.value.number = revnum2 803 804 merge_options = _types.Array(c_char_p, merge_options) 805 806 svn_client_merge2(source1, byref(revision1), source2, byref(revision2), 807 target_wcpath, recurse, ignore_ancestry, force, dry_run, 808 merge_options.header, self.client, self.iterpool) 809 810 self.iterpool.clear() 811