Fix compiler warning due to missing function prototype.
[svn.git] / subversion / bindings / swig / ruby / svn / core.rb
blobbab0f148257568d0db663b1382b6eb7766fdfa67
1 require "English"
2 require "time"
3 require "stringio"
4 require "tempfile"
5 require "svn/util"
6 require "svn/error"
7 require "svn/ext/core"
9 class Time
10   MILLION = 1_000_000
12   class << self
13     def from_apr_time(apr_time)
14       return apr_time if apr_time.is_a?(Time)
15       sec, usec = apr_time.divmod(MILLION)
16       Time.at(sec, usec)
17     end
19     def from_svn_format(str)
20       return nil if str.nil?
21       return str if str.is_a?(Time)
22       from_apr_time(Svn::Core.time_from_cstring(str))
23     end
25     def parse_svn_format(str)
26       return str if str.is_a?(Time)
27       matched, result = Svn::Core.parse_date(str, Time.now.to_apr_time)
28       if matched
29         from_apr_time(result)
30       else
31         nil
32       end
33     end
34   end
36   def to_apr_time
37     to_i * MILLION + usec
38   end
40   def to_svn_format
41     Svn::Core.time_to_cstring(self.to_apr_time)
42   end
44   def to_svn_human_format
45     Svn::Core.time_to_human_cstring(self.to_apr_time)
46   end
47 end
49 module Svn
50   module Core
51     Util.set_constants(Ext::Core, self)
52     Util.set_methods(Ext::Core, self)
54     nls_init
55     Util.reset_message_directory
57     # for backward compatibility
58     SWIG_INVALID_REVNUM = INVALID_REVNUM
59     SWIG_IGNORED_REVNUM = IGNORED_REVNUM
61     class << self
62       alias binary_mime_type? mime_type_is_binary
63       alias prop_diffs2 prop_diffs
65       def prop_diffs(target_props, source_props)
66         Property.prop_diffs(target_props, source_props)
67       end
68     end
71     DEFAULT_CHARSET = default_charset
72     LOCALE_CHARSET = locale_charset
74     AuthCredSSLClientCert = AuthCredSslClientCert
75     AuthCredSSLClientCertPw = AuthCredSslClientCertPw
76     AuthCredSSLServerTrust = AuthCredSslServerTrust
78     dirent_all = 0
79     constants.each do |name|
80       dirent_all |= const_get(name) if /^DIRENT_/ =~ name
81     end
82     DIRENT_ALL = dirent_all
84     Pool = Svn::Ext::Core::Apr_pool_wrapper_t
86     class Pool
87       class << self
88         def number_of_pools
89           ObjectSpace.each_object(Pool) {}
90         end
91       end
93       alias _initialize initialize
94       private :_initialize
95       def initialize(parent=nil)
96         _initialize(parent)
97         @parent = parent
98       end
100       def destroy
101         @parent = nil
102         _destroy
103       end
104       private :_destroy
105     end
107     class Stream
108       if Core.const_defined?(:STREAM_CHUNK_SIZE)
109         CHUNK_SIZE = Core::STREAM_CHUNK_SIZE
110       else
111         CHUNK_SIZE = 8192
112       end
114       def write(data)
115         Core.stream_write(self, data)
116       end
118       def read(len=nil)
119         if len.nil?
120           read_all
121         else
122           buf = ""
123           while len > CHUNK_SIZE
124             buf << _read(CHUNK_SIZE)
125             len -= CHUNK_SIZE
126           end
127           buf << _read(len)
128           buf
129         end
130       end
132       def close
133         Core.stream_close(self)
134       end
136       def copy(other, &cancel_proc)
137         Core.stream_copy2(self, other, cancel_proc)
138       end
140       private
141       def _read(size)
142         Core.stream_read(self, size)
143       end
145       def read_all
146         buf = ""
147         while chunk = _read(CHUNK_SIZE)
148           buf << chunk
149         end
150         buf
151       end
152     end
155     class AuthBaton
156       attr_reader :providers, :parameters
158       alias _initialize initialize
159       private :_initialize
160       def initialize(providers=[], parameters={})
161         _initialize(providers)
162         @providers = providers
163         self.parameters = parameters
164       end
166       def [](name)
167         Core.auth_get_parameter(self, name)
168       end
170       def []=(name, value)
171         Core.auth_set_parameter(self, name, value)
172         @parameters[name] = value
173       end
175       def parameters=(params)
176         @parameters = {}
177         params.each do |key, value|
178           self[key] = value
179         end
180       end
181     end
183     module Authenticatable
184       attr_accessor :auth_baton
186       def add_simple_provider
187         add_provider(Core.auth_get_simple_provider)
188       end
190       if Core.respond_to?(:auth_get_windows_simple_provider)
191         def add_windows_simple_provider
192           add_provider(Core.auth_get_windows_simple_provider)
193         end
194       end
196       if Core.respond_to?(:auth_get_keychain_simple_provider)
197         def add_keychain_simple_provider
198           add_provider(Core.auth_get_keychain_simple_provider)
199         end
200       end
202       def add_username_provider
203         add_provider(Core.auth_get_username_provider)
204       end
206       def add_ssl_client_cert_file_provider
207         add_provider(Core.auth_get_ssl_client_cert_file_provider)
208       end
210       def add_ssl_client_cert_pw_file_provider
211         add_provider(Core.auth_get_ssl_client_cert_pw_file_provider)
212       end
214       def add_ssl_server_trust_file_provider
215         add_provider(Core.auth_get_ssl_server_trust_file_provider)
216       end
218       if Core.respond_to?(:auth_get_windows_ssl_server_trust_provider)
219         def add_windows_ssl_server_trust_provider
220           add_provider(Core.auth_get_windows_ssl_server_trust_provider)
221         end
222       end
224       def add_simple_prompt_provider(retry_limit, prompt=Proc.new)
225         args = [retry_limit]
226         klass = AuthCredSimple
227         add_prompt_provider("simple", args, prompt, klass)
228       end
230       def add_username_prompt_provider(retry_limit, prompt=Proc.new)
231         args = [retry_limit]
232         klass = AuthCredUsername
233         add_prompt_provider("username", args, prompt, klass)
234       end
236       def add_ssl_server_trust_prompt_provider(prompt=Proc.new)
237         args = []
238         klass = AuthCredSSLServerTrust
239         add_prompt_provider("ssl_server_trust", args, prompt, klass)
240       end
242       def add_ssl_client_cert_prompt_provider(retry_limit, prompt=Proc.new)
243         args = [retry_limit]
244         klass = AuthCredSSLClientCert
245         add_prompt_provider("ssl_client_cert", args, prompt, klass)
246       end
248       def add_ssl_client_cert_pw_prompt_provider(retry_limit, prompt=Proc.new)
249         args = [retry_limit]
250         klass = AuthCredSSLClientCertPw
251         add_prompt_provider("ssl_client_cert_pw", args, prompt, klass)
252       end
254       private
255       def add_prompt_provider(name, args, prompt, credential_class)
256         real_prompt = Proc.new do |*prompt_args|
257           credential = credential_class.new
258           prompt.call(credential, *prompt_args)
259           credential
260         end
261         method_name = "swig_rb_auth_get_#{name}_prompt_provider"
262         baton, provider = Core.send(method_name, real_prompt, *args)
263         provider.instance_variable_set("@baton", baton)
264         provider.instance_variable_set("@prompt", real_prompt)
265         add_provider(provider)
266       end
268       def add_provider(provider)
269         if auth_baton
270           providers = auth_baton.providers
271           parameters = auth_baton.parameters
272         else
273           providers = []
274           parameters = {}
275         end
276         self.auth_baton = AuthBaton.new(providers + [provider], parameters)
277       end
278     end
280     class AuthProviderObject
281       class << self
282         undef new
283       end
284     end
287     Diff = SWIG::TYPE_p_svn_diff_t
288     class Diff
289       attr_accessor :original, :modified, :latest, :ancestor
291       class << self
292         def version
293           Core.diff_version
294         end
296         def file_diff(original, modified, options=nil)
297           options ||= Core::DiffFileOptions.new
298           diff = Core.diff_file_diff_2(original, modified, options)
299           if diff
300             diff.original = original
301             diff.modified = modified
302           end
303           diff
304         end
306         def file_diff3(original, modified, latest, options=nil)
307           options ||= Core::DiffFileOptions.new
308           diff = Core.diff_file_diff3_2(original, modified, latest, options)
309           if diff
310             diff.original = original
311             diff.modified = modified
312             diff.latest = latest
313           end
314           diff
315         end
317         def file_diff4(original, modified, latest, ancestor, options=nil)
318           options ||= Core::DiffFileOptions.new
319           args = [original, modified, latest, ancestor, options]
320           diff = Core.diff_file_diff4_2(*args)
321           if diff
322             diff.original = original
323             diff.modified = modified
324             diff.latest = latest
325             diff.ancestor = ancestor
326           end
327           diff
328         end
329       end
331       def unified(orig_label, mod_label, header_encoding=nil)
332         header_encoding ||= Svn::Core.locale_charset
333         output = StringIO.new
334         args = [
335           output, self, @original, @modified,
336           orig_label, mod_label, header_encoding
337         ]
338         Core.diff_file_output_unified2(*args)
339         output.rewind
340         output.read
341       end
343       def merge(conflict_original=nil, conflict_modified=nil,
344                 conflict_latest=nil, conflict_separator=nil,
345                 display_original_in_conflict=true,
346                 display_resolved_conflicts=true)
347         header_encoding ||= Svn::Core.locale_charset
348         output = StringIO.new
349         args = [
350           output, self, @original, @modified, @latest,
351           conflict_original, conflict_modified,
352           conflict_latest, conflict_separator,
353           display_original_in_conflict,
354           display_resolved_conflicts,
355         ]
356         Core.diff_file_output_merge(*args)
357         output.rewind
358         output.read
359       end
361       def conflict?
362         Core.diff_contains_conflicts(self)
363       end
365       def diff?
366         Core.diff_contains_diffs(self)
367       end
368     end
370     class DiffFileOptions
371       class << self
372         def parse(*args)
373           options = new
374           options.parse(*args)
375           options
376         end
377       end
379       def parse(*args)
380         args = args.first if args.size == 1 and args.first.is_a?(Array)
381         Svn::Core.diff_file_options_parse(self, args)
382       end
383     end
385     class Version
387       alias _initialize initialize
388       def initialize(major=nil, minor=nil, patch=nil, tag=nil)
389         _initialize
390         self.major = major if major
391         self.minor = minor if minor
392         self.patch = patch if patch
393         self.tag = tag || ""
394       end
396       def ==(other)
397         valid? and other.valid? and Core.ver_equal(self, other)
398       end
400       def compatible?(other)
401         valid? and other.valid? and Core.ver_compatible(self, other)
402       end
404       def valid?
405         (major and minor and patch and tag) ? true : false
406       end
408       alias _tag= tag=
409       def tag=(value)
410         @tag = value
411         self._tag = value
412       end
414       def to_a
415         [major, minor, patch, tag]
416       end
418       def to_s
419         "#{major}.#{minor}.#{patch}#{tag}"
420       end
421     end
423     # Following methods are also available:
424     #
425     # [created_rev]
426     #   Returns a revision at which the instance was last modified.
427     # [have_props?]
428     #   Returns +true+ if the instance has properties.
429     # [last_author]
430     #   Returns an author who last modified the instance.
431     # [size]
432     #   Returns a size of the instance.
433     class Dirent
434       alias have_props? has_props
436       # Returns +true+ when the instance is none.
437       def none?
438         kind == NODE_NONE
439       end
441       # Returns +true+ when the instance is a directory.
442       def directory?
443         kind == NODE_DIR
444       end
446       # Returns +true+ when the instance is a file.
447       def file?
448         kind == NODE_FILE
449       end
451       # Returns +true+ when the instance is an unknown node.
452       def unknown?
453         kind == NODE_UNKNOWN
454       end
456       # Returns a Time when the instance was last changed.
457       #
458       # Svn::Core::Dirent#time is replaced by this method, _deprecated_,
459       # and provided for backward compatibility with the 1.3 API.
460       def time2
461         __time = time
462         __time && Time.from_apr_time(__time)
463       end
464     end
466     Config = SWIG::TYPE_p_svn_config_t
468     class Config
469       include Enumerable
471       class << self
472         def get(path=nil)
473           Core.config_get_config(path)
474         end
475         alias config get
477         def read(file, must_exist=true)
478           Core.config_read(file, must_exist)
479         end
481         def ensure(dir)
482           Core.config_ensure(dir)
483         end
485         def read_auth_data(cred_kind, realm_string, config_dir=nil)
486           Core.config_read_auth_data(cred_kind, realm_string, config_dir)
487         end
489         def write_auth_data(hash, cred_kind, realm_string, config_dir=nil)
490           Core.config_write_auth_data(hash, cred_kind,
491                                       realm_string, config_dir)
492         end
493       end
495       def merge(file, must_exist=true)
496         Core.config_merge(self, file, must_exist)
497       end
499       def get(section, option, default=nil)
500         Core.config_get(self, section, option, default)
501       end
503       def get_bool(section, option, default)
504         Core.config_get_bool(self, section, option, default)
505       end
507       def set(section, option, value)
508         Core.config_set(self, section, option, value)
509       end
510       alias_method :[]=, :set
512       def set_bool(section, option, value)
513         Core.config_set_bool(self, section, option, value)
514       end
516       def each
517         each_section do |section|
518           each_option(section) do |name, value|
519             yield(section, name, value)
520             true
521           end
522           true
523         end
524       end
526       def each_option(section)
527         receiver = Proc.new do |name, value|
528           yield(name, value)
529         end
530         Core.config_enumerate2(self, section, receiver)
531       end
533       def each_section
534         receiver = Proc.new do |name|
535           yield(name)
536         end
537         Core.config_enumerate_sections2(self, receiver)
538       end
540       def find_group(key, section)
541         Core.config_find_group(self, key, section)
542       end
544       def get_server_setting(group, name, default=nil)
545         Core.config_get_server_setting(self, group, name, default)
546       end
548       def get_server_setting_int(group, name, default)
549         Core.config_get_server_setting_int(self, group, name, default)
550       end
552       alias_method :_to_s, :to_s
553       def to_s
554         result = ""
555         each_section do |section|
556           result << "[#{section}]\n"
557           each_option(section) do |name, value|
558             result << "#{name} = #{value}\n"
559           end
560           result << "\n"
561         end
562         result
563       end
565       def inspect
566         "#{_to_s}#{to_hash.inspect}"
567       end
569       def to_hash
570         sections = {}
571         each do |section, name, value|
572           sections[section] ||= {}
573           sections[section][name] = value
574         end
575         sections
576       end
578       def ==(other)
579         other.is_a?(self.class) and to_hash == other.to_hash
580       end
581     end
583     module Property
584       module_function
585       def kind(name)
586         kind, len = Core.property_kind(name)
587         [kind, name[0...len]]
588       end
590       def svn_prop?(name)
591         Core.prop_is_svn_prop(name)
592       end
594       def needs_translation?(name)
595         Core.prop_needs_translation(name)
596       end
598       def categorize(props)
599         categorize2(props).collect do |categorized_props|
600           Util.hash_to_prop_array(categorized_props)
601         end
602       end
603       alias_method :categorize_props, :categorize
604       module_function :categorize_props
606       def categorize2(props)
607         Core.categorize_props(props)
608       end
610       def diffs(target_props, source_props)
611         Util.hash_to_prop_array(diffs2(target_props, source_props))
612       end
613       alias_method :prop_diffs, :diffs
614       module_function :prop_diffs
616       def diffs2(target_props, source_props)
617         Core.prop_diffs2(target_props, source_props)
618       end
620       def has_svn_prop?(props)
621         Core.prop_has_svn_prop(props)
622       end
623       alias_method :have_svn_prop?, :has_svn_prop?
624       module_function :have_svn_prop?
626       def valid_name?(name)
627         Core.prop_name_is_valid(name)
628       end
629     end
631     module Depth
632       module_function
633       def from_string(str)
634         return nil if str.nil?
635         Core.depth_from_word(str)
636       end
638       def to_string(depth)
639         Core.depth_to_word(depth)
640       end
642       def infinity_or_empty_from_recurse(depth_or_recurse)
643         case depth_or_recurse
644           when true  : DEPTH_INFINITY
645           when false : DEPTH_EMPTY
646           else depth_or_recurse
647         end
648       end
650       def infinity_or_immediates_from_recurse(depth_or_recurse)
651         case depth_or_recurse
652           when true  : DEPTH_INFINITY
653           when false : DEPTH_IMMEDIATES
654           else depth_or_recurse
655         end
656       end
657     end
659     module MimeType
660       module_function
661       def parse(source)
662         file = Tempfile.new("svn-ruby-mime-type")
663         file.print(source)
664         file.close
665         Core.io_parse_mimetypes_file(file.path)
666       end
668       def parse_file(path)
669         Core.io_parse_mimetypes_file(path)
670       end
672       def detect(path, type_map={})
673         Core.io_detect_mimetype2(path, type_map)
674       end
675     end
677     class CommitInfo
678       alias _date date
679       def date
680         Time.from_svn_format(_date)
681       end
682     end
684     # Following methods are also available:
685     #
686     # [action]
687     #   Returns an action taken to the path at the revision.
688     # [copyfrom_path]
689     #   If the path was added at the revision by the copy action from
690     #   another path at another revision, returns an original path.
691     #   Otherwise, returns +nil+.
692     # [copyfrom_rev]
693     #   If the path was added at the revision by the copy action from
694     #   another path at another revision, returns an original revision.
695     #   Otherwise, returns <tt>-1</tt>.
696     class LogChangedPath
697       # Returns +true+ when the path is added by the copy action.
698       def copied?
699         Util.copy?(copyfrom_path, copyfrom_rev)
700       end
701     end
703     # For backward compatibility
704     class Prop
705       attr_accessor :name, :value
706       def initialize(name, value)
707         @name = name
708         @value = value
709       end
711       def ==(other)
712         other.is_a?(self.class) and
713           [@name, @value] == [other.name, other.value]
714       end
715     end
717     class MergeRange
718       def to_a
719         [self.start, self.end, self.inheritable]
720       end
722       def inspect
723         super.gsub(/>$/, ":#{to_a.inspect}>")
724       end
726       def ==(other)
727         to_a == other.to_a
728       end
729     end
731     class MergeInfo < Hash
732       class << self
733         def parse(input)
734           new(Core.mergeinfo_parse(input))
735         end
736       end
738       def initialize(info)
739         super()
740         info.each do |path, ranges|
741           self[path] = RangeList.new(*ranges)
742         end
743       end
745       def diff(to, consider_inheritance=nil)
746         Core.mergeinfo_diff(self, to, consider_inheritance).collect do |result|
747           self.class.new(result)
748         end
749       end
751       def merge(changes)
752         self.class.new(Core.swig_mergeinfo_merge(self, changes))
753       end
755       def remove(eraser)
756         self.class.new(Core.mergeinfo_remove(eraser, self))
757       end
759       def sort
760         self.class.new(Core.swig_mergeinfo_sort(self))
761       end
763       def to_s
764         Core.mergeinfo_to_string(self)
765       end
766     end
768     class RangeList < Array
769       def initialize(*ranges)
770         super()
771         ranges.each do |range|
772           self << Svn::Core::MergeRange.new(*range.to_a)
773         end
774       end
776       def diff(to, consider_inheritance=nil)
777         result = Core.rangelist_diff(self, to, consider_inheritance)
778         deleted = result.pop
779         added = result
780         [added, deleted].collect do |result|
781           self.class.new(*result)
782         end
783       end
785       def merge(changes)
786         self.class.new(*Core.swig_rangelist_merge(self, changes))
787       end
789       def remove(eraser, consider_inheritance=nil)
790         self.class.new(*Core.rangelist_remove(eraser, self, consider_inheritance))
791       end
793       def intersect(other)
794         self.class.new(*Core.rangelist_intersect(self, other))
795       end
797       def reverse
798         self.class.new(*Core.swig_rangelist_reverse(self))
799       end
801       def to_s
802         Core.rangelist_to_string(self)
803       end
804     end
806     class LogEntry
807       alias_method(:revision_properties, :revprops)
808       alias_method(:has_children?, :has_children)
809       undef_method(:has_children)
810     end
811   end