Module: Rails::Hyperdrive::ThreeWayMerge
- Defined in:
- lib/rails/hyperdrive/three_way_merge.rb
Overview
Tempfiles live in the system tmpdir, never in the app, so a dry run stays write-free. Fail-open: a missing or erroring git reads as :unavailable, never an exception.
Defined Under Namespace
Classes: Outcome
Class Method Summary collapse
Class Method Details
.binary?(content) ⇒ Boolean
40 41 42 43 44 |
# File 'lib/rails/hyperdrive/three_way_merge.rb', line 40 def binary?(content) s = content.to_s return true if s.include?("\0".b) !s.dup.force_encoding(Encoding::UTF_8).valid_encoding? end |
.merge(ours:, base:, theirs:) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/rails/hyperdrive/three_way_merge.rb', line 18 def merge(ours:, base:, theirs:) return Outcome.new(status: :unavailable) if [ours, base, theirs].any? { |b| binary?(b) } Dir.mktmpdir("hyperdrive-merge") do |dir| paths = { "ours" => ours, "base" => base, "theirs" => theirs }.map do |name, content| File.join(dir, name).tap { |p| File.binwrite(p, content) } end out, _err, status = Open3.capture3("git", "merge-file", "-p", *paths) if status.success? Outcome.new(status: :clean, body: out) elsif status.exited? && status.exitstatus.between?(1, 127) # git merge-file exits with the conflict count. Outcome.new(status: :conflicted) else Outcome.new(status: :unavailable) end end rescue SystemCallError, IOError Outcome.new(status: :unavailable) end |