Class: MultiRepo::MergeCommand
- Inherits:
-
Command
- Object
- CLAide::Command
- Command
- MultiRepo::MergeCommand
show all
- Defined in:
- lib/multirepo/commands/merge-command.rb
Class Method Summary
collapse
Instance Method Summary
collapse
-
#ask_tracking_files_update(all_merges_succeeded) ⇒ Object
-
#build_dependency_merge_descriptors(our_dependencies, their_dependencies, ref_name, mode) ⇒ Object
-
#build_merge(main_repo, initial_revision, ref_name, mode) ⇒ Object
-
#ensure_dependencies_match(our_dependencies, their_dependencies) ⇒ Object
-
#ensure_merge_valid(descriptors) ⇒ Object
-
#initialize(argv) ⇒ MergeCommand
constructor
A new instance of MergeCommand.
-
#merge_core(main_repo, initial_revision, mode) ⇒ Object
-
#message_for_mode(mode, ref_name) ⇒ Object
-
#perform_merges(descriptors) ⇒ Object
-
#preview_merge(descriptors, mode, ref_name) ⇒ Object
-
#run ⇒ Object
-
#validate! ⇒ Object
Methods inherited from Command
#ensure_in_work_tree, #ensure_multirepo_enabled, #ensure_multirepo_tracked, #install_hooks, #multirepo_enabled_dependencies, report_error, #uninstall_hooks, #update_gitconfig
Constructor Details
Returns a new instance of MergeCommand.
37
38
39
40
41
42
43
44
|
# File 'lib/multirepo/commands/merge-command.rb', line 37
def initialize(argv)
@ref_name = argv.shift_argument
@checkout_latest = argv.flag?("latest")
@checkout_lock = argv.flag?("as-lock")
@edit = argv.flag?("edit")
@fast_forward = argv.flag?("ff")
super
end
|
Class Method Details
.options ⇒ Object
27
28
29
30
31
32
33
34
35
|
# File 'lib/multirepo/commands/merge-command.rb', line 27
def self.options
[
['<refname>', 'The main repo tag, branch or commit id to merge.'],
['[--latest]', 'Merge the HEAD of each stored dependency branch instead of the commits recorded in the lock file.'],
['[--as-lock]', 'Merge the exact specified commits for each repo, as stored in the lock file.'],
['[--edit]', 'Open an editor to edit the commit message for each merge operation.'],
['[--ff]', 'Perform a fast-forward if possible.']
].concat(super)
end
|
Instance Method Details
#ask_tracking_files_update(all_merges_succeeded) ⇒ Object
230
231
232
233
234
235
236
237
238
|
# File 'lib/multirepo/commands/merge-command.rb', line 230
def ask_tracking_files_update(all_merges_succeeded)
unless all_merges_succeeded
Console.log_warning("Perform a 'multi update' after resolving merge conflicts to ensure lock file contents are valid")
return
end
update_command = UpdateCommand.new(CLAide::ARGV.new(["--diff", "--commit", "[multirepo] Post-merge tracking files update"]))
update_command.update_tracking_files_step(RepoSelection::MAIN)
end
|
#build_dependency_merge_descriptors(our_dependencies, their_dependencies, ref_name, mode) ⇒ Object
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/multirepo/commands/merge-command.rb', line 156
def build_dependency_merge_descriptors(our_dependencies, their_dependencies, ref_name, mode)
descriptors = []
our_dependencies.zip(their_dependencies).each do |our_dependency, their_dependency|
our_revision = our_dependency.config_entry.repo.current_revision
their_revision = RevisionSelector.revision_for_mode(mode, ref_name, their_dependency.lock_entry)
their_name = their_dependency.config_entry.name
their_repo = their_dependency.config_entry.repo
descriptor = MergeDescriptor.new(their_name, their_repo, our_revision, their_revision)
descriptors.push(descriptor)
end
return descriptors
end
|
#build_merge(main_repo, initial_revision, ref_name, mode) ⇒ Object
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# File 'lib/multirepo/commands/merge-command.rb', line 130
def build_merge(main_repo, initial_revision, ref_name, mode)
our_dependencies = Performer.depth_ordered_dependencies
commit_id = Ref.new(main_repo, ref_name).commit_id Performer.perform_main_repo_checkout(main_repo, commit_id, false, "Checked out main repo '#{ref_name}' to inspect to-merge dependencies")
their_dependencies = Performer.depth_ordered_dependencies
Performer.perform_main_repo_checkout(main_repo, initial_revision, false, "Checked out initial main repo revision '#{initial_revision}'")
ensure_dependencies_match(our_dependencies, their_dependencies)
descriptors = build_dependency_merge_descriptors(our_dependencies, their_dependencies, ref_name, mode)
descriptors.push(MergeDescriptor.new("Main Repo", main_repo, initial_revision, ref_name))
return descriptors
end
|
#ensure_dependencies_match(our_dependencies, their_dependencies) ⇒ Object
172
173
174
175
176
177
178
179
180
181
182
|
# File 'lib/multirepo/commands/merge-command.rb', line 172
def ensure_dependencies_match(our_dependencies, their_dependencies)
our_dependencies.zip(their_dependencies).each do |our_dependency, their_dependency|
if their_dependency.nil? || their_dependency.config_entry.id != our_dependency.config_entry.id
fail MultiRepoException, "Dependencies differ, please merge manually"
end
end
if their_dependencies.count > our_dependencies.count
fail MultiRepoException, "There are more dependencies in the specified ref, please merge manually"
end
end
|
#ensure_merge_valid(descriptors) ⇒ Object
#merge_core(main_repo, initial_revision, mode) ⇒ Object
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/multirepo/commands/merge-command.rb', line 83
def merge_core(main_repo, initial_revision, mode)
config_file = ConfigFile.new(".")
fail MultiRepoException, "Main repo is not clean; merge aborted" unless main_repo.clean?
unless Utils.dependencies_clean?(config_file.load_entries)
fail MultiRepoException, "Dependencies are not clean; merge aborted"
end
ref_name = @ref_name
descriptors = nil
loop do
descriptors = build_merge(main_repo, initial_revision, ref_name, mode)
preview_merge(descriptors, mode, ref_name)
result = ensure_merge_valid(descriptors)
case result.outcome
when MergeValidationResult::ABORT
fail MultiRepoException, result.message
when MergeValidationResult::PROCEED
fail MultiRepoException, "Merge aborted" unless Console.ask("Proceed?")
Console.log_warning(result.message) if result.message
break
when MergeValidationResult::MERGE_UPSTREAM
Console.log_warning(result.message)
fail MultiRepoException, "Merge aborted" unless Console.ask("Merge upstream instead of local branches?")
fail MultiRepoException, "Fallback behavior not implemented. Please merge manually."
next
end
fail MultiRepoException, "Merge aborted" unless Console.ask("Proceed?")
end
Console.log_step("Performing merge...")
all_succeeded = perform_merges(descriptors)
ask_tracking_files_update(all_succeeded)
end
|
#message_for_mode(mode, ref_name) ⇒ Object
240
241
242
243
244
245
246
247
248
249
|
# File 'lib/multirepo/commands/merge-command.rb', line 240
def message_for_mode(mode, ref_name)
case mode
when RevisionSelection::AS_LOCK
"merge specific commits as stored in the lock file for main repo revision #{ref_name}"
when RevisionSelection::LATEST
"merge each branch as stored in the lock file of main repo revision #{ref_name}"
when RevisionSelection::EXACT
"merge #{ref_name} for each repository, ignoring the contents of the lock file"
end
end
|
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
# File 'lib/multirepo/commands/merge-command.rb', line 213
def perform_merges(descriptors)
success = true
descriptors.each do |descriptor|
Console.log_substep("#{descriptor.name} : Merging #{descriptor.their_revision} into #{descriptor.our_revision}...")
GitRunner.run_as_system(descriptor.repo.path, "merge #{descriptor.their_revision}#{@edit ? '' : ' --no-edit'}#{@fast_forward ? '' : ' --no-ff'}")
success &= GitRunner.last_command_succeeded
end
if success
Console.log_info("All merges performed successfully!")
else
Console.log_warning("Some merge operations failed. Please review the above.")
end
return success
end
|
#preview_merge(descriptors, mode, ref_name) ⇒ Object
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/multirepo/commands/merge-command.rb', line 184
def preview_merge(descriptors, mode, ref_name)
Console.log_info("Merging would #{message_for_mode(mode, ref_name)}:")
table = Terminal::Table.new do |t|
descriptors.reverse.each_with_index do |descriptor, index|
t.add_row [descriptor.name.bold, descriptor.merge_description, descriptor.upstream_description]
t.add_separator unless index == descriptors.count - 1
end
end
puts table
end
|
#run ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/multirepo/commands/merge-command.rb', line 54
def run
ensure_in_work_tree
ensure_multirepo_enabled
mode = RevisionSelector.mode_for_args(@checkout_latest, @checkout_lock)
strategy_name = RevisionSelection.name_for_mode(mode)
Console.log_step("Merging #{@ref_name} with '#{strategy_name}' strategy...")
main_repo = Repo.new(".")
initial_revision = main_repo.current_revision
begin
merge_core(main_repo, initial_revision, mode)
rescue MultiRepoException => e
unless main_repo.current_revision == initial_revision
Console.log_warning("Restoring working copy to #{initial_revision}")
main_repo.checkout(initial_revision)
end
raise e
end
Console.log_step("Done!")
end
|
#validate! ⇒ Object
46
47
48
49
50
51
52
|
# File 'lib/multirepo/commands/merge-command.rb', line 46
def validate!
super
help! "You must specify a ref to merge" unless @ref_name
unless Utils.only_one_true?(@checkout_latest, @checkout_lock)
help! "You can't provide more than one operation modifier (--latest, --as-lock, etc.)"
end
end
|