-
Notifications
You must be signed in to change notification settings - Fork 11
/
repo_checker.rb
381 lines (288 loc) · 8.35 KB
/
repo_checker.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
82
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
129
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
class RepoChecker
def initialize
@repos = []
@repos_needing_a_pull = []
@repos_needing_a_push = []
@repos_not_on_master = []
@has_changes_to_be_committed = []
@has_changes_not_staged_for_commit = []
Dir.glob("../docs-*/") { |repo|
@repos.push(Repo.new repo)
@repos.reject!{|r| r.path.include? 'docs-utility'}
}
fetch_statuses
get_user_to_choose
end
def report
puts "All repos being tracked:"
@repos.each { |esr| puts "\t#{esr.path}" }
puts "-------------------------"
sort_repos @repos
puts "the following repos are even with origin/master:"
@even.each { |esr| puts "\t#{esr.path}" }
puts "-------------------------"
puts "the following repos need a pull:"
@repos_needing_a_pull.each { |npr| puts "\t#{npr.path}"}
puts "-------------------------"
puts "the following repos have changes not staged for commit"
@has_changes_not_staged_for_commit.each {|cnsc| puts "\t#{cnsc.path}"}
puts "-------------------------"
puts "the following repos have changes to be committed"
@has_changes_to_be_committed.each {|cnsc| puts "\t#{cnsc.path}"}
puts "-------------------------"
puts "the following repos need a push: "
@repos_needing_a_push.each { |npr| puts "\t#{npr.path}"}
puts "-------------------------"
puts "the following repos are not on master: "
@repos_not_on_master.each { |nmr| puts "\t#{nmr.path} is on branch |#{nmr.branch}|"}
puts "-------------------------"
puts "Other repos:"
( @repos - @repos_needing_a_pull - @repos_needing_a_push - @even) .each do |repo|
puts "~~~~~~~~~~~~~~~~~~~~~~~~~"
puts "Repo path:\n\t#{repo.path}!\n branch:\b\t#{repo.branch}\nstatus:\n\t#{repo.status}"
p repo.status
puts "~~~~~~~~~~~~~~~~~~~~~~~~~"
end
get_user_to_choose
end
def fetch_statuses
threads = []
@repos.each do |repo|
threads.push(
Thread.new do
Dir.chdir repo.path
branch = `git branch -a | grep '*'`.gsub(/[*\s]/, '')
Dir.chdir repo.path
status = `git fetch; git status`
{
repo: repo,
status: status,
branch: branch
}
end
)
end
threads.each do |t|
t.join
end
threads.each do |t|
repo = t.value[:repo]
status = t.value[:status]
branch = t.value[:branch]
repo.branch = branch
repo.status = status
end
report
end
def show_repos_lagging_behind_master
puts
puts
puts "Repos lagging behind master:"
unless @has_changes_to_be_committed.length
puts "no repos lag behind master"
return
end
@repos_needing_a_pull.each do |repo|
puts "\n-----------------------\n\n"
puts repo.path
puts
puts repo.status
puts "\n-----------------------\n\n"
end
get_user_to_choose
end
def show_has_changes_to_be_committed
puts
puts
puts "Repos with changes staged for commit:"
unless @has_changes_to_be_committed.length
puts "no repos have changes to be committed"
return
end
@has_changes_to_be_committed.each do |repo|
puts "\n-----------------------\n\n"
puts repo.path
puts
puts repo.status
puts "\n-----------------------\n\n"
end
get_user_to_choose
end
def show_has_changes_not_staged_for_commit
puts
puts
puts "Repos with changes not staged for commit:"
unless @has_changes_not_staged_for_commit.length
puts "no repos have changes to be committed"
return
end
@has_changes_not_staged_for_commit.each do |repo|
puts "\n-----------------------\n\n"
puts repo.path
puts
puts repo.status
puts "\n-----------------------\n\n"
end
get_user_to_choose
end
def stash_rebase_stashpop
threads = []
@repos_needing_a_pull.each do |repo|
threads.push(Thread.new do
Dir.chdir repo.path
status = `git fetch; git stash; git rebase; git stash pop`
{
repo: repo,
status: status
}
end)
end
threads.each do |t|
t.join
end
threads.each do |t|
repo = t.value[:repo]
if repo.status != t.value[:status]
p t.value[:status]
repo.status = t.value[:status]
end
end
report
end
def batch_commit_and_push_with_message
puts "this method is under construction"
return
# puts "*****************\nthis method is pretty dangerous; make sure you really want to commit and push everything. You should probably rebase first too."
threads = []
@repos_needing_a_push.each do |repo|
threads.push(Thread.new do
Dir.chdir repo.path
status = `git add .; git commit -m '#{message}'; git push`
{
repo: repo,
status: status
}
end)
end
threads.each do |t|
t.join
end
threads.each do |t|
t.value[:repo].status = t.value[:status]
end
get_user_to_choose
end
def quit
puts "goodbye!!"
exit
return nil
end
private
def get_urls
urls = @repos.map do |repo|
Dir.chdir repo.path
url = `git remote show origin | grep "Fetch" `
end
p urls
get_user_to_choose
end
def fetch_statuses_sequentially
@repos.each do |repo|
Dir.chdir repo.path
status = `git fetch; git status`
repo.status = status
end
get_user_to_choose
end
def sort_repos repos
needs_pull = []
needs_push = []
even = []
not_on_master = []
has_changes_to_be_committed = []
has_changes_not_staged_for_commit = []
repos.each do |repo|
even << repo if repo.status == "On branch master\nYour branch is up-to-date with 'origin/master'.\nnothing to commit, working directory clean\n"
needs_pull << repo if repo.status.include? "On branch master\nYour branch is behind 'origin/master'"
needs_push << repo if ( repo.status.include? "Changes not staged for commit:" and repo.status.include? "modified:")
not_on_master << repo unless repo.branch.include? "master"
has_changes_to_be_committed << repo if repo.status.include? "Changes to be committed"
has_changes_not_staged_for_commit << repo if repo.status.include? "Changes not staged for commit"
end
@repos_needing_a_push = needs_push
@repos_needing_a_pull = needs_pull
@even = even
@repos_not_on_master = not_on_master
@has_changes_to_be_committed = has_changes_to_be_committed
@has_changes_not_staged_for_commit = has_changes_not_staged_for_commit
return nil
end
attr_accessor :repos
def get_user_to_choose
choices = self.methods - self.class.superclass.new.methods
puts "please enter the number of your choice."
# choices.push('quit') unless choices.any? { |choice| choice == 'quit' }
3.times {puts}
choices.each_with_index do |choice, i|
puts "- #{i}: #{
choice
.to_s
.gsub('_', ' ')
.gsub('has changes', 'repos with changes')
}"
end
print "Choice: "
choice = user_choice = gets.downcase.gsub(/\s/, '_')
choice = choice.to_i
if self.respond_to? choices[choice]
self.send choices[choice]
elsif choice > choices.length - 1
get_user_to_choose
end
return nil
end
end
class Repo
attr_accessor :path, :status, :branch
@status
@path
@branch
def initialize path
@path = path
end
end
def interact rc
puts "what would you like to do next?"
puts "1: exit RepoChecker"
puts "2: view statuses of repos that need a pull"
puts "3: stash local changes, rebase, then stash pop all repos"
puts "4: get urls (really slow, under construction)"
puts "5: do the following to all repos_needing_a_push: git add. ; git commit -m 'message'; git rebase; git push"
puts "6: fetch fresh statuses"
print "your response:"
response = gets.chomp
if response == "2"
rc.show_repos_needing_a_pull
interact rc
elsif response == "3"
rc.stash_rebase_stashpop
rc.report
interact rc
elsif response == "4"
rc.get_urls
elsif response == "5"
puts
print "enter commit message: "
message = gets.chomp
rc.batch_push_with_message message
elsif response == "6"
rc.fetch_statuses
rc.report
interact rc
end
end
rc = RepoChecker.new
rc.fetch_statuses
# rc.stash_rebase_stashpop
rc.report
# interact rc