7 require "svn/ext/delta"
11 Util.set_constants(Ext::Delta, self)
12 Util.set_methods(Ext::Delta, self)
15 alias _path_driver path_driver
17 alias _path_driver path_driver
20 def svndiff_handler(output, version=nil)
21 args = [output, version || 0]
22 handler, handler_baton = Delta.txdelta_to_svndiff2(*args)
23 handler.baton = handler_baton
27 def read_svndiff_window(stream, version)
28 Delta.txdelta_read_svndiff_window(stream, version)
31 def skip_svndiff_window(file, version)
32 Delta.txdelta_skip_svndiff_window(file, version)
35 def path_driver(editor, revision, paths, &callback_func)
36 Delta._path_driver(editor, revision, paths, callback_func)
39 def send(string_or_stream, handler=nil)
40 if handler.nil? and block_given?
41 handler = Proc.new {|window| yield(window)}
42 Delta.setup_handler_wrapper(handler)
44 if string_or_stream.is_a?(TextDeltaStream)
45 string_or_stream.send(handler)
46 elsif string_or_stream.is_a?(String)
47 Delta.txdelta_send_string(string_or_stream, handler)
49 Delta.txdelta_send_stream(string_or_stream, handler)
53 def apply(source, target, error_info=nil)
54 result = Delta.txdelta_apply_wrapper(source, target, error_info)
55 digest, handler, handler_baton = result
56 handler.baton = handler_baton
60 def parse_svndiff(error_on_early_close=true, &handler)
61 Delta.txdelta_parse_svndiff(handler, error_on_early_close)
64 def setup_handler_wrapper(wrapper)
66 Delta.txdelta_invoke_window_handler_wrapper(wrapper, window)
70 TextDeltaStream = SWIG::TYPE_p_svn_txdelta_stream_t
74 def new(source, target)
75 Delta.txdelta(source, target)
78 def push_target(source, &handler)
79 Delta.txdelta_target_push(handler, source)
84 Delta.txdelta_md5_digest_as_cstring(self)
88 Delta.txdelta_next_window(self, Svn::Core::Pool.new)
92 while window = next_window
98 if handler.nil? and block_given?
99 handler = Proc.new {|window| yield(window)}
100 Delta.setup_handler_wrapper(handler)
102 Delta.txdelta_send_txstream(self, handler)
106 TextDeltaWindow = TxdeltaWindow
108 class TextDeltaWindow
109 def compose(other_window)
110 Delta.txdelta_compose_windows(other_window, self)
114 Delta.txdelta_window_t_ops_get(self)
117 def apply_instructions(source_buffer)
118 Delta.swig_rb_txdelta_apply_instructions(self, source_buffer)
122 TextDeltaWindowHandler =
123 SWIG::TYPE_p_f_p_svn_txdelta_window_t_p_void__p_svn_error_t
125 class TextDeltaWindowHandler
129 Delta.txdelta_invoke_window_handler(self, window, @baton)
132 def send(string_or_stream)
133 if string_or_stream.is_a?(TextDeltaStream)
134 Delta.txdelta_send_txstream(string_or_stream, self, @baton)
135 elsif string_or_stream.is_a?(String)
136 Delta.txdelta_send_string(string_or_stream, self, @baton)
138 Delta.txdelta_send_stream(string_or_stream, self, @baton)
145 %w(set_target_revision open_root delete_entry
146 add_directory open_directory change_dir_prop
147 close_directory absent_directory add_file open_file
148 apply_textdelta change_file_prop close_file
149 absent_file close_edit abort_edit).each do |name|
150 alias_method("_#{name}", name)
151 undef_method("#{name}=")
155 attr_writer :target_revision_address
156 private :target_revision_address=
159 Svn::Delta.swig_rb_delta_editor_get_target_revision(self)
162 def set_target_revision(target_revision)
163 args = [self, @baton, target_revision]
164 Svn::Delta.editor_invoke_set_target_revision(*args)
167 def open_root(base_revision)
168 args = [self, @baton, base_revision]
169 Svn::Delta.editor_invoke_open_root_wrapper(*args)
172 def delete_entry(path, revision, parent_baton)
173 args = [self, path, revision, parent_baton]
174 Svn::Delta.editor_invoke_delete_entry(*args)
177 def add_directory(path, parent_baton,
178 copyfrom_path, copyfrom_revision)
179 args = [self, path, parent_baton, copyfrom_path, copyfrom_revision]
180 Svn::Delta.editor_invoke_add_directory_wrapper(*args)
183 def open_directory(path, parent_baton, base_revision)
184 args = [self, path, parent_baton, base_revision]
185 Svn::Delta.editor_invoke_open_directory_wrapper(*args)
188 def change_dir_prop(dir_baton, name, value)
189 args = [self, dir_baton, name, value]
190 Svn::Delta.editor_invoke_change_dir_prop(*args)
193 def close_directory(dir_baton)
194 args = [self, dir_baton]
195 Svn::Delta.editor_invoke_close_directory(*args)
198 def absent_directory(path, parent_baton)
199 args = [self, path, parent_baton]
200 Svn::Delta.editor_invoke_absent_directory(*args)
203 def add_file(path, parent_baton,
204 copyfrom_path, copyfrom_revision)
205 args = [self, path, parent_baton, copyfrom_path, copyfrom_revision]
206 Svn::Delta.editor_invoke_add_file_wrapper(*args)
209 def open_file(path, parent_baton, base_revision)
210 args = [self, path, parent_baton, base_revision]
211 Svn::Delta.editor_invoke_open_file_wrapper(*args)
214 def apply_textdelta(file_baton, base_checksum)
215 args = [self, file_baton, base_checksum]
216 handler, handler_baton =
217 Svn::Delta.editor_invoke_apply_textdelta_wrapper(*args)
218 handler.baton = handler_baton
222 def change_file_prop(file_baton, name, value)
223 args = [self, file_baton, name, value]
224 Svn::Delta.editor_invoke_change_file_prop(*args)
227 def close_file(file_baton, text_checksum)
228 args = [self, file_baton, text_checksum]
229 Svn::Delta.editor_invoke_close_file(*args)
232 def absent_file(path, parent_baton)
233 args = [self, path, parent_baton]
234 Svn::Delta.editor_invoke_absent_file(*args)
238 args = [self, @baton]
239 Svn::Delta.editor_invoke_close_edit(*args)
241 Core::Pool.destroy(self)
245 args = [self, @baton]
246 Svn::Delta.editor_invoke_abort_edit(*args)
248 Core::Pool.destroy(self)
253 # open_root -> add_directory -> open_directory -> add_file -> open_file
254 def set_target_revision(target_revision)
257 def open_root(base_revision)
260 def delete_entry(path, revision, parent_baton)
263 def add_directory(path, parent_baton,
264 copyfrom_path, copyfrom_revision)
267 def open_directory(path, parent_baton, base_revision)
270 def change_dir_prop(dir_baton, name, value)
273 def close_directory(dir_baton)
276 def absent_directory(path, parent_baton)
279 def add_file(path, parent_baton,
280 copyfrom_path, copyfrom_revision)
283 def open_file(path, parent_baton, base_revision)
286 # return nil or object which has `call' method.
287 def apply_textdelta(file_baton, base_checksum)
290 def change_file_prop(file_baton, name, value)
293 def close_file(file_baton, text_checksum)
296 def absent_file(path, parent_baton)
299 def close_edit(baton)
302 def abort_edit(baton)
306 class CopyDetectableEditor < BaseEditor
307 def add_directory(path, parent_baton,
308 copyfrom_path, copyfrom_revision)
311 def add_file(path, parent_baton,
312 copyfrom_path, copyfrom_revision)
316 class ChangedDirsEditor < BaseEditor
317 attr_reader :changed_dirs
323 def open_root(base_revision)
327 def delete_entry(path, revision, parent_baton)
328 dir_changed(parent_baton)
331 def add_directory(path, parent_baton,
332 copyfrom_path, copyfrom_revision)
333 dir_changed(parent_baton)
337 def open_directory(path, parent_baton, base_revision)
341 def change_dir_prop(dir_baton, name, value)
342 dir_changed(dir_baton)
345 def add_file(path, parent_baton,
346 copyfrom_path, copyfrom_revision)
347 dir_changed(parent_baton)
350 def open_file(path, parent_baton, base_revision)
351 dir_changed(parent_baton)
354 def close_edit(baton)
359 def dir_changed(baton)
361 # the directory hasn't been printed yet. do it.
362 @changed_dirs << "#{baton[1]}/"
368 class ChangedEditor < BaseEditor
370 attr_reader :copied_files, :copied_dirs
371 attr_reader :added_files, :added_dirs
372 attr_reader :deleted_files, :deleted_dirs
373 attr_reader :updated_files, :updated_dirs
375 def initialize(root, base_root)
377 @base_root = base_root
389 def open_root(base_revision)
393 def delete_entry(path, revision, parent_baton)
394 if @base_root.dir?("/#{path}")
395 @deleted_dirs << "#{path}/"
397 @deleted_files << path
401 def add_directory(path, parent_baton,
402 copyfrom_path, copyfrom_revision)
403 copyfrom_rev, copyfrom_path = @root.copied_from(path)
405 @in_copied_dir.push(true)
406 elsif Util.copy?(copyfrom_path, copyfrom_rev)
407 @copied_dirs << ["#{path}/", "#{copyfrom_path.sub(/^\//, '')}/", copyfrom_rev]
408 @in_copied_dir.push(true)
410 @added_dirs << "#{path}/"
411 @in_copied_dir.push(false)
416 def open_directory(path, parent_baton, base_revision)
420 def change_dir_prop(dir_baton, name, value)
422 @updated_dirs << "#{dir_baton[1]}/"
428 def close_directory(dir_baton)
434 def add_file(path, parent_baton,
435 copyfrom_path, copyfrom_revision)
436 copyfrom_rev, copyfrom_path = @root.copied_from(path)
439 elsif Util.copy?(copyfrom_path, copyfrom_rev)
440 @copied_files << [path, copyfrom_path.sub(/^\//, ''), copyfrom_rev]
447 def open_file(path, parent_baton, base_revision)
451 def apply_textdelta(file_baton, base_checksum)
452 file_baton[0] = :update
456 def change_file_prop(file_baton, name, value)
457 file_baton[1] = :update
460 def close_file(file_baton, text_checksum)
461 text_mod, prop_mod, path = file_baton
462 # test the path. it will be nil if we added this file.
464 if [text_mod, prop_mod] != [nil, nil]
465 @updated_files << path
470 def close_edit(baton)
471 @copied_files.sort! {|a, b| a[0] <=> b[0]}
472 @copied_dirs.sort! {|a, b| a[0] <=> b[0]}
490 def_delegators :@wrapped_editor, :set_target_revision, :open_root
491 def_delegators :@wrapped_editor, :delete_entry, :add_directory
492 def_delegators :@wrapped_editor, :open_directory, :change_dir_prop
493 def_delegators :@wrapped_editor, :close_directory, :absent_directory
494 def_delegators :@wrapped_editor, :add_file, :open_file, :apply_textdelta
495 def_delegators :@wrapped_editor, :change_file_prop, :close_file
496 def_delegators :@wrapped_editor, :absent_file, :close_edit, :abort_edit
498 def initialize(wrapped_editor)
499 @wrapped_editor = wrapped_editor