Class: FlashFlow::Git
- Inherits:
-
Object
- Object
- FlashFlow::Git
- Defined in:
- lib/flash_flow/git.rb
Constant Summary collapse
- ATTRIBUTES =
[:merge_remote, :merge_branch, :master_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
- #commit_message(log) ⇒ Object
- #commit_rerere(current_rereres) ⇒ Object
- #conflicted_files ⇒ Object
- #copy_temp_to_merge_branch ⇒ Object
- #current_branch ⇒ Object
- #delete_temp_merge_branch ⇒ Object
- #fetch(remote) ⇒ Object
- #fetch_remote_for_url(url) ⇒ Object
- #in_branch(branch) ⇒ 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?(ref) ⇒ Boolean
- #merge(branch) ⇒ Object
- #most_recent_commit ⇒ Object
- #push(branch, options) ⇒ Object
- #push_merge_branch ⇒ Object
- #read_file_from_merge_branch(filename) ⇒ Object
- #remotes ⇒ Object
- #remotes_hash ⇒ 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) ⇒ Object
- #split_diff_lines(arr) ⇒ Object
- #staged_and_working_dir_files ⇒ Object
- #unresolved_conflicts ⇒ Object
Constructor Details
#initialize(config, logger = nil) ⇒ Git
Returns a new instance of Git.
11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/flash_flow/git.rb', line 11 def initialize(config, logger=nil) @cmd_runner = CmdRunner.new(logger: logger) 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.
7 8 9 |
# File 'lib/flash_flow/git.rb', line 7 def working_branch @working_branch end |
Instance Method Details
#add_and_commit(files, message, opts = {}) ⇒ Object
41 42 43 44 45 |
# File 'lib/flash_flow/git.rb', line 41 def add_and_commit(files, , opts={}) files = [files].flatten run("add #{'-f ' if opts[:add] && opts[:add][:force]}#{files.join(' ')}") run("commit -m '#{message}'") end |
#commit_message(log) ⇒ Object
207 208 209 |
# File 'lib/flash_flow/git.rb', line 207 def (log) "Flash Flow run from branch: #{working_branch}\n\n#{log}".gsub(/'/, '') 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
171 172 173 174 |
# File 'lib/flash_flow/git.rb', line 171 def conflicted_files run("diff --name-only --diff-filter=U") last_stdout.split("\n") end |
#copy_temp_to_merge_branch ⇒ Object
198 199 200 201 202 203 204 205 |
# File 'lib/flash_flow/git.rb', line 198 def copy_temp_to_merge_branch run("checkout #{temp_merge_branch}") run("merge --strategy=ours --no-edit #{merge_branch}") run("checkout #{merge_branch}") run("merge #{temp_merge_branch}") squash_commits end |
#current_branch ⇒ Object
176 177 178 179 |
# File 'lib/flash_flow/git.rb', line 176 def current_branch run("rev-parse --abbrev-ref HEAD") last_stdout.strip end |
#delete_temp_merge_branch ⇒ Object
211 212 213 214 215 |
# File 'lib/flash_flow/git.rb', line 211 def delete_temp_merge_branch in_merge_branch do run("branch -d #{temp_merge_branch}") end end |
#fetch(remote) ⇒ Object
55 56 57 |
# File 'lib/flash_flow/git.rb', line 55 def fetch(remote) run("fetch #{remote}") end |
#fetch_remote_for_url(url) ⇒ Object
161 162 163 164 |
# File 'lib/flash_flow/git.rb', line 161 def fetch_remote_for_url(url) fetch_remotes = remotes.grep(Regexp.new(url)).grep(/ \(fetch\)/) fetch_remotes.map { |remote| remote.to_s.split("\t").first }.first end |
#in_branch(branch) ⇒ Object
225 226 227 228 229 230 231 232 233 234 |
# File 'lib/flash_flow/git.rb', line 225 def in_branch(branch) begin starting_branch = current_branch run("checkout #{branch}") yield ensure run("checkout #{starting_branch}") end end |
#in_merge_branch(&block) ⇒ Object
221 222 223 |
# File 'lib/flash_flow/git.rb', line 221 def in_merge_branch(&block) in_branch(merge_branch, &block) end |
#in_original_merge_branch ⇒ Object
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/flash_flow/git.rb', line 64 def in_original_merge_branch begin starting_branch = current_branch run("checkout #{merge_remote}/#{merge_branch}") yield ensure run("checkout #{starting_branch}") end end |
#in_temp_merge_branch(&block) ⇒ Object
217 218 219 |
# File 'lib/flash_flow/git.rb', line 217 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
29 30 31 |
# File 'lib/flash_flow/git.rb', line 29 def last_command @cmd_runner.last_command end |
#last_stdout ⇒ Object
25 26 27 |
# File 'lib/flash_flow/git.rb', line 25 def last_stdout @cmd_runner.last_stdout end |
#last_success? ⇒ Boolean
33 34 35 |
# File 'lib/flash_flow/git.rb', line 33 def last_success? @cmd_runner.last_success? end |
#master_branch_contains?(ref) ⇒ Boolean
59 60 61 62 |
# File 'lib/flash_flow/git.rb', line 59 def master_branch_contains?(ref) run("branch --contains #{ref}") last_stdout.split("\n").detect { |str| str[2..-1] == master_branch } end |
#merge(branch) ⇒ Object
51 52 53 |
# File 'lib/flash_flow/git.rb', line 51 def merge(branch) run("merge #{branch}") end |
#most_recent_commit ⇒ Object
181 182 183 |
# File 'lib/flash_flow/git.rb', line 181 def most_recent_commit run("show -s --format=%cd head") end |
#push(branch, options) ⇒ Object
47 48 49 |
# File 'lib/flash_flow/git.rb', line 47 def push(branch, ) run("push #{'-f' if options[:force]} #{merge_remote} #{branch}") end |
#push_merge_branch ⇒ Object
194 195 196 |
# File 'lib/flash_flow/git.rb', line 194 def push_merge_branch run("push -f #{merge_remote} #{merge_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 #{merge_remote}/#{merge_branch}:#{filename}") last_stdout end |
#remotes ⇒ Object
144 145 146 147 |
# File 'lib/flash_flow/git.rb', line 144 def remotes run('remote -v') last_stdout.split("\n") end |
#remotes_hash ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/flash_flow/git.rb', line 149 def remotes_hash return @remotes_hash if @remotes_hash @remotes_hash = {} remotes.each do |r| name = r.split[0] url = r.split[1] @remotes_hash[name] ||= url end @remotes_hash 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
185 186 187 188 189 190 191 192 |
# File 'lib/flash_flow/git.rb', line 185 def reset_temp_merge_branch in_branch(master_branch) do run("fetch #{merge_remote}") run("branch -D #{temp_merge_branch}") run("checkout -b #{temp_merge_branch}") run("reset --hard #{merge_remote}/#{master_branch}") end end |
#resolution_candidates(file) ⇒ Object
git rerere doesn’t give you a deterministic way to determine which resolution was used
130 131 132 133 134 135 136 137 138 |
# File 'lib/flash_flow/git.rb', line 130 def resolution_candidates(file) @cmd_runner.run("diff -q --from-file #{file} .git/rr-cache/*/postimage") different_files = split_diff_lines(@cmd_runner.last_stdout) @cmd_runner.run('ls -la .git/rr-cache/*/postimage') all_files = split_diff_lines(@cmd_runner.last_stdout) all_files - different_files end |
#resolutions(files) ⇒ Object
121 122 123 124 125 126 127 |
# File 'lib/flash_flow/git.rb', line 121 def resolutions(files) {}.tap do |hash| files.map do |file| hash[file] = resolution_candidates(file) end.flatten end end |
#run(cmd) ⇒ Object
37 38 39 |
# File 'lib/flash_flow/git.rb', line 37 def run(cmd) @cmd_runner.run("git #{cmd}") end |
#split_diff_lines(arr) ⇒ Object
140 141 142 |
# File 'lib/flash_flow/git.rb', line 140 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
166 167 168 169 |
# File 'lib/flash_flow/git.rb', line 166 def staged_and_working_dir_files run("status --porcelain") last_stdout.split("\n").reject { |line| line[0..1] == '??' } end |
#unresolved_conflicts ⇒ Object
115 116 117 118 119 |
# File 'lib/flash_flow/git.rb', line 115 def unresolved_conflicts conflicted_files.map do |file| File.open(file) { |f| f.grep(/>>>>/) }.empty? ? nil : file end.compact end |