class Au::Document
Attributes
path[R]
Public Class Methods
find(paths)
click to toggle source
# File lib/au/models/document.rb, line 16 def self.find(paths) paths.is_a?(Array) ? paths.map{ |path| new(path) } : new(paths) end
new(path)
click to toggle source
Do NOT invoke this method directly, always use Document.find
instead.
# File lib/au/models/document.rb, line 24 def initialize(path) @path = path end
Public Instance Methods
changed?(parent_diff_id)
click to toggle source
# File lib/au/models/document.rb, line 52 def changed?(parent_diff_id) !diff(parent_diff_id).empty? end
checkout(diff_id)
click to toggle source
# File lib/au/models/document.rb, line 67 def checkout(diff_id) # do nothing if file didn't change return if File.exists?(abs_path) && calculate_md5 == md5_at(diff_id) FileUtils.mkdir_p(File.dirname(abs_path)) unless File.exists?(abs_path) File.open(abs_path, 'w') do |f| apply_diffs(f, diff_id) end end
content_from(diff_id)
click to toggle source
# File lib/au/models/document.rb, line 60 def content_from(diff_id) output = Tempfile.new return output unless diff_id apply_diffs(output, diff_id) output end
create_diff(parent_diff_id)
click to toggle source
# File lib/au/models/document.rb, line 28 def create_diff(parent_diff_id) return nil unless File.exists?(abs_path) changes = diff(parent_diff_id) # if not first diff AND there's no change, don't create new diff return parent_diff_id if changes.empty? && parent_diff_id Diff.create(diff_db_name, parent_diff_id, changes, calculate_md5) end
diff(parent_diff_id)
click to toggle source
# File lib/au/models/document.rb, line 56 def diff(parent_diff_id) `diff -c #{abs_path} #{content_from(parent_diff_id).path}` end
diff_3(ancestor_diff_id:, other_diff_id:)
click to toggle source
# File lib/au/models/document.rb, line 36 def diff_3(ancestor_diff_id:, other_diff_id:) file_in_ancestor_state = content_from(ancestor_diff_id) file_in_other_state = content_from(other_diff_id) diff3_args = "#{abs_path} #{file_in_ancestor_state.path} #{file_in_other_state.path}" # diff3 has issue when this file and other file are identical, but ancestor is different, # so we need a special case for identical files return if (`diff -c #{abs_path} #{file_in_other_state.path}` == '') has_conflict = !`diff3 -x #{diff3_args}`.empty? merged_content = `diff3 --merge #{diff3_args}` File.open(abs_path, 'w'){ |f| f.write(merged_content) } raise HasMergeConflict.new(self) if has_conflict end
md5_at(diff_id)
click to toggle source
# File lib/au/models/document.rb, line 77 def md5_at(diff_id) Diff.find(diff_id, db_name: diff_db_name).md5 end
Private Instance Methods
abs_path()
click to toggle source
# File lib/au/models/document.rb, line 102 def abs_path paths = [Repository.root, path].compact File.join(*paths) end
apply_diffs(output, last_diff_id)
click to toggle source
# File lib/au/models/document.rb, line 87 def apply_diffs(output, last_diff_id) Diff.replay_changes_upto(last_diff_id, diff_db_name) do |diff| Tempfile.create do |f| f.write(diff.change) f.rewind `patch -cR #{output.path} #{f.path}` end end end
calculate_md5()
click to toggle source
# File lib/au/models/document.rb, line 83 def calculate_md5 Digest::MD5.hexdigest(File.read(abs_path)) end
diff_db_name()
click to toggle source
# File lib/au/models/document.rb, line 97 def diff_db_name paths = [Repository.path, "diff_#{path.gsub('/', '.')}.pstore"].compact File.join(*paths) end