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