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.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +21 -0
- data/bin/bp +5 -0
- data/bin/brightpearl +5 -0
- data/lib/brightpearl_cli.rb +351 -0
- data/lib/core/api.rb +7 -0
- data/lib/core/config.rb +175 -0
- data/lib/core/enums.rb +9 -0
- data/lib/core/git.rb +771 -0
- data/lib/core/jira.rb +43 -0
- data/lib/core/mysql.rb +48 -0
- data/lib/core/terminal.rb +389 -0
- data/lib/core/tools.rb +78 -0
- data/lib/core/validate.rb +7 -0
- data/lib/routes/build.rb +83 -0
- data/lib/routes/dummy_order.rb +151 -0
- data/lib/routes/git_branch.rb +55 -0
- data/lib/routes/git_checkout.rb +155 -0
- data/lib/routes/git_delete.rb +120 -0
- data/lib/routes/git_merge.rb +288 -0
- data/lib/routes/git_pull.rb +16 -0
- data/lib/routes/git_push.rb +16 -0
- data/lib/routes/git_stash.rb +27 -0
- data/lib/routes/git_update.rb +125 -0
- data/lib/routes/jira.rb +51 -0
- data/lib/routes/less.rb +37 -0
- data/lib/routes/reset.rb +33 -0
- data/lib/routes/review.rb +16 -0
- data/lib/routes/scripts_code_sniffer.rb +36 -0
- data/lib/routes/scripts_color.rb +52 -0
- data/lib/routes/setup.rb +15 -0
- data/lib/routes/tests.rb +69 -0
- data/lib/routes/update.rb +35 -0
- metadata +169 -0
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
|