Module: Rails::Credentials::Conflict::MergeDriver

Defined in:
lib/rails/credentials/conflict/merge_driver.rb

Overview

Git merge driver entry point for encrypted credentials files.

Invoked by git during merge/rebase/cherry-pick when a custom merge driver is configured via .gitattributes.

Git calls the driver with four paths:

  • base_path (+%O+) — common ancestor version
  • ours_path (+%A+) — current branch version (result is written here)
  • theirs_path (+%B+) — other branch version
  • file_path (+%P+) — pathname of the file being merged

Class Method Summary collapse

Class Method Details

.call(base_path, ours_path, theirs_path, file_path) ⇒ Object

Runs the merge driver. Decrypts the three versions, performs a three-way merge, and writes the encrypted result back to ours_path.

Returns 0 on successful auto-merge, 1 when conflicts remain.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rails/credentials/conflict/merge_driver.rb', line 31

def self.call(base_path, ours_path, theirs_path, file_path)
  environment = extract_environment(file_path)
  path_resolver = PathResolver.new(environment)
  encryption_service = EncryptionService.new(path_resolver.key_path)
  merge_strategy = MergeStrategy.new(encryption_service)

  base_content = encryption_service.decrypt(File.binread(base_path))
  ours_content = encryption_service.decrypt(File.binread(ours_path))
  theirs_content = encryption_service.decrypt(File.binread(theirs_path))

  return 0 if ours_content == theirs_content

  result = merge_strategy.create_conflict_markers(
    ours_content,
    base_content,
    theirs_content,
    labels: { ours: "ours", base: "base", theirs: "theirs" }
  )

  return 1 if result[:has_conflicts]

  encryption_service.save_encrypted(result[:content], ours_path)
  0
rescue StandardError
  1
end

.extract_environment(file_path) ⇒ Object

Extracts the environment name from a credentials file path.

"config/credentials.yml.enc" → nil "config/credentials/staging.yml.enc" → "staging"



21
22
23
24
25
# File 'lib/rails/credentials/conflict/merge_driver.rb', line 21

def self.extract_environment(file_path)
  if file_path =~ %r{config/credentials/([^/]+)\.yml\.enc\z}
    $1
  end
end