Class: FlashFlow::Git
- Inherits:
-
Object
- Object
- FlashFlow::Git
- Defined in:
- lib/flash_flow/git.rb
Direct Known Subclasses
Constant Summary collapse
- ATTRIBUTES =
[:remote, :merge_branch, :master_branch, :release_branch, :use_rerere]
- UNMERGED_STATUSES =
%w{DD AU UD UA DU AA UU}
Instance Attribute Summary collapse
-
#working_branch ⇒ Object
readonly
Returns the value of attribute working_branch.
Instance Method Summary collapse
- #add_and_commit(files, message, opts = {}) ⇒ Object
- #ahead_of_master?(branch) ⇒ Boolean
- #branch_contains?(branch, ref) ⇒ Boolean
- #branch_exists?(branch) ⇒ Boolean
- #commit_rerere(current_rereres) ⇒ Object
- #conflicted_files ⇒ Object
- #copy_temp_to_branch(branch, squash_message = nil) ⇒ Object
- #current_branch ⇒ Object
- #delete_temp_merge_branch ⇒ Object
- #get_sha(branch, opts = {}) ⇒ Object
- #in_branch(branch) ⇒ Object
- #in_dir ⇒ Object
- #in_merge_branch(&block) ⇒ Object
- #in_original_merge_branch ⇒ Object
- #in_temp_merge_branch(&block) ⇒ Object
-
#initialize(config, logger = nil) ⇒ Git
constructor
A new instance of Git.
- #initialize_rerere ⇒ Object
- #last_command ⇒ Object
- #last_stdout ⇒ Object
- #last_success? ⇒ Boolean
- #master_branch_contains?(sha) ⇒ Boolean
- #merge(branch) ⇒ Object
- #most_recent_commit ⇒ Object
- #push(branch, force = false) ⇒ Object
- #read_file_from_merge_branch(filename) ⇒ Object
- #rerere_resolve! ⇒ Object
- #reset_temp_merge_branch ⇒ Object
-
#resolution_candidates(file) ⇒ Object
git rerere doesn’t give you a deterministic way to determine which resolution was used.
- #resolutions(files) ⇒ Object
- #run(cmd, opts = {}) ⇒ Object
- #split_diff_lines(arr) ⇒ Object
- #staged_and_working_dir_files ⇒ Object
- #temp_merge_branch ⇒ Object
- #unresolved_conflicts ⇒ Object
Constructor Details
#initialize(config, logger = nil) ⇒ Git
Returns a new instance of Git.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/flash_flow/git.rb', line 13 def initialize(config, logger=nil) @cmd_runner = CmdRunner.new(logger: logger) config['release_branch'] ||= config['master_branch'] config['remote'] ||= config['merge_remote'] # For backwards compatibility ATTRIBUTES.each do |attr| unless config.has_key?(attr.to_s) raise RuntimeError.new("git configuration missing. Required config parameters: #{ATTRIBUTES}") end instance_variable_set("@#{attr}", config[attr.to_s]) end @working_branch = current_branch end |
Instance Attribute Details
#working_branch ⇒ Object (readonly)
Returns the value of attribute working_branch.
9 10 11 |
# File 'lib/flash_flow/git.rb', line 9 def working_branch @working_branch end |
Instance Method Details
#add_and_commit(files, message, opts = {}) ⇒ Object
52 53 54 55 56 |
# File 'lib/flash_flow/git.rb', line 52 def add_and_commit(files, , opts={}) files = [files].flatten run("add #{'-f ' if opts[:add] && opts[:add][:force]}#{files.join(' ')}") run("commit -m '#{}'") end |
#ahead_of_master?(branch) ⇒ Boolean
230 231 232 |
# File 'lib/flash_flow/git.rb', line 230 def ahead_of_master?(branch) branch_exists?(branch) && !master_branch_contains?(get_sha(branch)) end |
#branch_contains?(branch, ref) ⇒ Boolean
62 63 64 65 |
# File 'lib/flash_flow/git.rb', line 62 def branch_contains?(branch, ref) run("branch -a --contains #{ref}", log: CmdRunner::LOG_CMD) last_stdout.split("\n").detect { |str| str[2..-1] == branch } end |
#branch_exists?(branch) ⇒ Boolean
225 226 227 228 |
# File 'lib/flash_flow/git.rb', line 225 def branch_exists?(branch) run("rev-parse --verify #{branch}") last_success? end |
#commit_rerere(current_rereres) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/flash_flow/git.rb', line 87 def commit_rerere(current_rereres) return unless use_rerere @cmd_runner.run('mkdir rr-cache') @cmd_runner.run('rm -rf rr-cache/*') current_rereres.each do |rerere| @cmd_runner.run("cp -R .git/rr-cache/#{rerere} rr-cache/") end run('add rr-cache/') run("commit -m 'Update rr-cache'") end |
#conflicted_files ⇒ Object
151 152 153 154 |
# File 'lib/flash_flow/git.rb', line 151 def conflicted_files run("diff --name-only --diff-filter=U") last_stdout.split("\n") end |
#copy_temp_to_branch(branch, squash_message = nil) ⇒ Object
178 179 180 181 182 183 184 185 |
# File 'lib/flash_flow/git.rb', line 178 def copy_temp_to_branch(branch, = nil) run("checkout #{temp_merge_branch}") run("merge --strategy=ours --no-edit #{branch}") run("checkout #{branch}") run("merge #{temp_merge_branch}") squash_commits(branch, ) if end |
#current_branch ⇒ Object
156 157 158 159 |
# File 'lib/flash_flow/git.rb', line 156 def current_branch run("rev-parse --abbrev-ref HEAD") last_stdout.strip end |
#delete_temp_merge_branch ⇒ Object
187 188 189 190 191 |
# File 'lib/flash_flow/git.rb', line 187 def delete_temp_merge_branch in_branch(master_branch) do run("branch -d #{temp_merge_branch}") end end |
#get_sha(branch, opts = {}) ⇒ Object
216 217 218 219 220 221 222 223 |
# File 'lib/flash_flow/git.rb', line 216 def get_sha(branch, opts={}) if opts[:short] run("rev-parse --short #{branch}") else run("rev-parse #{branch}") end last_stdout.strip if last_success? end |
#in_branch(branch) ⇒ Object
201 202 203 204 205 206 207 208 209 210 |
# File 'lib/flash_flow/git.rb', line 201 def in_branch(branch) begin starting_branch = current_branch run("checkout #{branch}") yield ensure run("checkout #{starting_branch}") end end |
#in_dir ⇒ Object
30 31 32 33 34 |
# File 'lib/flash_flow/git.rb', line 30 def in_dir Dir.chdir(@cmd_runner.dir) do yield end end |
#in_merge_branch(&block) ⇒ Object
197 198 199 |
# File 'lib/flash_flow/git.rb', line 197 def in_merge_branch(&block) in_branch(merge_branch, &block) end |
#in_original_merge_branch ⇒ Object
71 72 73 |
# File 'lib/flash_flow/git.rb', line 71 def in_original_merge_branch in_branch("#{remote}/#{merge_branch}") { yield } end |
#in_temp_merge_branch(&block) ⇒ Object
193 194 195 |
# File 'lib/flash_flow/git.rb', line 193 def in_temp_merge_branch(&block) in_branch(temp_merge_branch, &block) end |
#initialize_rerere ⇒ Object
80 81 82 83 84 85 |
# File 'lib/flash_flow/git.rb', line 80 def initialize_rerere return unless use_rerere @cmd_runner.run('mkdir .git/rr-cache') @cmd_runner.run('cp -R rr-cache/* .git/rr-cache/') end |
#last_command ⇒ Object
40 41 42 |
# File 'lib/flash_flow/git.rb', line 40 def last_command @cmd_runner.last_command end |
#last_stdout ⇒ Object
36 37 38 |
# File 'lib/flash_flow/git.rb', line 36 def last_stdout @cmd_runner.last_stdout end |
#last_success? ⇒ Boolean
44 45 46 |
# File 'lib/flash_flow/git.rb', line 44 def last_success? @cmd_runner.last_success? end |
#master_branch_contains?(sha) ⇒ Boolean
67 68 69 |
# File 'lib/flash_flow/git.rb', line 67 def master_branch_contains?(sha) branch_contains?("remotes/#{remote}/#{master_branch}", sha) end |
#merge(branch) ⇒ Object
58 59 60 |
# File 'lib/flash_flow/git.rb', line 58 def merge(branch) run("merge #{branch}") end |
#most_recent_commit ⇒ Object
161 162 163 |
# File 'lib/flash_flow/git.rb', line 161 def most_recent_commit run("show -s --format=%cd head") end |
#push(branch, force = false) ⇒ Object
174 175 176 |
# File 'lib/flash_flow/git.rb', line 174 def push(branch, force=false) run("push #{'-f' if force} #{remote} #{branch}") end |
#read_file_from_merge_branch(filename) ⇒ Object
75 76 77 78 |
# File 'lib/flash_flow/git.rb', line 75 def read_file_from_merge_branch(filename) run("show #{remote}/#{merge_branch}:#{filename}", log: CmdRunner::LOG_CMD) last_stdout end |
#rerere_resolve! ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/flash_flow/git.rb', line 99 def rerere_resolve! return false unless use_rerere if unresolved_conflicts.empty? merging_files = staged_and_working_dir_files.select { |s| UNMERGED_STATUSES.include?(s[0..1]) }.map { |s| s[3..-1] } conflicts = conflicted_files run("add #{merging_files.join(" ")}") run('commit --no-edit') resolutions(conflicts) else false end end |
#reset_temp_merge_branch ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/flash_flow/git.rb', line 165 def reset_temp_merge_branch in_branch(master_branch) do run("fetch #{remote}") run("branch -D #{temp_merge_branch}") run("checkout -b #{temp_merge_branch}") run("reset --hard #{remote}/#{master_branch}") end end |
#resolution_candidates(file) ⇒ Object
git rerere doesn’t give you a deterministic way to determine which resolution was used
132 133 134 135 136 137 138 139 140 |
# File 'lib/flash_flow/git.rb', line 132 def resolution_candidates(file) @cmd_runner.run("diff -q --from-file #{file} .git/rr-cache/*/postimage*", log: CmdRunner::LOG_CMD) different_files = split_diff_lines(@cmd_runner.last_stdout) @cmd_runner.run('ls -la .git/rr-cache/*/postimage*', log: CmdRunner::LOG_CMD) all_files = split_diff_lines(@cmd_runner.last_stdout) all_files - different_files end |
#resolutions(files) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/flash_flow/git.rb', line 123 def resolutions(files) {}.tap do |hash| files.map do |file| hash[file] = resolution_candidates(file) end.flatten end end |
#run(cmd, opts = {}) ⇒ Object
48 49 50 |
# File 'lib/flash_flow/git.rb', line 48 def run(cmd, opts={}) @cmd_runner.run("git #{cmd}", opts) end |
#split_diff_lines(arr) ⇒ Object
142 143 144 |
# File 'lib/flash_flow/git.rb', line 142 def split_diff_lines(arr) arr.split("\n").map { |s| s.split(".git/rr-cache/").last.split("/postimage").first } end |
#staged_and_working_dir_files ⇒ Object
146 147 148 149 |
# File 'lib/flash_flow/git.rb', line 146 def staged_and_working_dir_files run("status --porcelain") last_stdout.split("\n").reject { |line| line[0..1] == '??' } end |
#temp_merge_branch ⇒ Object
212 213 214 |
# File 'lib/flash_flow/git.rb', line 212 def temp_merge_branch "flash_flow/#{merge_branch}" end |
#unresolved_conflicts ⇒ Object
115 116 117 118 119 120 121 |
# File 'lib/flash_flow/git.rb', line 115 def unresolved_conflicts in_dir do conflicted_files.map do |file| File.open(file) { |f| f.grep(/>>>>/) }.empty? ? nil : file end.compact end end |