Class: Rails::Credentials::Conflict::Resolver

Inherits:
Object
  • Object
show all
Defined in:
lib/rails/credentials/conflict/resolver.rb,
sig/rails/credentials/conflict/resolver.rbs

Overview

Top-level orchestrator for resolving git merge conflicts in encrypted Rails credentials files.

Coordinates between PathResolver, EncryptionService, GitConflictHandler, and MergeStrategy to decrypt conflicting versions, merge them, and re-encrypt the result.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(environment = nil, output: $stdout) ⇒ Resolver

Returns a new instance of Resolver.

Parameters:

  • (defaults to: nil)
  • (defaults to: $stdout)


15
16
17
18
19
20
21
22
23
24
25
# File 'lib/rails/credentials/conflict/resolver.rb', line 15

def initialize(environment = nil, output: $stdout)
  @environment = environment
  @output = output
  @path_resolver = PathResolver.new(environment)
  @encryption_service = EncryptionService.new(@path_resolver.key_path)
  @git_handler = GitConflictHandler.new(
    @path_resolver.credentials_path,
    @path_resolver.relative_credentials_path
  )
  @merge_strategy = MergeStrategy.new(@encryption_service)
end

Instance Attribute Details

#environmentString? (readonly)

Returns the value of attribute environment.

Returns:



13
14
15
# File 'lib/rails/credentials/conflict/resolver.rb', line 13

def environment
  @environment
end

Instance Method Details

#basevoid

This method returns an undefined value.

Resolves the conflict by keeping the common ancestor's version.



79
80
81
# File 'lib/rails/credentials/conflict/resolver.rb', line 79

def base
  resolve_with_version(:base, "base")
end

#decrypt_version(version) ⇒ String

Parameters:

Returns:



100
101
102
103
# File 'lib/rails/credentials/conflict/resolver.rb', line 100

def decrypt_version(version)
  encrypted_content = @git_handler.get_version(version)
  @encryption_service.decrypt(encrypted_content)
end

#get_base_versionString

Returns:



105
106
107
108
109
110
111
112
113
# File 'lib/rails/credentials/conflict/resolver.rb', line 105

def get_base_version
  base_encrypted = @git_handler.get_version(:base)
  return "" if base_encrypted.empty?

  @encryption_service.decrypt(base_encrypted)
rescue StandardError => e
  log "Warning: Could not decrypt base version (#{e.message}). Using empty base."
  ""
end

#log(message) ⇒ void

This method returns an undefined value.

Parameters:



85
86
87
# File 'lib/rails/credentials/conflict/resolver.rb', line 85

def log(message)
  @output.puts(message)
end

#resolvevoid

This method returns an undefined value.

Decrypts both sides of a conflict, performs a three-way merge, and re-encrypts the resolved content. Opens an editor when automatic merge is not possible.



30
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
57
58
59
60
61
62
63
64
65
66
# File 'lib/rails/credentials/conflict/resolver.rb', line 30

def resolve
  @git_handler.validate_conflict!

  ours_content = decrypt_version(:ours)
  theirs_content = decrypt_version(:theirs)

  if ours_content == theirs_content
    log "No conflicts detected. Both versions are identical."
    save_and_stage(ours_content)
    return
  end

  base_content = get_base_version
  labels = @git_handler.get_merge_labels
  merge_result = @merge_strategy.create_conflict_markers(
    ours_content,
    base_content,
    theirs_content,
    labels: labels
  )

  if merge_result[:has_conflicts]
    log "Conflicts detected. Opening editor for manual resolution..."
    resolved_content = @merge_strategy.open_editor_for_resolution(merge_result[:content])

    if @merge_strategy.has_conflict_markers?(resolved_content)
      raise Error, "Conflict markers still present. Please resolve all conflicts."
    end
  else
    log "Changes in different sections detected. Auto-merged successfully."
    resolved_content = merge_result[:content]
  end

  @merge_strategy.validate_yaml!(resolved_content)
  save_and_stage(resolved_content)
  log "Credentials successfully resolved and encrypted."
end

#resolve_with_version(version, label) ⇒ void

This method returns an undefined value.

Parameters:

Raises:



89
90
91
92
93
94
95
96
97
98
# File 'lib/rails/credentials/conflict/resolver.rb', line 89

def resolve_with_version(version, label)
  @git_handler.validate_conflict!

  encrypted_content = @git_handler.get_version(version)
  raise Error, "No #{label} version found." if encrypted_content.empty?

  content = @encryption_service.decrypt(encrypted_content)
  save_and_stage(content)
  log "Kept #{label} version of credentials."
end

#save_and_stage(content) ⇒ void

This method returns an undefined value.

Parameters:



115
116
117
118
# File 'lib/rails/credentials/conflict/resolver.rb', line 115

def save_and_stage(content)
  @encryption_service.save_encrypted(content, @path_resolver.credentials_path)
  @git_handler.stage_resolved_file!
end

#theirsvoid

This method returns an undefined value.

Resolves the conflict by keeping the incoming branch's version.



74
75
76
# File 'lib/rails/credentials/conflict/resolver.rb', line 74

def theirs
  resolve_with_version(:theirs, "their")
end

#yoursvoid

This method returns an undefined value.

Resolves the conflict by keeping the current branch's version.



69
70
71
# File 'lib/rails/credentials/conflict/resolver.rb', line 69

def yours
  resolve_with_version(:ours, "your")
end