daq_flow 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +62 -0
- data/LICENSE.txt +22 -0
- data/README.md +165 -0
- data/Rakefile +10 -0
- data/bin/daq_flow +23 -0
- data/flash_flow.gemspec +28 -0
- data/flash_flow.yml.erb.example +42 -0
- data/lib/flash_flow.rb +7 -0
- data/lib/flash_flow/branch_merger.rb +55 -0
- data/lib/flash_flow/cmd_runner.rb +54 -0
- data/lib/flash_flow/config.rb +84 -0
- data/lib/flash_flow/data.rb +6 -0
- data/lib/flash_flow/data/base.rb +89 -0
- data/lib/flash_flow/data/bitbucket.rb +152 -0
- data/lib/flash_flow/data/branch.rb +124 -0
- data/lib/flash_flow/data/collection.rb +211 -0
- data/lib/flash_flow/data/github.rb +140 -0
- data/lib/flash_flow/data/store.rb +44 -0
- data/lib/flash_flow/git.rb +267 -0
- data/lib/flash_flow/install.rb +19 -0
- data/lib/flash_flow/lock.rb +23 -0
- data/lib/flash_flow/merge.rb +6 -0
- data/lib/flash_flow/merge/acceptance.rb +154 -0
- data/lib/flash_flow/merge/base.rb +116 -0
- data/lib/flash_flow/merge_order.rb +27 -0
- data/lib/flash_flow/notifier.rb +23 -0
- data/lib/flash_flow/options.rb +34 -0
- data/lib/flash_flow/resolve.rb +143 -0
- data/lib/flash_flow/shadow_repo.rb +44 -0
- data/lib/flash_flow/time_helper.rb +32 -0
- data/lib/flash_flow/version.rb +4 -0
- data/log/.keep +0 -0
- data/test/lib/data/test_base.rb +10 -0
- data/test/lib/data/test_branch.rb +206 -0
- data/test/lib/data/test_collection.rb +308 -0
- data/test/lib/data/test_store.rb +70 -0
- data/test/lib/lock/test_github.rb +74 -0
- data/test/lib/merge/test_acceptance.rb +230 -0
- data/test/lib/test_branch_merger.rb +78 -0
- data/test/lib/test_config.rb +63 -0
- data/test/lib/test_git.rb +73 -0
- data/test/lib/test_merge_order.rb +71 -0
- data/test/lib/test_notifier.rb +33 -0
- data/test/lib/test_resolve.rb +69 -0
- data/test/minitest_helper.rb +41 -0
- data/update_gem.sh +5 -0
- metadata +192 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
class Install
|
5
|
+
def self.install
|
6
|
+
FileUtils.mkdir 'config' unless Dir.exists?('config')
|
7
|
+
dest_file = 'config/flash_flow.yml.erb'
|
8
|
+
|
9
|
+
FileUtils.cp example_file, dest_file
|
10
|
+
|
11
|
+
puts "Flash flow config file is in #{dest_file}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.example_file
|
15
|
+
"#{File.dirname(__FILE__)}/../../flash_flow.yml.erb.example"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FlashFlow
|
2
|
+
module Lock
|
3
|
+
class Error < RuntimeError; end
|
4
|
+
|
5
|
+
class Base
|
6
|
+
def initialize(config=nil)
|
7
|
+
lock_class_name = config && config['class'] && config['class']['name']
|
8
|
+
return unless lock_class_name
|
9
|
+
|
10
|
+
lock_class = Object.const_get(lock_class_name)
|
11
|
+
@lock = lock_class.new(config['class'])
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_lock(&block)
|
15
|
+
if @lock
|
16
|
+
@lock.with_lock(&block)
|
17
|
+
else
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'flash_flow/merge/base'
|
2
|
+
require 'flash_flow/time_helper'
|
3
|
+
|
4
|
+
module FlashFlow
|
5
|
+
module Merge
|
6
|
+
class Acceptance < Base
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
super(opts)
|
10
|
+
|
11
|
+
@data = Data::Base.new(Config.configuration.branches, Config.configuration.branch_info_file, @git, logger: logger)
|
12
|
+
|
13
|
+
@do_not_merge = opts[:do_not_merge]
|
14
|
+
@force = opts[:force]
|
15
|
+
@rerere_forget = opts[:rerere_forget]
|
16
|
+
@stories = [opts[:stories]].flatten.compact
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
# check_version
|
21
|
+
check_git_version
|
22
|
+
check_repo
|
23
|
+
puts "Building #{@local_git.merge_branch}... Log can be found in #{FlashFlow::Config.configuration.log_file}"
|
24
|
+
logger.info "\n\n### Beginning #{@local_git.merge_branch} merge ###\n\n"
|
25
|
+
|
26
|
+
begin
|
27
|
+
open_pull_request
|
28
|
+
|
29
|
+
@lock.with_lock do
|
30
|
+
@git.in_original_merge_branch do
|
31
|
+
@git.initialize_rerere(@local_git.working_dir)
|
32
|
+
end
|
33
|
+
|
34
|
+
@git.reset_temp_merge_branch
|
35
|
+
@git.in_temp_merge_branch do
|
36
|
+
merge_branches(@data.mergeable) do |branch, merger|
|
37
|
+
# Do not merge the master branch or the merge branch
|
38
|
+
next if [@git.merge_branch, @git.master_branch].include?(branch.ref)
|
39
|
+
process_result(branch, merger)
|
40
|
+
end
|
41
|
+
commit_branch_info
|
42
|
+
commit_rerere
|
43
|
+
end
|
44
|
+
|
45
|
+
@git.copy_temp_to_branch(@git.merge_branch, commit_message)
|
46
|
+
@git.delete_temp_merge_branch
|
47
|
+
@git.push(@git.merge_branch)
|
48
|
+
end
|
49
|
+
|
50
|
+
raise OutOfSyncWithRemote.new("#{@git.merge_branch} is out of sync with the remote.") unless @git.last_success?
|
51
|
+
print_errors
|
52
|
+
logger.info "### Finished #{@local_git.merge_branch} merge ###"
|
53
|
+
rescue Lock::Error, OutOfSyncWithRemote => e
|
54
|
+
puts 'Failure!'
|
55
|
+
puts e.message
|
56
|
+
ensure
|
57
|
+
@local_git.run("checkout #{@local_git.working_branch}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def commit_branch_info
|
62
|
+
@stories.each do |story_id|
|
63
|
+
@data.add_story(@git.working_branch, story_id)
|
64
|
+
end
|
65
|
+
@data.save!
|
66
|
+
end
|
67
|
+
|
68
|
+
def commit_rerere
|
69
|
+
current_branches = @data.to_a.select { |branch| !@git.master_branch_contains?(branch.sha) && (Time.now - branch.updated_at < TimeHelper.two_weeks) }
|
70
|
+
current_rereres = current_branches.map { |branch| branch.resolutions.to_h.values }.flatten
|
71
|
+
|
72
|
+
@git.commit_rerere(current_rereres)
|
73
|
+
end
|
74
|
+
|
75
|
+
def process_result(branch, merger)
|
76
|
+
case merger.result
|
77
|
+
when :deleted
|
78
|
+
@data.mark_deleted(branch)
|
79
|
+
@notifier.deleted_branch(branch) unless is_working_branch(branch)
|
80
|
+
|
81
|
+
when :success
|
82
|
+
branch.sha = merger.sha
|
83
|
+
@data.mark_success(branch)
|
84
|
+
@data.set_resolutions(branch, merger.resolutions)
|
85
|
+
|
86
|
+
when :conflict
|
87
|
+
if is_working_branch(branch)
|
88
|
+
@data.mark_failure(branch, merger.conflict_sha)
|
89
|
+
else
|
90
|
+
@data.mark_failure(branch, nil)
|
91
|
+
@notifier.merge_conflict(branch)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def is_working_branch(branch)
|
97
|
+
branch.ref == @git.working_branch
|
98
|
+
end
|
99
|
+
|
100
|
+
def open_pull_request
|
101
|
+
return false if [@local_git.master_branch, @local_git.merge_branch].include?(@local_git.working_branch)
|
102
|
+
|
103
|
+
@local_git.push(@local_git.working_branch, @force)
|
104
|
+
raise OutOfSyncWithRemote.new("Your branch is out of sync with the remote. If you want to force push, run 'flash_flow -f'") unless @local_git.last_success?
|
105
|
+
|
106
|
+
if @do_not_merge
|
107
|
+
@data.remove_from_merge(@local_git.working_branch)
|
108
|
+
else
|
109
|
+
@data.add_to_merge(@local_git.working_branch)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def print_errors
|
114
|
+
puts format_errors
|
115
|
+
end
|
116
|
+
|
117
|
+
def format_errors
|
118
|
+
errors = []
|
119
|
+
branch_not_merged = nil
|
120
|
+
@data.failures.each do |branch|
|
121
|
+
if branch.ref == @local_git.working_branch
|
122
|
+
branch_not_merged = "ERROR: Your branch did not merge to #{@local_git.merge_branch}. Run 'flash_flow --resolve', fix the merge conflict(s) and then re-run this script\n"
|
123
|
+
else
|
124
|
+
errors << "WARNING: Unable to merge branch #{@local_git.remote}/#{branch.ref} to #{@local_git.merge_branch} due to conflicts."
|
125
|
+
end
|
126
|
+
end
|
127
|
+
errors << branch_not_merged if branch_not_merged
|
128
|
+
|
129
|
+
if errors.empty?
|
130
|
+
"Success!"
|
131
|
+
else
|
132
|
+
errors.join("\n")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def commit_message
|
137
|
+
message =<<-EOS
|
138
|
+
Flash Flow run from branch: #{@local_git.working_branch}
|
139
|
+
|
140
|
+
Merged branches:
|
141
|
+
#{@data.successes.empty? ? 'None' : @data.successes.sort_by(&:merge_order).map(&:ref).join("\n")}
|
142
|
+
|
143
|
+
Failed branches:
|
144
|
+
#{@data.failures.empty? ? 'None' : @data.failures.map(&:ref).join("\n")}
|
145
|
+
|
146
|
+
Removed branches:
|
147
|
+
#{@data.removals.empty? ? 'None' : @data.removals.map(&:ref).join("\n")}
|
148
|
+
EOS
|
149
|
+
message.gsub(/'/, '')
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'flash_flow/git'
|
4
|
+
require 'flash_flow/data'
|
5
|
+
require 'flash_flow/lock'
|
6
|
+
require 'flash_flow/notifier'
|
7
|
+
require 'flash_flow/branch_merger'
|
8
|
+
require 'flash_flow/merge_order'
|
9
|
+
require 'flash_flow/shadow_repo'
|
10
|
+
|
11
|
+
module FlashFlow
|
12
|
+
module Merge
|
13
|
+
class Base
|
14
|
+
|
15
|
+
class VersionError < RuntimeError; end
|
16
|
+
class OutOfSyncWithRemote < RuntimeError; end
|
17
|
+
class UnmergeableBranch < RuntimeError; end
|
18
|
+
class NothingToMergeError < RuntimeError; end
|
19
|
+
|
20
|
+
def initialize(opts={})
|
21
|
+
@local_git = Git.new(Config.configuration.git, logger)
|
22
|
+
@git = ShadowGit.new(Config.configuration.git, logger)
|
23
|
+
@lock = Lock::Base.new(Config.configuration.lock)
|
24
|
+
@notifier = Notifier::Base.new(Config.configuration.notifier)
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger
|
28
|
+
@logger ||= FlashFlow::Config.configuration.logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def check_repo
|
32
|
+
if @local_git.staged_and_working_dir_files.any?
|
33
|
+
raise RuntimeError.new('You have changes in your working directory. Please stash and try again')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_version
|
38
|
+
data_version = @data.version
|
39
|
+
return if data_version.nil?
|
40
|
+
|
41
|
+
written_version = data_version.split(".").map(&:to_i)
|
42
|
+
running_version = FlashFlow::VERSION.split(".").map(&:to_i)
|
43
|
+
|
44
|
+
unless written_version[0] < running_version[0] ||
|
45
|
+
(written_version[0] == running_version[0] && written_version[1] <= running_version[1]) # Ignore the point release number
|
46
|
+
raise RuntimeError.new("Your version of flash flow (#{FlashFlow::VERSION}) is behind the version that was last used (#{data_version}) by a member of your team. Please upgrade to at least #{written_version[0]}.#{written_version[1]}.0 and try again.")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_git_version
|
51
|
+
git_version = @local_git.version
|
52
|
+
return if git_version.nil?
|
53
|
+
|
54
|
+
running_version = git_version.split(".").map(&:to_i)
|
55
|
+
expected_version = FlashFlow::GIT_VERSION.split(".").map(&:to_i)
|
56
|
+
|
57
|
+
if running_version[0] < expected_version[0] ||
|
58
|
+
(running_version[0] == expected_version[0] && running_version[1] < expected_version[1]) # Ignore the point release number
|
59
|
+
puts "Warning: Your version of git (#{git_version}) is behind the version that is tested (#{FlashFlow::GIT_VERSION}). We recommend to upgrade to at least #{expected_version[0]}.#{expected_version[1]}.0"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def merge_branches(branches)
|
64
|
+
ordered_branches = MergeOrder.new(@git, branches).get_order
|
65
|
+
ordered_branches.each_with_index do |branch, index|
|
66
|
+
branch.merge_order = index + 1
|
67
|
+
|
68
|
+
merger = git_merge(branch)
|
69
|
+
|
70
|
+
yield(branch, merger)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def git_merge(branch)
|
75
|
+
merger = BranchMerger.new(@git, branch)
|
76
|
+
forget_rerere = is_working_branch(branch) && @rerere_forget
|
77
|
+
|
78
|
+
merger.do_merge(forget_rerere)
|
79
|
+
|
80
|
+
merger
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_working_branch(branch)
|
84
|
+
branch.ref == @git.working_branch
|
85
|
+
end
|
86
|
+
|
87
|
+
def pending_release
|
88
|
+
@data.pending_release
|
89
|
+
end
|
90
|
+
|
91
|
+
def ready_to_merge_release
|
92
|
+
@data.ready_to_merge_release
|
93
|
+
end
|
94
|
+
|
95
|
+
def release_ahead_of_master?
|
96
|
+
@git.ahead_of_master?("#{@git.remote}/#{@git.release_branch}")
|
97
|
+
end
|
98
|
+
|
99
|
+
def write_data(commit_msg)
|
100
|
+
@git.in_temp_merge_branch do
|
101
|
+
@git.run("reset --hard #{@git.remote}/#{@git.merge_branch}")
|
102
|
+
end
|
103
|
+
@git.in_merge_branch do
|
104
|
+
@git.run("reset --hard #{@git.remote}/#{@git.merge_branch}")
|
105
|
+
end
|
106
|
+
|
107
|
+
@data.save!
|
108
|
+
|
109
|
+
@git.copy_temp_to_branch(@git.merge_branch, commit_msg)
|
110
|
+
@git.delete_temp_merge_branch
|
111
|
+
@git.push(@git.merge_branch, false)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module FlashFlow
|
2
|
+
class MergeOrder
|
3
|
+
|
4
|
+
def initialize(git, branches)
|
5
|
+
@git = git
|
6
|
+
@branches = branches
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_order
|
10
|
+
new_branches, old_branches = @branches.partition { |branch| branch.merge_order.nil? }
|
11
|
+
branches = old_branches.sort_by(&:merge_order) + new_branches
|
12
|
+
|
13
|
+
unchanged, changed = branches.partition { |branch| current_sha(branch) == branch.sha }
|
14
|
+
my_branch_index = changed.find_index { |branch| branch.ref == @git.working_branch }
|
15
|
+
my_branch_changed = my_branch_index ? changed.delete_at(my_branch_index) : nil
|
16
|
+
|
17
|
+
[unchanged, changed, my_branch_changed].flatten.compact
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def current_sha(branch)
|
23
|
+
@git.get_sha("#{@git.remote}/#{branch.ref}")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'flash_flow/data'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
module Notifier
|
5
|
+
class Base
|
6
|
+
def initialize(config=nil)
|
7
|
+
notifier_class_name = config && config['class'] && config['class']['name']
|
8
|
+
return unless notifier_class_name
|
9
|
+
|
10
|
+
@notifier_class = Object.const_get(notifier_class_name)
|
11
|
+
@notifier = @notifier_class.new(config['class'])
|
12
|
+
end
|
13
|
+
|
14
|
+
def merge_conflict(branch)
|
15
|
+
@notifier.merge_conflict(branch) if @notifier.respond_to?(:merge_conflict)
|
16
|
+
end
|
17
|
+
|
18
|
+
def deleted_branch(branch)
|
19
|
+
@notifier.deleted_branch(branch) if @notifier.respond_to?(:deleted_branch)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
class Options
|
5
|
+
def self.parse
|
6
|
+
options = {}
|
7
|
+
opt_parser = OptionParser.new do |opts|
|
8
|
+
opts.banner = 'Usage: flash_flow [options]'
|
9
|
+
opts.separator ''
|
10
|
+
|
11
|
+
opts.on('--install', 'Copy flash_flow.yml.erb to your repo and exit') { |v| options[:install] = true }
|
12
|
+
opts.on('-v', '--version', 'Print the current version of flash flow and exit') { |v| options[:version] = true }
|
13
|
+
opts.on('-n', '--no-merge', 'Run flash flow, but do not merge this branch') { |v| options[:do_not_merge] = true }
|
14
|
+
opts.on('--rerere-forget', 'Delete the saved patch for this branch and let the merge fail if there is a conflict') { |v| options[:rerere_forget] = true }
|
15
|
+
opts.on('-f', '--force-push', 'Force push your branch') { |v| options[:force] = v }
|
16
|
+
opts.on('-c', '--config-file FILE_PATH', 'The path to your config file. Defaults to config/flash_flow.yml.erb') { |v| options[:config_file] = v }
|
17
|
+
opts.on('--resolve', 'Launch a bash shell to save your conflict resolutions') { |v| options[:resolve] = true }
|
18
|
+
opts.on('--resolve-manual', 'Print instructions to use git to resolve conflicts') { |v| options[:resolve_manual] = true }
|
19
|
+
|
20
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
21
|
+
puts opts
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
opt_parser.parse!
|
27
|
+
|
28
|
+
options[:stories] ||= []
|
29
|
+
options[:config_file] ||= './config/flash_flow.yml.erb'
|
30
|
+
|
31
|
+
options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'flash_flow/git'
|
4
|
+
require 'flash_flow/data'
|
5
|
+
|
6
|
+
module FlashFlow
|
7
|
+
class Resolve
|
8
|
+
|
9
|
+
class NothingToResolve < StandardError; end
|
10
|
+
|
11
|
+
def initialize(git_config, branch_info_file, opts={})
|
12
|
+
@logger = opts[:logger]
|
13
|
+
@branch_info_file = branch_info_file
|
14
|
+
@cmd_runner = CmdRunner.new(logger: @logger)
|
15
|
+
@git = ShadowGit.new(git_config, @logger)
|
16
|
+
end
|
17
|
+
|
18
|
+
def manual_instructions
|
19
|
+
check_for_conflict
|
20
|
+
puts manual_not_merged_instructions
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
check_for_conflict
|
25
|
+
|
26
|
+
in_working_branch do
|
27
|
+
merge_conflicted
|
28
|
+
|
29
|
+
if unresolved_conflicts.empty?
|
30
|
+
puts "You have already resolved all conflicts."
|
31
|
+
else
|
32
|
+
launch_bash
|
33
|
+
|
34
|
+
rerere
|
35
|
+
|
36
|
+
unless unresolved_conflicts.empty?
|
37
|
+
puts "There are still unresolved conflicts in these files:\n#{unresolved_conflicts.join("\n")}\n\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
git_reset
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def unresolved_conflicts
|
46
|
+
@git.unresolved_conflicts
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge_conflicted
|
50
|
+
@git.run("checkout #{branch.conflict_sha}")
|
51
|
+
@git.run("merge #{@git.remote}/#{working_branch}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def git_reset
|
55
|
+
@git.run("reset --hard HEAD")
|
56
|
+
end
|
57
|
+
|
58
|
+
def rerere
|
59
|
+
@git.run("rerere")
|
60
|
+
end
|
61
|
+
|
62
|
+
def bash_message
|
63
|
+
puts "\nNote: You are in a special flash_flow directory (#{Dir.pwd}). The files still open in your editor will not reflect the merge conflicts, open them from this shell to get the conflicted versions.\n\nPlease fix the following conflicts and then 'exit':\n#{unresolved_conflicts.join("\n")}\n\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
def launch_bash
|
67
|
+
bash_message
|
68
|
+
|
69
|
+
with_init_file do |file|
|
70
|
+
system("bash --init-file #{file} -i")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_init_file
|
75
|
+
filename = '.flash_flow_init'
|
76
|
+
File.open(filename, 'w') do |f|
|
77
|
+
f.puts(init_file_contents)
|
78
|
+
end
|
79
|
+
|
80
|
+
yield filename
|
81
|
+
|
82
|
+
File.delete(filename)
|
83
|
+
end
|
84
|
+
|
85
|
+
def manual_not_merged_instructions
|
86
|
+
<<-EOS
|
87
|
+
|
88
|
+
Run the following commands to fix the merge conflict and then re-run flash_flow:
|
89
|
+
pushd #{flash_flow_directory}
|
90
|
+
git checkout #{branch.conflict_sha}
|
91
|
+
git merge #{working_branch}
|
92
|
+
# Resolve the conflicts
|
93
|
+
git add <conflicted files>
|
94
|
+
git commit --no-edit
|
95
|
+
popd
|
96
|
+
|
97
|
+
EOS
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def data
|
103
|
+
@data ||= Data::Base.new({}, @branch_info_file, @git, logger: @logger)
|
104
|
+
end
|
105
|
+
|
106
|
+
def branch
|
107
|
+
@branch ||= data.saved_branches.detect { |branch| branch.ref == working_branch }
|
108
|
+
end
|
109
|
+
|
110
|
+
def working_branch
|
111
|
+
@git.working_branch
|
112
|
+
end
|
113
|
+
|
114
|
+
def in_working_branch
|
115
|
+
@git.in_dir do
|
116
|
+
@git.in_branch(working_branch) do
|
117
|
+
yield
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def flash_flow_directory
|
123
|
+
@git.flash_flow_dir
|
124
|
+
end
|
125
|
+
|
126
|
+
def init_file_contents
|
127
|
+
<<-EOS
|
128
|
+
# Commented this one out because it was causing lots of spurious "saving session..." type messages
|
129
|
+
# [[ -s /etc/profile ]] && source /etc/profile
|
130
|
+
[[ -s ~/.bash_profile ]] && source ~/.bash_profile
|
131
|
+
[[ -s ~/.bash_login ]] && source ~/.bash_login
|
132
|
+
[[ -s ~/.profile ]] && source ~/.profile
|
133
|
+
[[ -s ~/.bashrc ]] && source ~/.bashrc
|
134
|
+
|
135
|
+
PS1='flash_flow resolve: (type "exit" after your conflicts are resolved)$ '
|
136
|
+
EOS
|
137
|
+
end
|
138
|
+
|
139
|
+
def check_for_conflict
|
140
|
+
raise NothingToResolve.new("The current branch (#{working_branch}) does not appear to be in conflict.") unless branch.conflict_sha
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|