vcs 0.2.148 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/AUTHORS +6 -0
  2. data/NEWS +9 -0
  3. data/README +82 -0
  4. data/Rakefile +7 -72
  5. data/SPEC.dyn.yml +10 -0
  6. data/SPEC.gemspec +14 -0
  7. data/SPEC.yml +39 -0
  8. data/bin/vcs +18 -16
  9. data/lib/vcs/changelog.rb +164 -0
  10. data/lib/vcs/conflict.rb +21 -0
  11. data/{src → lib/vcs}/cvs.rb +1 -1
  12. data/{src → lib/vcs}/diff.rb +2 -2
  13. data/lib/vcs/diffstat.rb +28 -0
  14. data/lib/vcs/edit.rb +16 -0
  15. data/{src → lib/vcs}/last_changed_date.rb +3 -5
  16. data/{src → lib/vcs}/mail.rb +4 -4
  17. data/lib/vcs/message.rb +79 -0
  18. data/{src → lib/vcs}/mycommit.rb +15 -15
  19. data/{src → lib/vcs}/news.rb +6 -6
  20. data/{src → lib/vcs}/prcs.rb +1 -1
  21. data/{src → lib/vcs}/revision.rb +3 -4
  22. data/lib/vcs/script.rb +19 -0
  23. data/{src → lib/vcs}/status.rb +1 -1
  24. data/{src → lib/vcs}/svn.rb +3 -5
  25. data/lib/vcs/url.rb +16 -0
  26. data/lib/vcs/vcs.rb +279 -0
  27. metadata +52 -150
  28. data/TODO +0 -19
  29. data/doc/jamis.rb +0 -564
  30. data/ruby_ex/abstract.rb +0 -254
  31. data/ruby_ex/abstract_node.rb +0 -85
  32. data/ruby_ex/algorithms/simulated_annealing.rb +0 -140
  33. data/ruby_ex/array_each_pair.rb +0 -18
  34. data/ruby_ex/ask.rb +0 -101
  35. data/ruby_ex/attributed_class.rb +0 -302
  36. data/ruby_ex/cache.rb +0 -373
  37. data/ruby_ex/checkout.rb +0 -12
  38. data/ruby_ex/choose.rb +0 -271
  39. data/ruby_ex/commands.rb +0 -18
  40. data/ruby_ex/commands/command.rb +0 -401
  41. data/ruby_ex/commands/datas.rb +0 -16
  42. data/ruby_ex/commands/datas/data.rb +0 -33
  43. data/ruby_ex/commands/datas/factory.rb +0 -66
  44. data/ruby_ex/commands/factory.rb +0 -66
  45. data/ruby_ex/commands/helpers.rb +0 -67
  46. data/ruby_ex/commands/pipe.rb +0 -64
  47. data/ruby_ex/commands/runners.rb +0 -17
  48. data/ruby_ex/commands/runners/exec.rb +0 -49
  49. data/ruby_ex/commands/runners/fork.rb +0 -97
  50. data/ruby_ex/commands/runners/runner.rb +0 -107
  51. data/ruby_ex/commands/seq.rb +0 -27
  52. data/ruby_ex/config_file.rb +0 -96
  53. data/ruby_ex/const_regexp.rb +0 -59
  54. data/ruby_ex/daemon.rb +0 -134
  55. data/ruby_ex/diff.rb +0 -667
  56. data/ruby_ex/dlogger.rb +0 -62
  57. data/ruby_ex/drb/dispatcher.rb +0 -252
  58. data/ruby_ex/drb/dispatcher_server_test.rb +0 -29
  59. data/ruby_ex/drb/drb_observable.rb +0 -97
  60. data/ruby_ex/drb/drb_observable_pool.rb +0 -27
  61. data/ruby_ex/drb/drb_service.rb +0 -43
  62. data/ruby_ex/drb/drb_undumped_attributes.rb +0 -55
  63. data/ruby_ex/drb/drb_undumped_indexed_object.rb +0 -54
  64. data/ruby_ex/drb/insecure_protected_methods.rb +0 -103
  65. data/ruby_ex/drb/session_client_test.rb +0 -40
  66. data/ruby_ex/drb/session_manager.rb +0 -246
  67. data/ruby_ex/drb/session_server.rb +0 -53
  68. data/ruby_ex/dtime.rb +0 -143
  69. data/ruby_ex/dumpable_proc.rb +0 -63
  70. data/ruby_ex/exception.rb +0 -32
  71. data/ruby_ex/filetype.rb +0 -229
  72. data/ruby_ex/fileutils_ex.rb +0 -44
  73. data/ruby_ex/fold.rb +0 -58
  74. data/ruby_ex/generate_id.rb +0 -44
  75. data/ruby_ex/hookable.rb +0 -262
  76. data/ruby_ex/hooker.rb +0 -54
  77. data/ruby_ex/inactive_timeout.rb +0 -137
  78. data/ruby_ex/indexed_node.rb +0 -66
  79. data/ruby_ex/io_marshal.rb +0 -100
  80. data/ruby_ex/ioo.rb +0 -194
  81. data/ruby_ex/labeled_node.rb +0 -63
  82. data/ruby_ex/logger_observer.rb +0 -23
  83. data/ruby_ex/md5sum.rb +0 -66
  84. data/ruby_ex/mktemp.rb +0 -208
  85. data/ruby_ex/module/attr_once.rb +0 -36
  86. data/ruby_ex/module/autoload_tree.rb +0 -75
  87. data/ruby_ex/module/hierarchy.rb +0 -335
  88. data/ruby_ex/module/instance_method_visibility.rb +0 -73
  89. data/ruby_ex/module_ex.rb +0 -11
  90. data/ruby_ex/node.rb +0 -80
  91. data/ruby_ex/object_monitor.rb +0 -145
  92. data/ruby_ex/object_monitor_activity.rb +0 -33
  93. data/ruby_ex/observable.rb +0 -140
  94. data/ruby_ex/observable_pool.rb +0 -293
  95. data/ruby_ex/orderedhash.rb +0 -252
  96. data/ruby_ex/pathname_ex.rb +0 -152
  97. data/ruby_ex/pp_hierarchy.rb +0 -29
  98. data/ruby_ex/pseudo_cache.rb +0 -190
  99. data/ruby_ex/queue.rb +0 -56
  100. data/ruby_ex/random_generators.rb +0 -25
  101. data/ruby_ex/random_generators/random_generator.rb +0 -31
  102. data/ruby_ex/random_generators/ruby.rb +0 -23
  103. data/ruby_ex/safe_eval.rb +0 -348
  104. data/ruby_ex/sendmail.rb +0 -215
  105. data/ruby_ex/service_manager.rb +0 -121
  106. data/ruby_ex/session/administrable.rb +0 -120
  107. data/ruby_ex/session/client.rb +0 -153
  108. data/ruby_ex/session/const.rb +0 -18
  109. data/ruby_ex/session/dispatcher.rb +0 -184
  110. data/ruby_ex/session/error.rb +0 -21
  111. data/ruby_ex/session/fetchable.rb +0 -57
  112. data/ruby_ex/session/fetcher.rb +0 -62
  113. data/ruby_ex/session/hookable.rb +0 -26
  114. data/ruby_ex/session/profile.rb +0 -110
  115. data/ruby_ex/session/server.rb +0 -582
  116. data/ruby_ex/session/test/administrable_test.rb +0 -337
  117. data/ruby_ex/session/test/basic_test.rb +0 -523
  118. data/ruby_ex/session/test/dispatcher_test.rb +0 -409
  119. data/ruby_ex/session/test/fetchable_test.rb +0 -119
  120. data/ruby_ex/session/test/sub_server_test.rb +0 -188
  121. data/ruby_ex/shuffle.rb +0 -30
  122. data/ruby_ex/spring.rb +0 -136
  123. data/ruby_ex/spring_set.rb +0 -137
  124. data/ruby_ex/string_ex.rb +0 -28
  125. data/ruby_ex/symtbl.rb +0 -106
  126. data/ruby_ex/synflow.rb +0 -474
  127. data/ruby_ex/test/unit/ui/yaml/testrunner.rb +0 -164
  128. data/ruby_ex/thread_mutex.rb +0 -10
  129. data/ruby_ex/timeout_ex.rb +0 -81
  130. data/ruby_ex/top_down.rb +0 -73
  131. data/ruby_ex/trace.rb +0 -26
  132. data/ruby_ex/uri/druby.rb +0 -81
  133. data/ruby_ex/uri/file.rb +0 -65
  134. data/ruby_ex/uri/ftp_ex.rb +0 -37
  135. data/ruby_ex/uri/http_ex.rb +0 -43
  136. data/ruby_ex/uri/ssh.rb +0 -92
  137. data/ruby_ex/uri/svn.rb +0 -118
  138. data/ruby_ex/uri_ex.rb +0 -45
  139. data/ruby_ex/verbose_object.rb +0 -30
  140. data/ruby_ex/version.rb +0 -66
  141. data/ruby_ex/yaml/basenode_ext.rb +0 -63
  142. data/ruby_ex/yaml/chop_header.rb +0 -23
  143. data/ruby_ex/yaml/transform.rb +0 -449
  144. data/ruby_ex/yaml/yregexpath.rb +0 -76
  145. data/src/ask.rb +0 -101
  146. data/src/changelog.rb +0 -117
  147. data/src/conflict.rb +0 -20
  148. data/src/diffstat.rb +0 -42
  149. data/src/message.rb +0 -64
  150. data/src/reply-mail.rb +0 -14
  151. data/src/tools.rb +0 -22
  152. data/src/vcs.rb +0 -176
@@ -1,18 +0,0 @@
1
- # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
- # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
- # License: Gnu General Public License.
4
-
5
- # $LastChangedBy: polrop $
6
- # $Id: cache.rb 173 2005-03-29 09:41:46Z polrop $
7
-
8
-
9
- class Array
10
-
11
- # Basically, do the same as each_with_index but yield the arguments in
12
- # reverse order. Thus an array can be assume in certain cases to a hash.
13
- def each_pair(&block)
14
- each_with_index { |x, i| block[i, x] }
15
- end
16
-
17
- end # class Array
18
-
@@ -1,101 +0,0 @@
1
- # Author: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
- # Copyright: Copyright (c) 2004, 2005 Nicolas Pouillard. All rights reserved.
3
- # License: GNU General Public License (GPL).
4
-
5
- # $LastChangedBy: ertai $
6
- # $Id: ask.rb 187 2005-04-03 00:11:56Z ertai $
7
-
8
- ANSWERS = [ :y, :n ]
9
- ANSWER_NOT_VALID = 'Not a valid answer, please answer correctly'
10
-
11
- # `ask', ask the user to answer, to your question.
12
- #
13
- # Example:
14
- # ask('Commiting, are you sure', :n)
15
- #
16
- # produce => Commiting, are you sure (y/N):
17
- # and wait your answer.
18
- def ask ( aQuestion, theDefaultAnswer=:y, cin=STDIN, cout=STDOUT, cerr=STDERR )
19
-
20
- yn = case theDefaultAnswer
21
- when :y then ' [Y/n]: '
22
- when :n then ' [y/N]: '
23
- else raise ArgumentError, "not valid default answer #{theDefaultAnswer}"
24
- end
25
-
26
- loop do
27
- cout.print aQuestion, yn
28
- cout.flush
29
-
30
- answer = cin.readline.chomp.downcase
31
-
32
- return theDefaultAnswer if answer.empty?
33
-
34
- answer = answer.to_sym
35
-
36
- return answer if ANSWERS.include? answer
37
-
38
- cerr.puts ANSWER_NOT_VALID
39
- cout.puts
40
- end
41
-
42
- end
43
-
44
- if defined? TEST_MODE or $0 == __FILE__
45
-
46
- require 'test/unit'
47
- class AskTest < Test::Unit::TestCase
48
-
49
- def ask_checker ( question, default, answer, ref, out, err )
50
- require 'stringio'
51
- cin, cout, cerr = StringIO.new, StringIO.new, StringIO.new
52
- cin.puts answer
53
- cin.rewind
54
- res = ask(question, default, cin, cout, cerr)
55
- cout.rewind
56
- cerr.rewind
57
- assert_equal(res, ref, 'bad return value')
58
- assert_equal(cout.readlines.join, out, 'bad standard output')
59
- assert_equal(cerr.readlines.join, err, 'bad error output')
60
- end
61
-
62
- def test_bad_default
63
- assert_raise(ArgumentError) { ask_checker('Q', :foo, '', :y, [], []) }
64
- assert_nothing_raised do
65
- ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
66
- end
67
- assert_nothing_raised do
68
- ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '')
69
- end
70
- end
71
-
72
- def test_valid_default_yes
73
- ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
74
- ask_checker('Q', :y, 'Y', :y, 'Q [Y/n]: ', '')
75
- ask_checker('Q', :y, 'n', :n, 'Q [Y/n]: ', '')
76
- ask_checker('Q', :y, 'N', :n, 'Q [Y/n]: ', '')
77
- ask_checker('Q', :y, '', :y, 'Q [Y/n]: ', '')
78
- end
79
-
80
- def test_valid_default_no
81
- ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '')
82
- ask_checker('Q', :n, 'Y', :y, 'Q [y/N]: ', '')
83
- ask_checker('Q', :n, 'n', :n, 'Q [y/N]: ', '')
84
- ask_checker('Q', :n, 'N', :n, 'Q [y/N]: ', '')
85
- ask_checker('Q', :n, '', :n, 'Q [y/N]: ', '')
86
- end
87
-
88
- def test_invalid_answer
89
- ask_checker('Q', :n, "bad\ny", :y,
90
- "Q [y/N]: \nQ [y/N]: ", ANSWER_NOT_VALID + "\n")
91
- ask_checker('Q', :y, "ad\n\n", :y,
92
- "Q [Y/n]: \nQ [Y/n]: ", ANSWER_NOT_VALID + "\n")
93
- end
94
-
95
- def test_ask1
96
- ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
97
- end
98
-
99
- end # class AskTest
100
-
101
- end
@@ -1,302 +0,0 @@
1
- # Copyright:: Copyright (c) 2004, 2005 Nicolas Pouillard. All rights reserved.
2
- # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
3
- # License:: Gnu General Public License.
4
- # Revision:: $Id: attributed_class.rb 212 2005-05-05 20:07:23Z ertai $
5
-
6
-
7
- # Extension to have inherited, class attributes,
8
- # Where each class have his own attributes set.
9
- module AttributedClass
10
-
11
- class Attribute
12
-
13
- attr_reader :name, :descr, :klass, :default_proc
14
- attr_accessor :default
15
-
16
- @@default_proc = nil
17
-
18
- def initialize ( name, descr, *args, &block )
19
- raise ArgumentError, 'need a symbol' unless name.is_a? Symbol
20
- @name, @descr = name, descr
21
- @default, @klass = nil, nil
22
- @mandatory = false
23
- @visible = true
24
- if block_given?
25
- @default_proc = block
26
- else
27
- @default_proc = @@default_proc
28
- end
29
- other = []
30
-
31
- args.each do |arg|
32
- case arg
33
- when :mandatory then @mandatory = true
34
- when :invisible then @visible = false
35
- else other << arg
36
- end
37
- end
38
-
39
- case other.size
40
- when 1
41
- if other[0].is_a? Class
42
- @klass = [other[0]]
43
- elsif other[0].is_a? Array and other[0].all? { |k| k.is_a? Class }
44
- @klass = other[0]
45
- else
46
- @default = other[0]
47
- end
48
- when 2
49
- a, b = other
50
- if a.is_a? Class and b.is_a? a
51
- @klass, @default = [a], b
52
- elsif a.is_a? Array and
53
- a.all? { |k| k.is_a? Class } and
54
- a.any? { |k| b.is_a? k }
55
- @klass, @default = a, b
56
- elsif b.is_a? Class and a.is_a? b
57
- @klass, @default = [b], a
58
- elsif b.is_a? Array and
59
- b.all? { |k| k.is_a? Class } and
60
- b.any? { |k| a.is_a? k }
61
- @klass, @default = b, a
62
- else
63
- raise ArgumentError, 'need a Class and a default value'
64
- end
65
- when 0
66
- else raise ArgumentError, 'too many values'
67
- end
68
-
69
- # removed because it causes some probleme when distributed such a class
70
- #[@name, @descr, @default].each { |x| x.freeze }
71
- end
72
-
73
- def visible?
74
- @visible
75
- end
76
-
77
- def invisible?
78
- !@visible
79
- end
80
-
81
- def mandatory?
82
- @mandatory
83
- end
84
-
85
- def valid? ( anObject )
86
- return false if mandatory? and anObject.nil?
87
- @klass.nil? or @klass.empty? or @klass.any? { |k| anObject.is_a? k }
88
- end
89
-
90
-
91
- def self.set_default_proc ( &block )
92
- @@default_proc = block
93
- end
94
-
95
-
96
- def help ( output=STDERR )
97
- output << "#@name: #@descr"
98
- output << " [#@klass]" unless @klass.nil?
99
- other = []
100
- other << 'mandatory' if mandatory?
101
- other << 'invisible' if invisible?
102
- output << " (#{other.join(', ')})" unless other.empty?
103
- output
104
- end
105
-
106
- def inspect
107
- help('#<') + '>'
108
- end
109
-
110
- end # class Attribute
111
-
112
-
113
- class MethodAttribute < Attribute
114
- VISIBILITIES = [ :private, :protected, :public, :unknown ]
115
- attr_reader :visibility
116
- def private?
117
- @visibility == :private
118
- end
119
- def protected?
120
- @visibility == :protected
121
- end
122
- def public?
123
- @visibility == :public
124
- end
125
- def initialize ( name, descr, *args )
126
- vis = args.find { |arg| VISIBILITIES.include? arg }
127
- args.delete(vis) unless vis.nil?
128
- @visibility = vis || :unknown
129
- super(name, descr, *args)
130
- end
131
- end # class MethodAttribute
132
-
133
-
134
- class AttributeError < Exception
135
-
136
- def initialize ( anObject, anAttr, val=nil )
137
- if val.nil?
138
- super "Missing the #{anAttr.name} attribute for `#{anObject}'"
139
- else
140
- super "Attribute #{anAttr.name} wait for a `#{anAttr.klass}' not " +
141
- "`#{val}' in #{anObject}"
142
- end
143
- end
144
-
145
- end # class AttributeError
146
-
147
-
148
- def self.included ( aClass )
149
-
150
- aClass.module_eval do
151
-
152
- def initialize_attributes ( *default_proc_args )
153
- self.class.attributes.each do |attr|
154
- next if attr.is_a? MethodAttribute
155
- if attr.default_proc.nil? and attr.default.nil?
156
- instance_variable_set("@#{attr.name}", nil)
157
- else
158
- unless attr.default_proc.nil?
159
- pr = attr.default_proc
160
- if pr.arity == default_proc_args.size
161
- default = pr[*default_proc_args]
162
- else
163
- default = pr[attr, *default_proc_args]
164
- end
165
- attr.default = default
166
- end
167
- send "#{attr.name}=", attr.default
168
- end
169
- end
170
- end
171
-
172
- def self.set_default_proc ( &block )
173
- Attribute.set_default_proc(&block)
174
- end
175
-
176
- def each_attribute ( &block )
177
- self.class.attributes.each do |attr|
178
- block[attr, send(attr.name)]
179
- end
180
- end
181
-
182
- def each_variable_attribute ( &block )
183
- self.class.attributes.each do |attr|
184
- next if attr.is_a? MethodAttribute
185
- block[attr, send(attr.name)]
186
- end
187
- end
188
-
189
- def each_method_attribute ( &block )
190
- self.class.attributes.each do |attr|
191
- next unless attr.is_a? MethodAttribute
192
- block[attr, send(attr.name)]
193
- end
194
- end
195
-
196
- def check_attribute ( attr, anObject )
197
- unless attr.valid? anObject
198
- raise AttributeError.new(self, attr, anObject)
199
- end
200
- end
201
-
202
- def check_attributes
203
- each_variable_attribute(&method(:check_attribute))
204
- end
205
-
206
- def self.help ( output=STDERR )
207
- output.puts "#{self.to_s}:"
208
- attributes.each do |attr|
209
- output << ' '
210
- attr.help(output)
211
- output.puts '.'
212
- end
213
- end
214
-
215
- def self.attributes
216
- unless defined? @attributes
217
- if superclass and superclass.respond_to? :attributes
218
- @attributes = superclass.attributes.dup
219
- else
220
- @attributes = []
221
- end
222
- end
223
- @attributes
224
- end
225
-
226
- def self.attribute ( name, descr, *args, &block )
227
- attr = Attribute.new(name, descr, *args, &block)
228
- unless method_defined? name
229
- if att = get_attribute(name, MethodAttribute)
230
- attributes.delete(att)
231
- end
232
- attr_reader name
233
- end
234
- meth = "#{name}="
235
- unless method_defined? meth
236
- if att = get_attribute(meth, MethodAttribute)
237
- attributes.delete(att)
238
- end
239
- attr_writer name
240
- end
241
- attributes << attr
242
- end
243
-
244
- def self.method_attribute ( name, descr, *args, &block )
245
- # unless method_defined? name
246
- # raise ArgumentError, "Undefined method #{name}"
247
- # end
248
- attr = MethodAttribute.new(name, descr, *args, &block)
249
- attributes << attr
250
- end
251
-
252
- def self.get_attribute ( name, type=nil )
253
- if type.nil?
254
- attributes.find { |attr| attr.name == name }
255
- else
256
- attributes.find { |attr| attr.name == name && attr.is_a?(type) }
257
- end
258
- end
259
-
260
- end
261
-
262
- end
263
-
264
- end # module AttributedClass
265
-
266
-
267
-
268
- if defined? TEST_MODE or $0 == __FILE__
269
-
270
- require 'test/unit'
271
- class AttributedClassTest < Test::Unit::TestCase
272
-
273
- def test_simple
274
- c = Class.new
275
- assert_nothing_raised do
276
- c.module_eval { include AttributedClass }
277
- end
278
- assert_equal([], c.attributes)
279
- assert_nothing_raised do
280
- c.module_eval { attribute :foo, 'foofoo', 42 }
281
- end
282
- cc, d, dd = nil, nil, nil
283
- assert_nothing_raised { cc = c.new }
284
- assert_equal(nil, cc.foo)
285
- assert_nothing_raised { cc.initialize_attributes }
286
- assert_equal(42, cc.foo)
287
- assert_nothing_raised { cc.foo = 32 }
288
- assert_equal(32, cc.foo)
289
- assert_nothing_raised { d = Class.new(c) }
290
- assert_nothing_raised do
291
- d.module_eval { attribute :bar, 'foofoo', :mandatory }
292
- end
293
- assert_nothing_raised { dd = d.new }
294
- assert_nothing_raised { dd.initialize_attributes }
295
- assert_raise(AttributedClass::AttributeMissingError) do
296
- dd.check_attributes
297
- end
298
- end
299
-
300
- end # class AttributedClassTest
301
-
302
- end
@@ -1,373 +0,0 @@
1
- # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
- # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
- # License: Gnu General Public License.
4
-
5
- # $LastChangedBy: ertai $
6
- # $Id: cache.rb 186 2005-04-03 00:07:45Z ertai $
7
-
8
-
9
- require 'pathname'
10
- require 'md5'
11
- require 'tempfile'
12
- require 'fileutils'
13
-
14
-
15
- class Cache
16
-
17
- #
18
- # Constants
19
- #
20
- REPOSITORY = '/var/cache/ruby_ex_cache'
21
- MAX_SIZE = 50 * 1024 * 1024 # 50 MB
22
- BLOCK_SIZE = 1024 # octets
23
-
24
- #
25
- # Attributs
26
- #
27
- attr_reader :repository, :max_size, :size
28
-
29
- #
30
- # Constructor
31
- #
32
- def initialize(repository=REPOSITORY, max_size=MAX_SIZE)
33
- @repository = Pathname.new(repository)
34
- @max_size = check_max_size(max_size)
35
- create
36
- end
37
-
38
- #
39
- # Methods
40
- #
41
- def create
42
- @size = 0
43
- @atime = []
44
- if @repository.directory?
45
- @repository.each_entry do |p|
46
- next if p.to_s =~ /^\./
47
- full_p = @repository + p
48
- @atime << full_p
49
- @size += full_p.size
50
- end
51
- @atime.sort! { |a, b| a.atime <=> b.atime }
52
- else
53
- @repository.mkdir
54
- end
55
- end
56
-
57
- def clear
58
- @repository.each_entry do |p|
59
- (@repository + p).delete unless p.to_s =~ /^\./
60
- end
61
- @size = 0
62
- @atime.clear
63
- end
64
-
65
- def recreate
66
- clear
67
- create
68
- end
69
-
70
- def open(md5sum=nil, mode='r', perm=0644, &block)
71
- case mode
72
- when 'r': read(md5sum, &block)
73
- when 'w': write(perm, &block)
74
- else
75
- raise(ArgumentError, "`#{mode}' - bad mode")
76
- end
77
- end
78
-
79
- def read(md5sum, &block)
80
- p = @repository + md5sum.to_s
81
- p.open('r', &block)
82
- @atime.delete(p)
83
- @atime << p
84
- p
85
- end
86
-
87
- def write(perm=0644, &block)
88
- tmp = nil
89
- p = nil
90
- begin
91
- md5 = Digest::MD5.new
92
- tmp = Tempfile.new('cache')
93
- new_size = 0
94
- while (str = block[])
95
- tmp.write(str)
96
- md5 << str
97
- new_size += str.size
98
- end
99
- tmp.close
100
- p = @repository + md5.to_s
101
- if p.exist?
102
- @atime.delete(p)
103
- else
104
- @size += new_size
105
- end
106
- FileUtils.move(tmp.path, p)
107
- p.chmod(perm)
108
- rescue
109
- tmp.delete if tmp
110
- raise
111
- end
112
- @atime << p
113
- adjust_size
114
- p
115
- end
116
-
117
- def import(filename)
118
- p = nil
119
- File.open(filename) do |f|
120
- p = write(File.stat(filename).mode) { f.eof? ? nil : f.read(BLOCK_SIZE) }
121
- end
122
- p
123
- end
124
-
125
- def export(md5sum, dst_filename)
126
- p = @repository + md5sum.to_s
127
- FileUtils.copy_entry(p, dst_filename)
128
- update_entry(p)
129
- p
130
- end
131
-
132
- def present?(md5sum)
133
- p = @repository + md5sum.to_s
134
- p.exist? ? p : nil;
135
- end
136
-
137
- def each
138
- @atime.each { |p| yield(p) }
139
- end
140
-
141
- def [](index)
142
- @atime[index]
143
- end
144
-
145
- def max_size=(max_size)
146
- @max_size = check_max_size(max_size)
147
- adjust_size
148
- end
149
-
150
- def nb_files
151
- @atime.size
152
- end
153
-
154
- protected
155
- def adjust_size
156
- while @size > @max_size
157
- p = @atime.shift
158
- @size -= p.size
159
- p.delete
160
- end
161
- @size
162
- end
163
-
164
- protected
165
- def check_max_size(max_size)
166
- unless max_size > 0
167
- raise(ArgumentError, "`#{max_size}' - bad cache maximum size")
168
- end
169
- max_size
170
- end
171
-
172
- end # class Cache
173
-
174
-
175
- #
176
- # Unit test suite
177
- #
178
- if defined? TEST_MODE or __FILE__ == $0
179
-
180
-
181
- require 'test/unit/ui/yaml/testrunner'
182
- require 'md5sum'
183
-
184
-
185
- class CacheTest < Test::Unit::TestCase
186
-
187
- #
188
- # Tests
189
- #
190
- def test_simple
191
- tmp_cache = nil
192
- begin
193
- tmp_cache = Tempfile.new('cache')
194
- repo = Pathname.new(tmp_cache.path)
195
- tmp_cache.delete
196
- cache = nil
197
- assert_nothing_raised { cache = Cache.new(repo) }
198
- assert_equal(0, cache.nb_files, 'bad nb_files')
199
- assert_nothing_raised { cache.create }
200
- assert_equal(0, cache.nb_files, 'bad nb_files')
201
- assert_nothing_raised { cache.clear }
202
- assert_equal(0, cache.nb_files, 'bad nb_files')
203
- assert_nothing_raised { cache.create }
204
- assert_equal(0, cache.nb_files, 'bad nb_files')
205
- assert_raises(Errno::ENOENT) { cache.open('toto', 'r') { |f| f.gets } }
206
- assert_equal(0, cache.nb_files, 'bad nb_files')
207
- assert_equal(0, cache.size)
208
-
209
- data = [ "toto\n", "tata\n" ]
210
- p1 = cache.open(nil, 'w') do
211
- data.shift
212
- end
213
- assert_equal(File.md5sum(p1.to_s).to_s, p1.basename.to_s, 'bad md5 open')
214
- assert_equal(1, cache.nb_files, 'bad nb_files')
215
- assert_equal(p1, cache[0])
216
- assert_equal(10, cache.size)
217
- assert_equal(p1, cache.present?(p1.basename))
218
- tmp_p = cache.read(p1) do |f|
219
- assert_equal("toto\n", f.gets)
220
- assert_equal("tata\n", f.gets)
221
- assert(f.eof?)
222
- end
223
- assert_equal(tmp_p, p1)
224
- check_atime(cache)
225
- assert_equal(1, cache.nb_files, 'bad nb_files')
226
- assert(cache.present?(p1))
227
- assert_equal(p1, cache[0])
228
- assert(! cache.present?('foo'))
229
-
230
- tmp_file = Tempfile.new('cache')
231
- system("man printf > #{tmp_file.path} 2> /dev/null")
232
- md5 = File.md5sum(tmp_file.path)
233
- p2 = cache.import(tmp_file.path)
234
- assert_equal(md5.to_s, p2.basename.to_s, 'bad name after import')
235
- assert(p2.exist?, 'file do not exist after import')
236
- assert(FileUtils.cmp(tmp_file.path, p2.to_s), 'bad import')
237
- assert_equal(md5.to_s, File.md5sum(p2.to_s).to_s, 'bad md5 import')
238
- tmp_file.delete
239
- assert_equal(2, cache.nb_files, 'bad nb_files')
240
- assert_equal(p2, cache[1])
241
- check_atime(cache)
242
-
243
- data = [ "foo\n", "bar\n" ]
244
- p3 = cache.open(nil, 'w') do
245
- data.shift
246
- end
247
- assert_equal(File.md5sum(p3.to_s).to_s, p3.basename.to_s, 'bad md5 open')
248
- assert_equal(3, cache.nb_files, 'bad nb_files')
249
- assert_equal(p3, cache[2])
250
- assert_equal(p3, cache.present?(p3.basename))
251
-
252
- assert_equal(p1, cache[0], 'p1 first')
253
- assert_equal(p2, cache[1], 'p2 second')
254
- assert_equal(p3, cache[2], 'p3 third')
255
- assert_equal(p1, cache.read(p1) { |f| f.gets })
256
- assert_equal(p2, cache[0], 'p2 first')
257
- assert_equal(p3, cache[1], 'p3 second')
258
- assert_equal(p1, cache[2], 'p1 third')
259
- check_atime(cache)
260
- assert_equal(3, cache.nb_files, 'bad nb_files')
261
-
262
-
263
- new_cache = nil
264
- assert_nothing_raised { new_cache = Cache.new(repo) }
265
- assert_equal(3, new_cache.nb_files, 'bad nb_files in new cache')
266
- check_atime(new_cache)
267
- assert_equal(cache.size, new_cache.size)
268
-
269
- assert_equal(3, cache.nb_files, 'bad nb_files')
270
- assert(cache.size > 1024)
271
- cache.max_size = 1024
272
- assert(cache.size < 1024)
273
- assert_equal(p1.size + p3.size, cache.size)
274
- assert_equal(2, cache.nb_files, 'bad nb_files')
275
- assert_equal(p3, cache[0], 'p3 first')
276
- assert_equal(p1, cache[1], 'p1 second')
277
-
278
- cache.clear
279
- assert_equal(0, cache.nb_files, 'bad nb_files')
280
- assert_equal(0, cache.size)
281
- ensure
282
- repo.rmtree if repo
283
- end
284
- end
285
-
286
- def test_write_twice_the_same
287
- tmp_cache = nil
288
- begin
289
- tmp_cache = Tempfile.new('cache')
290
- repo = Pathname.new(tmp_cache.path)
291
- tmp_cache.delete
292
- cache = nil
293
- assert_nothing_raised { cache = Cache.new(repo) }
294
- assert_equal(0, cache.nb_files, 'bad nb_files')
295
- assert_equal(0, cache.size)
296
-
297
- data = [ "toto\n", "tata\n" ]
298
- d = data.dup
299
- p1 = cache.open(nil, 'w') do
300
- d.shift
301
- end
302
-
303
- assert_equal(File.md5sum(p1.to_s).to_s, p1.basename.to_s, 'bad md5 open')
304
- assert_equal(1, cache.nb_files, 'bad nb_files')
305
- assert_equal(p1, cache[0])
306
- assert_equal(10, cache.size)
307
- assert_equal(p1, cache.present?(p1.basename))
308
-
309
- data = [ "toto\n", "tata\n" ]
310
- d = data.dup
311
- p2 = cache.open(nil, 'w') do
312
- d.shift
313
- end
314
-
315
- assert_equal(File.md5sum(p1.to_s).to_s, p1.basename.to_s, 'bad md5 open')
316
- assert_equal(1, cache.nb_files, 'bad nb_files')
317
- assert_equal(p1, cache[0])
318
- assert_equal(10, cache.size)
319
- assert_equal(p1, cache.present?(p1.basename))
320
- ensure
321
- repo.rmtree if repo
322
- end
323
- end
324
-
325
- def test_nested_write
326
- tmp_cache = nil
327
- begin
328
- tmp_cache = Tempfile.new('cache')
329
- repo = Pathname.new(tmp_cache.path)
330
- tmp_cache.delete
331
- cache = nil
332
- assert_nothing_raised { cache = Cache.new(repo) }
333
- assert_equal(0, cache.nb_files, 'bad nb_files')
334
- assert_equal(0, cache.size)
335
-
336
- data = [ "toto\n", "tata\n" ]
337
- d1 = data.dup
338
- p1 = cache.open(nil, 'w') do
339
- d2 = data.dup
340
- p2 = cache.open(nil, 'w') do
341
- d2.shift
342
- end
343
- d1.shift
344
- end
345
-
346
- assert_equal(File.md5sum(p1.to_s).to_s, p1.basename.to_s, 'bad md5 open')
347
- assert_equal(1, cache.nb_files, 'bad nb_files')
348
- assert_equal(p1, cache[0])
349
- assert_equal(10, cache.size)
350
- assert_equal(p1, cache.present?(p1.basename))
351
-
352
- ensure
353
- repo.rmtree if repo
354
- end
355
- end
356
-
357
- #
358
- # Utilities
359
- #
360
- protected
361
- def check_atime(cache)
362
- j = 0
363
- for i in 1...cache.nb_files do
364
- assert(cache[j].atime <= cache[i].atime, "bad atime order for #{i}")
365
- j = i
366
- end
367
- end
368
-
369
- end # class CacheTest
370
-
371
-
372
- end
373
-