1# ==================================================================== 2# Licensed to the Apache Software Foundation (ASF) under one 3# or more contributor license agreements. See the NOTICE file 4# distributed with this work for additional information 5# regarding copyright ownership. The ASF licenses this file 6# to you under the Apache License, Version 2.0 (the 7# "License"); you may not use this file except in compliance 8# with the License. You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, 13# software distributed under the License is distributed on an 14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15# KIND, either express or implied. See the License for the 16# specific language governing permissions and limitations 17# under the License. 18# ==================================================================== 19 20require "English" 21require 'uri' 22require "svn/error" 23require "svn/util" 24require "svn/core" 25require "svn/wc" 26require "svn/ra" 27require "svn/ext/client" 28 29module Svn 30 module Client 31 Util.set_constants(Ext::Client, self) 32 Util.set_methods(Ext::Client, self) 33 34 class CommitItem 35 class << self 36 undef new 37 end 38 end 39 40 class CommitItem2 41 class << self 42 undef new 43 end 44 end 45 46 class CommitItem3 47 alias_method :wcprop_changes, :incoming_prop_changes 48 alias_method :wcprop_changes=, :incoming_prop_changes= 49 end 50 51 class CommitItemWrapper 52 def initialize(item) 53 @item = item 54 end 55 56 def incoming_prop_changes 57 if @item.incoming_prop_changes 58 Util.hash_to_prop_array(@item.incoming_prop_changes) 59 else 60 nil 61 end 62 end 63 alias_method :wcprop_changes, :incoming_prop_changes 64 65 def method_missing(method, *args, &block) 66 @item.__send__(method, *args, &block) 67 end 68 end 69 70 class Info 71 alias url URL 72 alias repos_root_url repos_root_URL 73 74 alias _last_changed_date last_changed_date 75 def last_changed_date 76 Time.from_apr_time(_last_changed_date) 77 end 78 end 79 80 81 # For backward compatibility 82 class PropListItem 83 # Returns an URI for the item concerned with the instance. 84 attr_accessor :name 85 86 # Returns a Hash of properties, such as 87 # <tt>{propname1 => propval1, propname2 => propval2, ...}</tt>. 88 attr_accessor :props 89 90 alias_method :node_name, :name 91 alias_method :prop_hash, :props 92 93 def initialize(name, props) 94 @name = name 95 @props = props 96 end 97 98 def method_missing(meth, *args) 99 if @props.respond_to?(meth) 100 @props.__send__(meth, *args) 101 else 102 super 103 end 104 end 105 end 106 107 Context = Ctx 108 class Context 109 alias _auth_baton auth_baton 110 alias _auth_baton= auth_baton= 111 remove_method :auth_baton, :auth_baton= 112 private :_auth_baton, :_auth_baton= 113 114 include Core::Authenticatable 115 116 alias _initialize initialize 117 private :_initialize 118 def initialize 119 _initialize 120 self.auth_baton = Core::AuthBaton.new 121 init_callbacks 122 return unless block_given? 123 begin 124 yield(self) 125 ensure 126 destroy 127 end 128 end 129 130 def destroy 131 Svn::Destroyer.destroy(self) 132 end 133 134 def auth_baton=(baton) 135 super(baton) 136 self._auth_baton = auth_baton 137 end 138 139 def checkout(url, path, revision=nil, peg_rev=nil, 140 depth=nil, ignore_externals=false, 141 allow_unver_obstruction=false) 142 revision ||= "HEAD" 143 Client.checkout3(url, path, peg_rev, revision, depth, 144 ignore_externals, allow_unver_obstruction, 145 self) 146 end 147 alias co checkout 148 149 def mkdir(*paths) 150 paths = paths.first if paths.size == 1 and paths.first.is_a?(Array) 151 mkdir2(:paths => paths) 152 end 153 154 MKDIR_REQUIRED_ARGUMENTS_KEYS = [:paths] 155 def mkdir2(arguments) 156 optional_arguments_defaults = { 157 :make_parents => false, 158 :revprop_table => {}, 159 } 160 161 arguments = optional_arguments_defaults.merge(arguments) 162 Util.validate_options(arguments, 163 optional_arguments_defaults.keys, 164 MKDIR_REQUIRED_ARGUMENTS_KEYS) 165 Client.mkdir3(normalize_path(arguments[:paths]), 166 arguments[:make_parents], 167 arguments[:revprop_table], 168 self) 169 end 170 171 def mkdir_p(*paths) 172 revprop_table = paths.pop if paths.last.is_a?(Hash) 173 paths = paths.first if paths.size == 1 and paths.first.is_a?(Array) 174 mkdir_p2(:paths => paths, :revprop_table => revprop_table || {}) 175 end 176 177 def mkdir_p2(arguments) 178 mkdir2(arguments.update(:make_parents => true)) 179 end 180 181 def commit(targets, recurse=true, keep_locks=false, 182 keep_changelist=false, changelist_name=nil, 183 revprop_table=nil) 184 targets = [targets] unless targets.is_a?(Array) 185 Client.commit4(targets, recurse, keep_locks, keep_changelist, 186 changelist_name, revprop_table, self) 187 end 188 alias ci commit 189 190 def status(path, rev=nil, depth_or_recurse=nil, get_all=false, 191 update=true, no_ignore=false, 192 ignore_externals=false, changelists_names=nil, &status_func) 193 depth = Core::Depth.infinity_or_immediates_from_recurse(depth_or_recurse) 194 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 195 Client.status3(path, rev, status_func, 196 depth, get_all, update, no_ignore, 197 ignore_externals, changelists_names, self) 198 end 199 alias st status 200 201 def add(path, recurse=true, force=false, no_ignore=false) 202 Client.add3(path, recurse, force, no_ignore, self) 203 end 204 205 def delete(paths, force=false, keep_local=false, revprop_table=nil) 206 paths = [paths] unless paths.is_a?(Array) 207 Client.delete3(paths, force, keep_local, revprop_table, self) 208 end 209 alias del delete 210 alias remove delete 211 alias rm remove 212 213 def rm_f(*paths) 214 paths = paths.first if paths.size == 1 and paths.first.is_a?(Array) 215 rm(paths, true) 216 end 217 218 def update(paths, rev="HEAD", depth=nil, ignore_externals=false, 219 allow_unver_obstruction=false, depth_is_sticky=false) 220 paths_is_array = paths.is_a?(Array) 221 paths = [paths] unless paths_is_array 222 result = Client.update3(paths, rev, depth, depth_is_sticky, 223 ignore_externals, allow_unver_obstruction, 224 self) 225 result = result.first unless paths_is_array 226 result 227 end 228 alias up update 229 230 def import(path, uri, depth_or_recurse=true, no_ignore=false, revprop_table=nil) 231 depth = Core::Depth.infinity_or_immediates_from_recurse(depth_or_recurse) 232 Client.import3(path, uri, depth, no_ignore, false, revprop_table, self) 233 end 234 235 def cleanup(dir) 236 Client.cleanup(dir, self) 237 end 238 239 def relocate(dir, from, to, recurse=true) 240 Client.relocate(dir, from, to, recurse, self) 241 end 242 243 def revert(paths, recurse=true) 244 paths = [paths] unless paths.is_a?(Array) 245 Client.revert(paths, recurse, self) 246 end 247 248 def resolved(path, recurse=true) 249 Client.resolved(path, recurse, self) 250 end 251 252 RESOLVE_REQUIRED_ARGUMENTS_KEYS = [:path] 253 def resolve(arguments={}) 254 arguments = arguments.reject {|k, v| v.nil?} 255 optional_arguments_defaults = { 256 :depth => nil, 257 :conflict_choice => Wc::CONFLICT_CHOOSE_POSTPONE 258 } 259 arguments = optional_arguments_defaults.merge(arguments) 260 Util.validate_options(arguments, 261 optional_arguments_defaults.keys, 262 RESOLVE_REQUIRED_ARGUMENTS_KEYS) 263 264 Client.resolve(arguments[:path], arguments[:depth], arguments[:conflict_choice], self) 265 end 266 267 def propset(name, value, target, depth_or_recurse=nil, force=false, 268 base_revision_for_url=nil, changelists_names=nil, 269 revprop_table=nil) 270 base_revision_for_url ||= Svn::Core::INVALID_REVNUM 271 depth = Core::Depth.infinity_or_empty_from_recurse(depth_or_recurse) 272 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 273 Client.propset3(name, value, target, depth, force, 274 base_revision_for_url, changelists_names, 275 revprop_table, self) 276 end 277 alias prop_set propset 278 alias pset propset 279 alias ps propset 280 281 def propdel(name, *args) 282 propset(name, nil, *args) 283 end 284 alias prop_del propdel 285 alias pdel propdel 286 alias pd propdel 287 288 # Returns a value of a property, with +name+ attached to +target+, 289 # as a Hash such as <tt>{uri1 => value1, uri2 => value2, ...}</tt>. 290 def propget(name, target, rev=nil, peg_rev=nil, depth_or_recurse=nil, 291 changelists_names=nil) 292 rev ||= "HEAD" 293 peg_rev ||= rev 294 depth = Core::Depth.infinity_or_empty_from_recurse(depth_or_recurse) 295 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 296 Client.propget3(name, target, peg_rev, rev, depth, changelists_names, self).first 297 end 298 alias prop_get propget 299 alias pget propget 300 alias pg propget 301 302 # Obsoleted document. 303 # 304 # Returns list of properties attached to +target+ as an Array of 305 # Svn::Client::PropListItem. 306 # Paths and URIs are available as +target+. 307 def proplist(target, peg_rev=nil, rev=nil, depth_or_recurse=nil, 308 changelists_names=nil, &block) 309 rev ||= "HEAD" 310 peg_rev ||= rev 311 items = [] 312 depth = Core::Depth.infinity_or_empty_from_recurse(depth_or_recurse) 313 receiver = Proc.new do |path, prop_hash| 314 items << PropListItem.new(path, prop_hash) 315 block.call(path, prop_hash) if block 316 end 317 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 318 Client.proplist3(target, peg_rev, rev, depth, changelists_names, 319 receiver, self) 320 items 321 end 322 alias prop_list proplist 323 alias plist proplist 324 alias pl proplist 325 326 def copy(src_paths, dst_path, rev_or_copy_as_child=nil, 327 make_parents=nil, revprop_table=nil) 328 if src_paths.is_a?(Array) 329 copy_as_child = rev_or_copy_as_child 330 if copy_as_child.nil? 331 copy_as_child = src_paths.size == 1 ? false : true 332 end 333 src_paths = src_paths.collect do |path| 334 if path.is_a?(CopySource) 335 path 336 else 337 CopySource.new(path) 338 end 339 end 340 else 341 copy_as_child = false 342 unless src_paths.is_a?(CopySource) 343 src_paths = CopySource.new(src_paths, rev_or_copy_as_child) 344 end 345 src_paths = [src_paths] 346 end 347 Client.copy4(src_paths, dst_path, copy_as_child, make_parents, 348 revprop_table, self) 349 end 350 alias cp copy 351 352 def move(src_paths, dst_path, force=false, move_as_child=nil, 353 make_parents=nil, revprop_table=nil) 354 src_paths = [src_paths] unless src_paths.is_a?(Array) 355 move_as_child = src_paths.size == 1 ? false : true if move_as_child.nil? 356 Client.move5(src_paths, dst_path, force, move_as_child, make_parents, 357 revprop_table, self) 358 end 359 alias mv move 360 361 def mv_f(src_paths, dst_path, move_as_child=nil) 362 move(src_paths, dst_path, true, move_as_child) 363 end 364 365 def diff(options, path1, rev1, path2, rev2, 366 out_file, err_file, depth=nil, 367 ignore_ancestry=false, 368 no_diff_deleted=false, force=false, 369 header_encoding=nil, relative_to_dir=nil, changelists=nil) 370 header_encoding ||= Core::LOCALE_CHARSET 371 relative_to_dir &&= Core.path_canonicalize(relative_to_dir) 372 Client.diff4(options, path1, rev1, path2, rev2, relative_to_dir, 373 depth, ignore_ancestry, 374 no_diff_deleted, force, header_encoding, 375 out_file, err_file, changelists, self) 376 end 377 378 def diff_peg(options, path, start_rev, end_rev, 379 out_file, err_file, peg_rev=nil, 380 depth=nil, ignore_ancestry=false, 381 no_diff_deleted=false, force=false, 382 header_encoding=nil, relative_to_dir=nil, changelists=nil) 383 header_encoding ||= Core::LOCALE_CHARSET 384 relative_to_dir &&= Core.path_canonicalize(relative_to_dir) 385 Client.diff_peg4(options, path, peg_rev, start_rev, end_rev, 386 relative_to_dir, depth, ignore_ancestry, 387 no_diff_deleted, force, header_encoding, 388 out_file, err_file, changelists, self) 389 end 390 391 # Invokes block once for each item changed between <tt>path1</tt> 392 # at <tt>rev1</tt> and <tt>path2</tt> at <tt>rev2</tt>, 393 # and returns +nil+. 394 # +diff+ is an instance of Svn::Client::DiffSummarize. 395 def diff_summarize(path1, rev1, path2, rev2, 396 depth=nil, ignore_ancestry=true, changelists=nil, 397 &block) # :yields: diff 398 Client.diff_summarize2(path1, rev1, path2, rev2, 399 depth, ignore_ancestry, changelists, block, 400 self) 401 end 402 403 def diff_summarize_peg(path1, rev1, rev2, peg_rev=nil, 404 depth=nil, ignore_ancestry=true, changelists=nil, 405 &block) 406 Client.diff_summarize_peg2(path1, rev1, rev2, peg_rev, 407 depth, ignore_ancestry, changelists, block, 408 self) 409 end 410 411 def merge(src1, rev1, src2, rev2, target_wcpath, 412 depth=nil, ignore_ancestry=false, 413 force=false, dry_run=false, options=nil, record_only=false) 414 Client.merge3(src1, rev1, src2, rev2, target_wcpath, 415 depth, ignore_ancestry, force, record_only, 416 dry_run, options, self) 417 end 418 419 420 def merge_peg(src, rev1, rev2, *rest) 421 merge_peg2(src, [[rev1, rev2]], *rest) 422 end 423 424 def merge_peg2(src, ranges_to_merge, target_wcpath, 425 peg_rev=nil, depth=nil, 426 ignore_ancestry=false, force=false, 427 dry_run=false, options=nil, record_only=false) 428 peg_rev ||= URI(src).scheme ? 'HEAD' : 'WORKING' 429 Client.merge_peg3(src, ranges_to_merge, peg_rev, 430 target_wcpath, depth, ignore_ancestry, 431 force, record_only, dry_run, options, self) 432 end 433 434 # Returns a content of +path+ at +rev+ as a String. 435 def cat(path, rev="HEAD", peg_rev=nil, output=nil) 436 used_string_io = output.nil? 437 output ||= StringIO.new 438 Client.cat2(output, path, peg_rev, rev, self) 439 if used_string_io 440 output.rewind 441 output.read 442 else 443 output 444 end 445 end 446 447 def lock(targets, comment=nil, steal_lock=false) 448 targets = [targets] unless targets.is_a?(Array) 449 Client.lock(targets, comment, steal_lock, self) 450 end 451 452 def unlock(targets, break_lock=false) 453 targets = [targets] unless targets.is_a?(Array) 454 Client.unlock(targets, break_lock, self) 455 end 456 457 def info(path_or_uri, rev=nil, peg_rev=nil, depth_or_recurse=false, 458 changelists=nil) 459 rev ||= URI(path_or_uri).scheme ? "HEAD" : "BASE" 460 depth = Core::Depth.infinity_or_empty_from_recurse(depth_or_recurse) 461 peg_rev ||= rev 462 receiver = Proc.new do |path, info| 463 yield(path, info) 464 end 465 Client.info2(path_or_uri, rev, peg_rev, receiver, depth, changelists, 466 self) 467 end 468 469 # Returns URL for +path+ as a String. 470 def url_from_path(path) 471 Client.url_from_path(path) 472 end 473 474 def uuid_from_path(path, adm) 475 Client.uuid_from_path(path, adm, self) 476 end 477 478 # Returns UUID for +url+ as a String. 479 def uuid_from_url(url) 480 Client.uuid_from_url(url, self) 481 end 482 483 def open_ra_session(url) 484 Client.open_ra_session(url, self) 485 end 486 487 # Scans revisions from +start_rev+ to +end_rev+ for each path in 488 # +paths+, invokes block once for each revision, and then returns 489 # +nil+. 490 # 491 # When +discover_changed_paths+ is +false+ or +nil+, +changed_paths+, 492 # the first block-argument, is +nil+. Otherwise, it is a Hash 493 # containing simple information associated with the revision, 494 # whose keys are paths and values are changes, such as 495 # <tt>{path1 => change1, path2 => change2, ...}</tt>, 496 # where each path is an absolute one in the repository and each 497 # change is a instance of Svn::Core::LogChangedPath. 498 # The rest of the block arguments, +rev+, +author+, +date+, and 499 # +message+ are the revision number, author, date, and the log 500 # message of that revision, respectively. 501 def log(paths, start_rev, end_rev, limit, 502 discover_changed_paths, strict_node_history, 503 peg_rev=nil) 504 paths = [paths] unless paths.is_a?(Array) 505 receiver = Proc.new do |changed_paths, rev, author, date, message| 506 yield(changed_paths, rev, author, date, message) 507 end 508 Client.log3(paths, peg_rev, start_rev, end_rev, limit, 509 discover_changed_paths, 510 strict_node_history, 511 receiver, self) 512 end 513 514 # Returns log messages, for commits affecting +paths+ from +start_rev+ 515 # to +end_rev+, as an Array of String. 516 # You can use URIs as well as paths as +paths+. 517 def log_message(paths, start_rev=nil, end_rev=nil) 518 start_rev ||= "HEAD" 519 end_rev ||= start_rev 520 messages = [] 521 receiver = Proc.new do |changed_paths, rev, author, date, message| 522 messages << message 523 end 524 log(paths, start_rev, end_rev, 0, false, false) do |*args| 525 receiver.call(*args) 526 end 527 if !paths.is_a?(Array) and messages.size == 1 528 messages.first 529 else 530 messages 531 end 532 end 533 534 def blame(path_or_uri, start_rev=nil, end_rev=nil, peg_rev=nil, 535 diff_options=nil, ignore_mime_type=false) 536 start_rev ||= 1 537 end_rev ||= URI(path_or_uri).scheme ? "HEAD" : "BASE" 538 peg_rev ||= end_rev 539 diff_options ||= Svn::Core::DiffFileOptions.new 540 receiver = Proc.new do |line_no, revision, author, date, line| 541 yield(line_no, revision, author, date, line) 542 end 543 Client.blame3(path_or_uri, peg_rev, start_rev, 544 end_rev, diff_options, ignore_mime_type, 545 receiver, self) 546 end 547 alias praise blame 548 alias annotate blame 549 alias ann annotate 550 551 # Returns a value of a revision property named +name+ for +uri+ 552 # at +rev+, as a String. 553 # Both URLs and paths are available as +uri+. 554 def revprop(name, uri, rev) 555 value, = revprop_get(name, uri, rev) 556 value 557 end 558 alias rp revprop 559 560 # Returns a value of a revision property named +name+ for +uri+ 561 # at +rev+, as an Array such as <tt>[value, rev]</tt>. 562 # Both URLs and paths are available as +uri+. 563 def revprop_get(name, uri, rev) 564 result = Client.revprop_get(name, uri, rev, self) 565 if result.is_a?(Array) 566 result 567 else 568 [nil, result] 569 end 570 end 571 alias rpget revprop_get 572 alias rpg revprop_get 573 574 # Sets +value+ as a revision property named +name+ for +uri+ at +rev+. 575 # Both URLs and paths are available as +uri+. 576 def revprop_set(name, value, uri, rev, force=false) 577 Client.revprop_set(name, value, uri, rev, force, self) 578 end 579 alias rpset revprop_set 580 alias rps revprop_set 581 582 # Deletes a revision property, named +name+, for +uri+ at +rev+. 583 # Both URLs and paths are available as +uri+. 584 def revprop_del(name, uri, rev, force=false) 585 Client.revprop_set(name, nil, uri, rev, force, self) 586 end 587 alias rpdel revprop_del 588 alias rpd revprop_del 589 590 # Returns a list of revision properties set for +uri+ at +rev+, 591 # as an Array such as 592 # <tt>[{revprop1 => value1, revprop2 => value2, ...}, rev]</tt>. 593 # Both URLs and paths are available as +uri+. 594 def revprop_list(uri, rev) 595 props, rev = Client.revprop_list(uri, rev, self) 596 if props.has_key?(Svn::Core::PROP_REVISION_DATE) 597 props[Svn::Core::PROP_REVISION_DATE] = 598 Time.from_svn_format(props[Svn::Core::PROP_REVISION_DATE]) 599 end 600 [props, rev] 601 end 602 alias rplist revprop_list 603 alias rpl revprop_list 604 605 def export(from, to, rev=nil, peg_rev=nil, 606 force=false, ignore_externals=false, 607 depth=nil, native_eol=nil) 608 Client.export4(from, to, rev, peg_rev, force, 609 ignore_externals, depth, native_eol, self) 610 end 611 612 def ls(path_or_uri, rev=nil, peg_rev=nil, recurse=false) 613 rev ||= URI(path_or_uri).scheme ? "HEAD" : "BASE" 614 peg_rev ||= rev 615 Client.ls3(path_or_uri, rev, peg_rev, recurse, self) 616 end 617 618 # Invokes block once for each path below +path_or_uri+ at +rev+ 619 # and returns +nil+. 620 # +path+ is a relative path from the +path_or_uri+. 621 # +dirent+ is an instance of Svn::Core::Dirent. 622 # +abs_path+ is an absolute path for +path_or_uri+ in the repository. 623 def list(path_or_uri, rev, peg_rev=nil, depth_or_recurse=Core::DEPTH_IMMEDIATES, 624 dirent_fields=nil, fetch_locks=true, 625 &block) # :yields: path, dirent, lock, abs_path 626 depth = Core::Depth.infinity_or_immediates_from_recurse(depth_or_recurse) 627 dirent_fields ||= Core::DIRENT_ALL 628 Client.list2(path_or_uri, peg_rev, rev, depth, dirent_fields, 629 fetch_locks, block, self) 630 end 631 632 def switch(path, uri, peg_rev=nil, rev=nil, depth=nil, 633 ignore_externals=false, allow_unver_obstruction=false, 634 depth_is_sticky=false) 635 636 Client.switch2(path, uri, peg_rev, rev, depth, depth_is_sticky, 637 ignore_externals, allow_unver_obstruction, self) 638 end 639 640 def set_log_msg_func(&callback) 641 callback_wrapper = Proc.new do |items| 642 items = items.collect do |item| 643 item_wrapper = CommitItemWrapper.new(item) 644 end 645 callback.call(items) 646 end 647 set_log_msg_func2(&callback_wrapper) 648 end 649 650 def set_log_msg_func2(&callback) 651 @log_msg_baton = Client.set_log_msg_func3(self, callback) 652 end 653 654 def set_notify_func(&callback) 655 @notify_baton = Client.set_notify_func2(self, callback) 656 end 657 658 def set_cancel_func(&callback) 659 @cancel_baton = Client.set_cancel_func(self, callback) 660 end 661 662 def config=(new_config) 663 Client.set_config(self, new_config) 664 end 665 666 def config 667 Client.get_config(self) 668 end 669 670 def merged(path_or_url, peg_revision=nil) 671 info = Client.mergeinfo_get_merged(path_or_url, peg_revision, self) 672 return nil if info.nil? 673 Core::MergeInfo.new(info) 674 end 675 676 def log_merged(path_or_url, peg_revision, merge_source_url, 677 source_peg_revision, discover_changed_path=true, 678 interested_revision_prop_names=nil, 679 &receiver) 680 raise ArgumentError, "Block isn't given" if receiver.nil? 681 Client.mergeinfo_log_merged(path_or_url, peg_revision, 682 merge_source_url, source_peg_revision, 683 receiver, discover_changed_path, 684 interested_revision_prop_names, 685 self) 686 end 687 688 def add_to_changelist(changelist_name, paths, depth=nil, changelists_names=nil) 689 paths = [paths] unless paths.is_a?(Array) 690 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 691 Client.add_to_changelist(paths, changelist_name, depth, changelists_names, self) 692 end 693 694 def changelists(changelists_names, root_path, depth=nil, &block) 695 lists_contents = Hash.new{|h,k| h[k]=[]} 696 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 697 block ||= lambda{|path, changelist| lists_contents[changelist] << path } 698 Client.get_changelists(root_path, changelists_names, depth, block, self) 699 lists_contents 700 end 701 702 def remove_from_changelists(changelists_names, paths, depth=nil) 703 changelists_names = [changelists_names] unless changelists_names.is_a?(Array) or changelists_names.nil? 704 paths = [paths] unless paths.is_a?(Array) 705 Client.remove_from_changelists(paths, depth, changelists_names, self) 706 end 707 708 private 709 def init_callbacks 710 set_log_msg_func 711 set_notify_func 712 set_cancel_func 713 end 714 %w(log_msg notify cancel).each do |type| 715 private "#{type}_func", "#{type}_baton" 716 private "#{type}_func=", "#{type}_baton=" 717 end 718 %w(notify).each do |type| 719 private "#{type}_func2", "#{type}_baton2" 720 private "#{type}_func2=", "#{type}_baton2=" 721 end 722 723 def normalize_path(paths) 724 paths = [paths] unless paths.is_a?(Array) 725 paths.collect do |path| 726 path.chomp(File::SEPARATOR) 727 end 728 end 729 end 730 731 # Following methods are also available: 732 # 733 # [path] 734 # Returns a path concerned with the instance. 735 # [prop_changed?] 736 # Returns +true+ when the instance is a change involving a property 737 # change. 738 class DiffSummarize 739 alias prop_changed? prop_changed 740 741 # Returns +true+ when the instance is a normal change. 742 def kind_normal? 743 summarize_kind == DIFF_SUMMARIZE_KIND_NORMAL 744 end 745 746 # Returns +true+ when the instance is a change involving addition. 747 def kind_added? 748 summarize_kind == DIFF_SUMMARIZE_KIND_ADDED 749 end 750 751 # Returns +true+ when the instance is a change involving modification. 752 def kind_modified? 753 summarize_kind == DIFF_SUMMARIZE_KIND_MODIFIED 754 end 755 756 # Returns +true+ when the instance is a change involving deletion. 757 def kind_deleted? 758 summarize_kind == DIFF_SUMMARIZE_KIND_DELETED 759 end 760 761 # Returns +true+ when the instance is a change made to no node. 762 def node_kind_none? 763 node_kind == Core::NODE_NONE 764 end 765 766 # Returns +true+ when the instance is a change made to a file node. 767 def node_kind_file? 768 node_kind == Core::NODE_FILE 769 end 770 771 # Returns +true+ when the instance is a change made to a directory node. 772 def node_kind_dir? 773 node_kind == Core::NODE_DIR 774 end 775 776 # Returns +true+ when the instance is a change made to an unknown node. 777 def node_kind_unknown? 778 node_kind == Core::NODE_UNKNOWN 779 end 780 end 781 782 class CopySource 783 alias_method :_initialize, :initialize 784 private :_initialize 785 def initialize(path, rev=nil, peg_rev=nil) 786 _initialize(path, rev, peg_rev) 787 end 788 end 789 end 790end 791