brightpearl-cli 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/core/git.rb ADDED
@@ -0,0 +1,771 @@
1
+ require 'columnist'
2
+ require 'date'
3
+ require 'highline'
4
+
5
+ module Brightpearl
6
+
7
+ class Git
8
+
9
+ include Columnist
10
+
11
+ DELIMITER = '*|*'
12
+
13
+ SORT_DATE = 'date'
14
+ SORT_REFNAME = 'refname'
15
+
16
+ LOCAL = 'local'
17
+ REMOTE = 'remote'
18
+ CODE = 'code'
19
+ DB = 'db'
20
+
21
+ MERGED_PREFIX = 'MERGED-'
22
+ MDASH = '━'
23
+
24
+ MASTER = 'master'
25
+ REFNAME = 'refname'
26
+ OBJECT_TYPE = 'objecttype'
27
+ OBJECT_SIZE = 'objectsize'
28
+ OBJECT_NAME = 'objectname'
29
+ TREE = 'tree'
30
+ NUM_PARENT = 'numparent'
31
+ COMMITTER_NAME = 'committername'
32
+ COMMITTER_EMAIL = 'committeremail'
33
+ COMMITTER_DATE = 'committerdate'
34
+ SUBJECT = 'subject'
35
+ UPSTREAM = 'upstream'
36
+
37
+ BRANCH_NAME = 'branch_name'
38
+ BRANCH_LOCATION = 'branch_location'
39
+ BRANCH_EXISTS = 'branch_exists'
40
+ BRANCH_EXISTS_LOCALLY = 'branch_exists_locally'
41
+ BRANCH_IS_CURRENT = 'branch_is_current'
42
+ BRANCH_IS_UP_TO_DATE = 'branch_is_up_to_date'
43
+ BRANCH_HAS_STASH = 'branch_has_stash'
44
+ BRANCH_HAS_UPSTREAM = 'branch_has_upstream'
45
+
46
+ def initialize
47
+
48
+ @origin_updated_code = false
49
+ @origin_updated_db = false
50
+ @branch_upstream_data = false
51
+ @branches_as_array = {
52
+ :local_code => nil,
53
+ :local_db => nil,
54
+ :local_both => nil,
55
+ :remote_code => nil,
56
+ :remote_db => nil,
57
+ :remote_both => nil
58
+ }
59
+ @branches_as_array_all = false
60
+
61
+ end
62
+
63
+ # Gets detailed info about local branches as Array.
64
+ # @return Array
65
+ def get_local_branches(sort = SORT_REFNAME, repo_dir = nil)
66
+ repos = []
67
+ repos_to_return = []
68
+ validate_sort(sort)
69
+ if repo_dir.nil?
70
+ repo_loop.each do |repo_dir_inner|
71
+ repos << repo_dir_inner
72
+ end
73
+ else
74
+ validate_repo_dir(repo_dir)
75
+ repos << repo_dir
76
+ end
77
+ repos.each do |repo_dir_inner|
78
+ unless File.directory?(repo_dir_inner)
79
+ Brightpearl::Terminal::error('Directory not found', "Directory doesn't exist: #{Brightpearl::Terminal::format_directory(repo_dir_inner)}", true)
80
+ end
81
+ raw_terminal_output = `
82
+ cd #{repo_dir_inner} &&
83
+ git for-each-ref refs/heads/ --format='%(#{REFNAME})#{DELIMITER}%(#{OBJECT_TYPE})#{DELIMITER}%(#{OBJECT_SIZE})#{DELIMITER}%(#{OBJECT_NAME})#{DELIMITER}%(tree)#{DELIMITER}%(#{NUM_PARENT})#{DELIMITER}%(#{COMMITTER_NAME})#{DELIMITER}%(#{COMMITTER_EMAIL})#{DELIMITER}%(#{COMMITTER_DATE})#{DELIMITER}%(#{SUBJECT})#{DELIMITER}%(#{UPSTREAM})#{DELIMITER}' | sed 's/refs\\/heads\\///g'
84
+ `
85
+ branches = {}
86
+ branch_count = 0
87
+ raw_terminal_output.split("\n").each do |line|
88
+ line_split = line.split(DELIMITER)
89
+ data = {}
90
+ data[:"#{REFNAME}"] = line_split[0]
91
+ data[:"#{OBJECT_TYPE}"] = line_split[1]
92
+ data[:"#{OBJECT_SIZE}"] = line_split[2]
93
+ data[:"#{OBJECT_NAME}"] = line_split[3]
94
+ data[:"#{TREE}"] = line_split[4]
95
+ data[:"#{NUM_PARENT}"] = line_split[5]
96
+ data[:"#{COMMITTER_NAME}"] = line_split[6]
97
+ data[:"#{COMMITTER_EMAIL}"] = line_split[7][1..-2]
98
+ data[:"#{COMMITTER_DATE}"] = DateTime.parse(line_split[8])
99
+ data[:"#{SUBJECT}"] = line_split[9]
100
+ data[:"#{UPSTREAM}"] = line_split[10]
101
+ case sort
102
+ when SORT_REFNAME
103
+ branches[data[:"#{REFNAME}"]] = data
104
+ when SORT_DATE
105
+ branches["#{data[:"#{COMMITTER_DATE}"].strftime('%Y-%m-%d-%H-%I-%S')}-#{branch_count}"] = data
106
+ branch_count = branch_count + 1
107
+ else
108
+ Brightpearl::Terminal::error('Sort not supported', "The following sorting option is not yet supported: #{sort}", true)
109
+ end
110
+ end
111
+ branch_keys = branches.keys
112
+ case sort
113
+ when SORT_REFNAME
114
+ branch_keys.sort_by!(&:downcase)
115
+ when SORT_DATE
116
+ branch_keys.sort_by! { |value| value }
117
+ branch_keys = branch_keys.reverse
118
+ else
119
+ Brightpearl::Terminal::error('Sort not supported', "The following sorting option is not yet supported: #{sort}", true)
120
+ end
121
+ branch_data = []
122
+ branch_keys.each do |key|
123
+ branch_data << branches["#{key}"]
124
+ end
125
+ repos_to_return << branch_data
126
+ end
127
+ if repo_dir.nil?
128
+ return repos_to_return[0], repos_to_return[1]
129
+ else
130
+ repos_to_return[0]
131
+ end
132
+ end
133
+
134
+ # Gets detailed info about remote branches as Array.
135
+ # @return Array
136
+ def get_remote_branches(sort = SORT_REFNAME, repo_dir = nil)
137
+ repos = []
138
+ repos_to_return = []
139
+ validate_sort(sort)
140
+ if repo_dir.nil?
141
+ repo_loop.each do |repo_dir_inner|
142
+ repos << repo_dir_inner
143
+ end
144
+ else
145
+ validate_repo_dir(repo_dir)
146
+ repos << repo_dir
147
+ end
148
+ repos.each do |repo_dir_inner|
149
+ unless File.directory?(repo_dir_inner)
150
+ Brightpearl::Terminal::error('Directory not found', "Directory doesn't exist: #{Brightpearl::Terminal::format_directory(repo_dir)}", true)
151
+ end
152
+ update_origin(repo_dir_inner)
153
+ raw_terminal_output = `
154
+ cd #{repo_dir_inner} &&
155
+ for branch in \`git branch -r | grep -v HEAD\`; do echo \`git show --format="%cn#{DELIMITER}%ce#{DELIMITER}%cd#{DELIMITER}%s#{DELIMITER}" $branch | head -n 1\` $branch; done | sort -r | sed 's/origin\\///g'
156
+ `
157
+ branches = {}
158
+ branch_count = 0
159
+ raw_terminal_output.split("\n").each do |line|
160
+ line_split = line.split(DELIMITER)
161
+ data = {}
162
+ data[:"#{COMMITTER_NAME}"] = line_split[0]
163
+ data[:"#{COMMITTER_EMAIL}"] = line_split[1]
164
+ data[:"#{COMMITTER_DATE}"] = DateTime.parse(line_split[2])
165
+ data[:"#{SUBJECT}"] = line_split[3]
166
+ data[:"#{REFNAME}"] = line_split[4].to_s.strip
167
+ case sort
168
+ when SORT_REFNAME
169
+ branches[data[:"#{REFNAME}"]] = data
170
+ when SORT_DATE
171
+ branches["#{data[:"#{COMMITTER_DATE}"].strftime('%Y-%m-%d-%H-%I-%S')}-#{branch_count}"] = data
172
+ branch_count = branch_count + 1
173
+ else
174
+ Brightpearl::Terminal::error('Sort not supported', "The following sorting option is not yet supported: #{sort}", true)
175
+ end
176
+ end
177
+ branch_keys = branches.keys
178
+ case sort
179
+ when SORT_REFNAME
180
+ branch_keys.sort_by!(&:downcase)
181
+ when SORT_DATE
182
+ branch_keys.sort_by! { |value| value }
183
+ branch_keys = branch_keys.reverse
184
+ else
185
+ Brightpearl::Terminal::error('Sort not supported', "The following sorting option is not yet supported: #{sort}", true)
186
+ end
187
+ branch_data = []
188
+ branch_keys.each do |key|
189
+ branch_data << branches["#{key}"]
190
+ end
191
+ repos_to_return << branch_data
192
+ end
193
+ if repo_dir.nil?
194
+ return repos_to_return[0], repos_to_return[1]
195
+ else
196
+ repos_to_return[0]
197
+ end
198
+ end
199
+
200
+ # Gets branch names as array.
201
+ # @return Array
202
+ def get_branches_as_array(local_remote = LOCAL, repo_dir = nil)
203
+ validate_local_remote(local_remote)
204
+
205
+ # Check if result is already cached.
206
+ if repo_dir.nil?
207
+ if local_remote == LOCAL
208
+ return @branches_as_array[:local_both] if @branches_as_array[:local_both] != nil
209
+ else
210
+ return @branches_as_array[:remote_both] if @branches_as_array[:remote_both] != nil
211
+ end
212
+ else
213
+ if repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)
214
+ if local_remote == LOCAL
215
+ return @branches_as_array[:local_code] if @branches_as_array[:local_code] != nil
216
+ else
217
+ return @branches_as_array[:remote_code] if @branches_as_array[:remote_code] != nil
218
+ end
219
+ else
220
+ if local_remote == LOCAL
221
+ return @branches_as_array[:local_db] if @branches_as_array[:local_db] != nil
222
+ else
223
+ return @branches_as_array[:remote_db] if @branches_as_array[:remote_db] != nil
224
+ end
225
+ end
226
+ end
227
+
228
+ case local_remote
229
+ when LOCAL
230
+ if repo_dir.nil?
231
+ brightpearl_code, brightpearl_db = get_local_branches
232
+ repos_branches = [brightpearl_code, brightpearl_db]
233
+ else
234
+ branches = get_local_branches(SORT_REFNAME, repo_dir)
235
+ repos_branches = [branches]
236
+ end
237
+ else
238
+ if repo_dir.nil?
239
+ brightpearl_code, brightpearl_db = get_remote_branches
240
+ repos_branches = [brightpearl_code, brightpearl_db]
241
+ else
242
+ branches = get_remote_branches(SORT_REFNAME, repo_dir)
243
+ repos_branches = [branches]
244
+ end
245
+ end
246
+ repos_to_return = []
247
+ repos_branches.each do |repo_data|
248
+ branch_names = []
249
+ repo_data.each do |branch_data|
250
+ branch_names << branch_data[:"#{REFNAME}"]
251
+ end
252
+ repos_to_return << branch_names
253
+ end
254
+ if repo_dir.nil?
255
+ if local_remote == LOCAL
256
+ return @branches_as_array[:local_both] = repos_to_return[0], repos_to_return[1]
257
+ else
258
+ return @branches_as_array[:remote_both] = repos_to_return[0], repos_to_return[1]
259
+ end
260
+ else
261
+ if repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)
262
+ if local_remote == LOCAL
263
+ return @branches_as_array[:local_code] = repos_to_return[0]
264
+ else
265
+ return @branches_as_array[:remote_code] = repos_to_return[0]
266
+ end
267
+ else
268
+ if local_remote == LOCAL
269
+ return @branches_as_array[:local_db] = repos_to_return[0]
270
+ else
271
+ return @branches_as_array[:remote_db] = repos_to_return[0]
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ # Gets EVERY SINGLE BRANCH that exists -- local & remote, code & db -- and puts them in a single, unique, array.
278
+ # @return Array
279
+ def get_all_branches_as_array
280
+ unless @branches_as_array_all
281
+ local_branches = get_branches_as_array(Brightpearl::Git::LOCAL)
282
+ remote_branches = get_branches_as_array(Brightpearl::Git::REMOTE)
283
+ @branches_as_array_all = local_branches[0].concat(local_branches[1]).concat(remote_branches[0]).concat(remote_branches[1])
284
+ @branches_as_array_all.uniq!
285
+ @branches_as_array_all.sort_by! { |m| m.downcase }
286
+ end
287
+ @branches_as_array_all
288
+ end
289
+
290
+ # Outputs list of branches to terminal.
291
+ # @return void
292
+ def show_branches(sort = SORT_REFNAME, local_remote = LOCAL)
293
+ # todo
294
+ puts
295
+ puts "\x1B[31mTODO!\x1B[0m Must do something with 'terminal_width' parameter."
296
+ puts
297
+ validate_sort(sort)
298
+ validate_local_remote(local_remote)
299
+ # terminal_width = HighLine::SystemExtensions.terminal_size
300
+ # terminal_width = terminal_width[0]
301
+ case local_remote
302
+ when LOCAL
303
+ brightpearl_code, brightpearl_db = get_local_branches(sort)
304
+ else
305
+ brightpearl_code, brightpearl_db = get_remote_branches(sort)
306
+ end
307
+ current_code_branch = current_branch_for_repo(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE))
308
+ current_db_branch = current_branch_for_repo(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB))
309
+ column_width = [2, 20, 23, 15, 34, 1, 34, 15, 23, 20, 1]
310
+ Brightpearl::Tools::validate_report_width(column_width)
311
+ puts "\n"
312
+ table(:border => false) do
313
+ row do
314
+ column('', :align => 'right', :bold => 'true', :width => column_width[0])
315
+ column('Last Activity', :align => 'right', :bold => 'true', :width => column_width[1])
316
+ column('Developer', :align => 'right', :bold => 'true', :width => column_width[2])
317
+ column('Last Commit', :align => 'right', :bold => 'true', :width => column_width[3])
318
+ column('BRIGHTPEARL-CODE', :align => 'right', :bold => 'true', :width => column_width[4], :color => 32)
319
+ column('|', :align => 'center', :bold => 'true', :width => column_width[5])
320
+ column('BRIGHTPEARL-DB', :align => 'left', :bold => 'true', :width => column_width[6], :color => 160)
321
+ column('Last Commit', :align => 'left', :bold => 'true', :width => column_width[7])
322
+ column('Developer', :align => 'left', :bold => 'true', :width => column_width[8])
323
+ column('Last Activity', :align => 'left', :bold => 'true', :width => column_width[9])
324
+ column('', :align => 'left', :bold => 'true', :width => column_width[10])
325
+ end
326
+ show_branches_divider(column_width)
327
+ db_branches_shown = []
328
+ brightpearl_code.each do |code_branch|
329
+ db_branch = show_branches_get_db_branch(brightpearl_db, code_branch)
330
+ if db_branch[:"#{REFNAME}"] != MDASH
331
+ db_branches_shown << db_branch[:"#{REFNAME}"]
332
+ # branch_data = branch_data(code_branch[:"#{REFNAME}"])
333
+ else
334
+ # branch_data = branch_data(code_branch[:"#{REFNAME}"], CODE)
335
+ end
336
+ code_time_adjusted = code_branch[:"#{COMMITTER_DATE}"] - (1 / 24.0)
337
+ row do
338
+ code_accent, code_color, code_star, db_accent, db_color, db_star = show_branches_get_colors(code_branch, current_code_branch, current_db_branch, db_branch)
339
+ column("#{code_star}", :color => code_color)
340
+ column(Brightpearl::Tools::time_passed_since(code_time_adjusted), :color => code_color)
341
+ column(code_branch[:"#{COMMITTER_NAME}"], :color => code_color)
342
+ column(code_branch[:"#{COMMITTER_DATE}"].strftime('%d %^b %H:%M'), :color => code_color)
343
+ column(code_branch[:"#{REFNAME}"], :color => code_accent)
344
+ column('|')
345
+ column(db_branch[:"#{REFNAME}"], :color => db_accent)
346
+ column((db_branch[:"#{COMMITTER_DATE}"] == nil) ? MDASH : db_branch[:"#{COMMITTER_DATE}"].strftime('%d %^b %H:%M'), :color => db_color)
347
+ column(db_branch[:"#{COMMITTER_NAME}"], :color => db_color)
348
+ column((db_branch[:"#{COMMITTER_DATE}"] == nil) ? MDASH : Brightpearl::Tools::time_passed_since(db_branch[:"#{COMMITTER_DATE}"] - (1 / 24.0)), :color => db_color)
349
+ column("#{db_star}", :color => db_color)
350
+ end
351
+ end
352
+ brightpearl_db.each do |db_branch|
353
+ unless db_branches_shown.include? db_branch[:"#{REFNAME}"]
354
+ row do
355
+ code_accent, code_color, code_star, db_accent, db_color, db_star = show_branches_get_colors(nil, current_code_branch, current_db_branch, db_branch)
356
+ column('', :color => code_color)
357
+ column(MDASH, :color => code_color)
358
+ column(MDASH, :color => code_color)
359
+ column(MDASH, :color => code_color)
360
+ column(MDASH, :color => code_accent)
361
+ column('|')
362
+ column(db_branch[:"#{REFNAME}"], :color => db_accent)
363
+ column((db_branch[:"#{COMMITTER_DATE}"] == nil) ? MDASH : db_branch[:"#{COMMITTER_DATE}"].strftime('%d %^b %H:%M'), :color => db_color)
364
+ column(db_branch[:"#{COMMITTER_NAME}"], :color => db_color)
365
+ column((db_branch[:"#{COMMITTER_DATE}"] == nil) ? MDASH : Brightpearl::Tools::time_passed_since(db_branch[:"#{COMMITTER_DATE}"]), :color => db_color)
366
+ column('')
367
+ end
368
+ end
369
+ end
370
+ show_branches_divider(column_width)
371
+ end
372
+ puts "\n"
373
+ end
374
+
375
+ # Sub-method for 'show_branches'. Don't call independently.
376
+ # @return String(s)
377
+ def show_branches_get_colors(code_branch, current_code_branch, current_db_branch, db_branch)
378
+ code_star = nil
379
+ code_color = 240
380
+ code_accent = nil
381
+ db_star = nil
382
+ db_color = 240
383
+ db_accent = nil
384
+ current_branch_color = 46
385
+ unless code_branch.nil?
386
+ if current_code_branch == code_branch[:"#{REFNAME}"]
387
+ code_star = "\xe2\x98\x85"
388
+ code_color = current_branch_color
389
+ code_accent = current_branch_color
390
+ end
391
+ end
392
+ unless db_branch.nil?
393
+ if current_db_branch == db_branch[:"#{REFNAME}"]
394
+ db_star = "\xe2\x98\x85"
395
+ db_color = current_branch_color
396
+ db_accent = current_branch_color
397
+ end
398
+ end
399
+ return code_accent, code_color, code_star, db_accent, db_color, db_star
400
+ end
401
+
402
+ # Sub-method for 'show_branches'. Don't call independently.
403
+ # @return void
404
+ def show_branches_get_db_branch(brightpearl_db, code_branch)
405
+ brightpearl_db.each do |db_branch|
406
+ if db_branch[:"#{REFNAME}"] == code_branch[:"#{REFNAME}"]
407
+ return db_branch
408
+ end
409
+ end
410
+ db_branch = {}
411
+ db_branch[:"#{REFNAME}"] = MDASH
412
+ db_branch[:"#{COMMITTER_NAME}"] = MDASH
413
+ db_branch[:"#{COMMITTER_DATE}"] = nil
414
+ db_branch
415
+ end
416
+
417
+ # Sub-method for 'show_branches'. Don't call independently.
418
+ # @return void
419
+ def show_branches_divider(column_width, color = 'white')
420
+ row do
421
+ column(Brightpearl::Terminal::fill(column_width[0], MDASH), :color => color)
422
+ column(Brightpearl::Terminal::fill(column_width[1], MDASH), :color => color)
423
+ column(Brightpearl::Terminal::fill(column_width[2], MDASH), :color => color)
424
+ column(Brightpearl::Terminal::fill(column_width[3], MDASH), :color => color)
425
+ column(Brightpearl::Terminal::fill(column_width[4], MDASH), :color => color)
426
+ column(Brightpearl::Terminal::fill(column_width[5], MDASH), :color => color)
427
+ column(Brightpearl::Terminal::fill(column_width[6], MDASH), :color => color)
428
+ column(Brightpearl::Terminal::fill(column_width[7], MDASH), :color => color)
429
+ column(Brightpearl::Terminal::fill(column_width[8], MDASH), :color => color)
430
+ column(Brightpearl::Terminal::fill(column_width[9], MDASH), :color => color)
431
+ column(Brightpearl::Terminal::fill(column_width[10], MDASH), :color => color)
432
+ end
433
+ end
434
+
435
+ # Get current branch for repo.
436
+ # @return String
437
+ def current_branch_for_repo(repo_dir)
438
+ validate_repo_dir(repo_dir)
439
+ `cd #{repo_dir} && git symbolic-ref --short -q HEAD`.strip
440
+ end
441
+
442
+ # Updates origin (IE: remote branches)
443
+ # @return void
444
+ def update_origin(repo_dir = nil)
445
+ validate_repo_dir(repo_dir)
446
+ if @origin_updated_code && repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE) ||
447
+ @origin_updated_db && repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB) ||
448
+ @origin_updated_code && @origin_updated_db && repo_dir.nil?
449
+ else
450
+ Brightpearl::Terminal::output("Updating origin (#{get_repo_shorthand(repo_dir)})")
451
+ case repo_dir
452
+ when Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)
453
+ @origin_updated_code = true
454
+ Brightpearl::Terminal::command(['git fetch -p'], Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE))
455
+ when Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB)
456
+ @origin_updated_db = true
457
+ Brightpearl::Terminal::command(['git fetch -p'], Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB))
458
+ else
459
+ @origin_updated_code = true
460
+ @origin_updated_db = true
461
+ repo_loop.each do |repo_dir_inner|
462
+ Brightpearl::Terminal::command(['git fetch -p'], repo_dir_inner)
463
+ end
464
+ end
465
+ end
466
+ end
467
+
468
+ # Merges master into current branch (for repo) and pushes changes to origin.
469
+ # @deprecated
470
+ # @return void
471
+ def merge_master_into_current_branch(repo_dir, push_to_origin = true)
472
+ current_branch = current_branch_for_repo(repo_dir)
473
+ if current_branch == Brightpearl::Git::MASTER
474
+ return
475
+ end
476
+ commands = Array.new
477
+ commands << 'git checkout master'
478
+ commands << 'git pull'
479
+ if current_branch != Brightpearl::Git::MASTER
480
+ commands << "git checkout #{current_branch}"
481
+ commands << 'git pull'
482
+ commands << 'git merge master'
483
+ end
484
+ if push_to_origin
485
+ commands << 'git push'
486
+ end
487
+ Brightpearl::Terminal::command(commands, repo_dir)
488
+ end
489
+
490
+ # Makes sure that both BP-CODE & BP-DB are on the same branch.
491
+ # @return void
492
+ # @deprecated
493
+ def verify_same_branch
494
+ branch_names = Array.new
495
+ repo_loop.each do |repo_dir|
496
+ branch_names << current_branch_for_repo(repo_dir)
497
+ end
498
+ if branch_names[0] != branch_names[1]
499
+ puts
500
+ puts "\x1B[41m ERROR \x1B[0m Cannot continue because your repos are not on the same branch."
501
+ puts
502
+ puts "\x1B[33m/brightpearl-code\x1B[0m is on: \x1B[32m#{branch_names[0]}\x1B[0m"
503
+ puts "\x1B[33m/brightpearl-db \x1B[0m is on: \x1B[32m#{branch_names[1]}\x1B[0m"
504
+ puts
505
+ puts "Use \x1B[33mbrightpearl checkout\x1B[0m \x1B[32m[branch-name]\x1B[0m to switch both repos to the same branch."
506
+ puts
507
+ exit
508
+ end
509
+ branch_names[0]
510
+ end
511
+
512
+ # Checks if you have staged changes in current repo and if so, prompts to stash them.
513
+ # @return void
514
+ def stash_staged_changes
515
+ repo_loop.each do |repo_dir|
516
+ results = `cd #{repo_dir} && git status | grep 'Changes '`
517
+ results = results.split("\n")
518
+ if results.any?
519
+ Brightpearl::Terminal::command(['git status'], repo_dir)
520
+ current_branch = current_branch_for_repo(repo_dir)
521
+ if Brightpearl::Terminal::prompt_yes_no("Found uncommitted files on branch #{Brightpearl::Terminal::format_branch(current_branch)}", nil, "Would you like to #{Brightpearl::Terminal::format_action('stash')}\x1B[38;5;89m these changes before continuing?")
522
+ Brightpearl::Terminal::command('git stash', repo_dir)
523
+ else
524
+ unless Brightpearl::Terminal::prompt_yes_no('Continue without stashing?', "By selecting #{Brightpearl::Terminal::format_action('Yes')}\x1B[38;5;240m, you're changes will be carried over to the next branch.", nil, false)
525
+ Brightpearl::Terminal::abort(nil, nil, true, false)
526
+ end
527
+ end
528
+ end
529
+ end
530
+ end
531
+
532
+ # Checks if you currently have stashed changes for current branch and if so, prompt to un-stash them.
533
+ # @return void
534
+ def check_for_stash
535
+ repo_loop.each do |repo_dir|
536
+ results = check_for_stash_get_stashes(repo_dir)
537
+ if results.any?
538
+ results_output = Array.new
539
+ results.each do |result|
540
+ results_output << "#{result}"
541
+ end
542
+ stashes_to_skip = 0
543
+ while results.any?
544
+ stash_name = results[0].split(/:/).first
545
+ if Brightpearl::Terminal::prompt_yes_no("Found the following stash on #{Brightpearl::Terminal::format_branch(current_branch_for_repo(repo_dir))}", "#{results[0]}", "Would you like to #{Brightpearl::Terminal::format_action('apply')}\x1B[38;5;89m this stash now?")
546
+ stash_apply_successful = Brightpearl::Terminal::command(["git stash apply #{stash_name}"], repo_dir)
547
+ if stash_apply_successful[0] == true
548
+ Brightpearl::Terminal::command("git stash drop #{stash_name}", repo_dir)
549
+ results = check_for_stash_get_stashes(repo_dir)
550
+ else
551
+ Brightpearl::Terminal::error("Stash could not be applied successfully (and therefore wasn't dropped).", ["#{results[0]}", nil, "Please #{Brightpearl::Terminal::format_action('open an IDE')} and resolve your conflicts before continuing.", "Don't forget to drop your stash afterwards with: #{Brightpearl::Terminal::format_command("git stash drop #{stash_name}")}"], false)
552
+ results = []
553
+ end
554
+ else
555
+ stashes_to_skip = stashes_to_skip + 1
556
+ results = check_for_stash_get_stashes(repo_dir)
557
+ a = (stashes_to_skip + 0)
558
+ b = 0
559
+ while b < a do
560
+ results.shift
561
+ b += 1
562
+ end
563
+ end
564
+ end
565
+ end
566
+ end
567
+ end
568
+
569
+ # Sub-method for 'show_branches'. Don't call independently.
570
+ # @return Array
571
+ def check_for_stash_get_stashes(repo_dir)
572
+ results = `cd #{repo_dir} && git stash list | grep 'WIP on #{current_branch_for_repo(repo_dir)}:'`
573
+ results = results.split("\n")
574
+ end
575
+
576
+ # Returns an array that include info for BOTH repos. Finds out whether a branch exists and if it's current or not
577
+ # Only does it locally.
578
+ # @return Array
579
+ def branch_data(branch_name, code_db = nil, verbose = true)
580
+ data = []
581
+ repo_loop.each do |repo_dir|
582
+ unless code_db.nil?
583
+ validate_code_db(code_db)
584
+ case code_db
585
+ when CODE
586
+ if repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB)
587
+ data << nil
588
+ next
589
+ end
590
+ else
591
+ if repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)
592
+ data << nil
593
+ next
594
+ end
595
+ end
596
+ end
597
+ Brightpearl::Terminal::output("Retrieving branch data for #{Brightpearl::Terminal::format_branch(branch_name)} \xe2\x80\x94 (#{get_repo_shorthand(repo_dir)})")
598
+ repo_data = {}
599
+ repo_data
600
+ repo_data[:"#{BRANCH_NAME}"] = branch_name
601
+ repo_data[:"#{BRANCH_LOCATION}"] = repo_dir
602
+ repo_data[:"#{BRANCH_EXISTS}"] = true
603
+ repo_data[:"#{BRANCH_EXISTS_LOCALLY}"] = true
604
+ repo_data[:"#{BRANCH_HAS_STASH}"] = false
605
+ repo_data[:"#{BRANCH_HAS_UPSTREAM}"] = branch_has_upstream(repo_dir, branch_name)
606
+ repo_data[:"#{BRANCH_IS_CURRENT}"] = (current_branch_for_repo(repo_dir) == branch_name ? true : false)
607
+ if repo_data[:"#{BRANCH_HAS_UPSTREAM}"]
608
+ # @todo
609
+ repo_data[:"#{BRANCH_IS_UP_TO_DATE}"] = nil
610
+ else
611
+ # @todo
612
+ repo_data[:"#{BRANCH_IS_UP_TO_DATE}"] = nil
613
+ end
614
+ # Check branch exists
615
+ unless branch_exists(branch_name, repo_dir, Brightpearl::Git::LOCAL)
616
+ repo_data[:"#{BRANCH_EXISTS_LOCALLY}"] = false
617
+ Brightpearl::Terminal::warning("Branch #{Brightpearl::Terminal::format_branch(branch_name)} not found #{Brightpearl::Terminal::format_action('locally')} - (#{get_repo_shorthand(repo_dir)})", nil) if verbose
618
+ Brightpearl::Terminal::output('Checking origin') if verbose
619
+ unless branch_exists(branch_name, repo_dir, Brightpearl::Git::REMOTE)
620
+ Brightpearl::Terminal::warning("Branch #{Brightpearl::Terminal::format_branch(branch_name)} not found #{Brightpearl::Terminal::format_action('remotely')} - (#{get_repo_shorthand(repo_dir)})", nil) if verbose
621
+ repo_data[:"#{BRANCH_EXISTS}"] = false
622
+ data << repo_data
623
+ next
624
+ end
625
+ end
626
+ # Check for stashed changes
627
+ stashes = `cd #{repo_dir} && git stash list | grep 'WIP on #{branch_name}:'`
628
+ stashes = stashes.split("\n")
629
+ if stashes.any?
630
+ repo_data[:"#{BRANCH_HAS_STASH}"] = stashes.count
631
+ end
632
+ data << repo_data
633
+ end
634
+ data
635
+ end
636
+
637
+ # Returns TRUE if branch exists, FALSE if not
638
+ # @return Array
639
+ def branch_exists(branch_name, repo_dir, local_remote = LOCAL)
640
+ validate_repo_dir(repo_dir)
641
+ validate_local_remote(local_remote)
642
+ case local_remote
643
+ when LOCAL
644
+ branches = get_branches_as_array(LOCAL, repo_dir)
645
+ else
646
+ branches = get_branches_as_array(REMOTE, repo_dir)
647
+ end
648
+ unless branches.include?(branch_name)
649
+ return false
650
+ end
651
+ true
652
+ end
653
+
654
+ # Checks if branch exists ANYWHERE -- Local, Remote, Code, DB. If the branch name is found anywhere, will return FALSE.
655
+ # @return boolean
656
+ def branch_exists_anywhere(branch_name, case_sensitive = false)
657
+ existing_branches = get_all_branches_as_array
658
+ if case_sensitive
659
+ existing_branches.map!(&:downcase)
660
+ branch_name.downcase!
661
+ end
662
+ unless existing_branches.include?(branch_name)
663
+ return false
664
+ end
665
+ true
666
+ end
667
+
668
+ # Checks if a branch has an upstream (remote) branch. Returns TRUE or FALSE.
669
+ # @return boolean
670
+ # @deprecated
671
+ def branch_has_upstream(repo_dir, branch_name)
672
+ validate_repo_dir(repo_dir)
673
+ result = `cd #{repo_dir} && git branch -vv | grep 'origin/#{branch_name}'`
674
+ result == '' ? false : true
675
+ end
676
+
677
+ # Checks if a branch is at same HEAD as upstream. Returns TRUE or FALSE.
678
+ # @return boolean
679
+ # @deprecated
680
+ def branch_synced_with_upstream(repo_dir, branch_name)
681
+ validate_repo_dir(repo_dir)
682
+ result = `cd #{repo_dir} && git branch -vv | grep 'origin/#{branch_name}'`
683
+ result == '' ? false : true
684
+ end
685
+
686
+ # Gets upstream info for a branch
687
+ # @return hash
688
+ def branch_upstream_info(branch_name)
689
+ unless @branch_upstream_data
690
+ @branch_upstream_data = []
691
+ repo_loop.each do |repo_dir|
692
+ output = `git for-each-ref --shell --format='
693
+ b=%(refname:short)
694
+ u=${b}'@{upstream}'
695
+ if git rev-parse --verify --quiet "$u" >/dev/null 2>&1; then
696
+ test -n "$(git rev-list -n 1 "$u..$b")" &&
697
+ echo "$b: has unpushed commits"
698
+ else
699
+ echo "$b: no upstream configuration" >&2
700
+ fi
701
+ ' refs/heads | sh`
702
+
703
+ @branch_upstream_data << output
704
+ end
705
+ end
706
+ puts @branch_upstream_data
707
+ end
708
+
709
+ # Checks if a branch is up-to-date with its remote
710
+ # @return boolea
711
+ def branch_is_up_to_date(repo_dir, branch_name)
712
+ validate_repo_dir(repo_dir)
713
+ result_local = `cd #{repo_dir} && git rev-parse #{branch_name}`
714
+ result_remote = `cd #{repo_dir} && git rev-parse origin/#{branch_name}`
715
+ result_local == result_remote ? true : false
716
+
717
+ end
718
+
719
+ # Returns array with the paths to both repos.
720
+ # @return Array
721
+ def repo_loop
722
+ Array[
723
+ Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE),
724
+ Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB)
725
+ ]
726
+ end
727
+
728
+ # Validates that a parameter is either 'local' or 'remote'
729
+ # @return void
730
+ def validate_local_remote(local_remote)
731
+ unless Array[LOCAL, REMOTE].include?(local_remote)
732
+ ("'#{local_remote}' is not a valid parameter. Must be LOCAL or REMOTE.")
733
+ end
734
+ end
735
+
736
+ # Validates that a parameter is either 'code' or 'db'
737
+ # @return void
738
+ def validate_code_db(code_db)
739
+ unless Array[CODE, DB].include?(code_db)
740
+ abort("'#{code_db}' is not a valid parameter. Must be CODE or DB.")
741
+ end
742
+ end
743
+
744
+ # Makes sure the repo directory is valid.
745
+ # @return void
746
+ def validate_repo_dir(repo_dir)
747
+ unless Array[
748
+ Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE),
749
+ Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB)
750
+ ].include?(repo_dir)
751
+ abort("'#{repo_dir}' is not a valid directory.")
752
+ end
753
+ end
754
+
755
+ # Validates if sort option is supported.
756
+ # @return void
757
+ def validate_sort(sort_option)
758
+ unless Array[SORT_DATE, SORT_REFNAME].include?(sort_option)
759
+ abort("'#{sort_option}' is not a valid sort option.")
760
+ end
761
+ end
762
+
763
+ # Returns short-hand string for repo
764
+ # @return String
765
+ def get_repo_shorthand(repo_dir)
766
+ repo_dir == Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE) ? 'brightpearl-code' : 'brightpearl-db'
767
+ end
768
+
769
+ end
770
+
771
+ end