git-maintain 0.9.0 → 0.12.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/branch.rb CHANGED
@@ -10,16 +10,15 @@ module GitMaintain
10
10
 
11
11
  class Branch
12
12
  ACTION_LIST = [
13
- :cp, :steal, :list, :list_stable,
14
- :merge, :push, :monitor,
15
- :push_stable, :monitor_stable,
13
+ :cp, :steal, :list,
14
+ :merge, :pull, :push, :monitor,
16
15
  :release, :reset, :create, :delete
17
16
  ]
18
17
  NO_FETCH_ACTIONS = [
19
18
  :cp, :merge, :monitor, :release, :delete
20
19
  ]
21
20
  NO_CHECKOUT_ACTIONS = [
22
- :create, :delete, :list, :list_stable, :push, :monitor, :monitor_stable
21
+ :create, :delete, :list, :push, :monitor
23
22
  ]
24
23
  ALL_BRANCHES_ACTIONS = [
25
24
  :create
@@ -30,12 +29,10 @@ module GitMaintain
30
29
  :delete => "Delete all local branches using the suffix",
31
30
  :steal => "Steal commit from upstream that fixes commit in the branch or were tagged as stable",
32
31
  :list => "List commit present in the branch but not in the stable branch",
33
- :list_stable => "List commit present in the stable branch but not in the latest associated relase",
34
32
  :merge => "Merge branch with suffix specified in -m <suff> into the main branch",
35
33
  :push => "Push branches to github for validation",
34
+ :pull => "Rebase branches on top of the upstream one",
36
35
  :monitor => "Check the CI state of all branches",
37
- :push_stable => "Push to stable repo",
38
- :monitor_stable => "Check the CI state of all stable branches",
39
36
  :release => "Create new release on all concerned branches",
40
37
  :reset => "Reset branch against upstream",
41
38
  }
@@ -58,6 +55,7 @@ module GitMaintain
58
55
  opts[:watch] = false
59
56
  opts[:delete_remote] = false
60
57
  opts[:no_edit] = false
58
+ opts[:stable] = false
61
59
 
62
60
  optsParser.on("-v", "--base-version [MIN_VER]", Integer, "Older release to consider.") {
63
61
  |val| opts[:base_ver] = val}
@@ -84,41 +82,49 @@ module GitMaintain
84
82
  when :delete
85
83
  optsParser.on("--remote", "Delete the remote staging branch instead of the local ones.") {
86
84
  |val| opts[:delete_remote] = true}
85
+ when :list
86
+ optsParser.on("--stable", "List unreleased commits in the upstream stable branch.") {
87
+ opts[:stable] = true }
87
88
  when :merge
88
89
  optsParser.banner += "-m <suffix>"
89
90
  optsParser.on("-m", "--merge [SUFFIX]", "Merge branch with suffix.") {
90
91
  |val| opts[:do_merge] = val}
91
- when :monitor, :monitor_stable
92
+ when :monitor
92
93
  optsParser.on("-w", "--watch <PERIOD>", Integer,
93
94
  "Watch and refresh CI status every <PERIOD>.") {
94
95
  |val| opts[:watch] = val}
96
+ optsParser.on("--stable", "Check CI status on stable repo.") {
97
+ opts[:stable] = true }
98
+ when :pull
99
+ optsParser.on("--stable", "List unreleased commits in the upstream stable branch.") {
100
+ opts[:stable] = true }
95
101
  when :push
96
102
  optsParser.banner += "[-f]"
97
103
  optsParser.on("-f", "--force", "Add --force to git push (for 'push' action).") {
98
- |val| opts[:push_force] = val}
99
- when :push_stable
104
+ opts[:push_force] = true}
105
+ optsParser.on("--stable", "Push to stable repo.") {
106
+ opts[:stable] = true }
100
107
  optsParser.banner += "[-T]"
101
108
  optsParser.on("-T", "--no-ci", "Ignore CI build status and push anyway.") {
102
- |val| opts[:no_ci] = true}
109
+ opts[:no_ci] = true}
103
110
  optsParser.on("-c", "--check", "Check if there is something to be pushed.") {
104
- |val| opts[:check_only] = true}
111
+ opts[:check_only] = true}
105
112
  when :release
106
- optsParser.on("--no-edit", "Do not edit release commit nor tag.") {
107
- opts[:no_edit] = true }
113
+ optsParser.on("--no-edit", "Do not edit release commit nor tag.") {
114
+ opts[:no_edit] = true }
108
115
  when :steal
109
116
  optsParser.banner += "[-a][-b <HEAD>]"
110
117
  optsParser.on("-a", "--all", "Check all commits from master. "+
111
- "By default only new commits (since last successful run) are considered.") {
118
+ "By default only new commits (since last successful run) are considered.") {
112
119
  |val| opts[:steal_base] = :all}
113
120
  optsParser.on("-b", "--base <HEAD>", "Check all commits from this commit. "+
114
- "By default only new commits (since last successful run) are considered.") {
121
+ "By default only new commits (since last successful run) are considered.") {
115
122
  |val| opts[:steal_base] = val}
116
123
  end
117
124
  end
118
125
 
119
126
  def self.check_opts(opts)
120
- if opts[:action] == :push_stable ||
121
- opts[:action] == :release then
127
+ if opts[:action] == :release then
122
128
  if opts[:br_suff] != "master" then
123
129
  raise "Action #{opts[:action]} can only be done on 'master' suffixed branches"
124
130
  end
@@ -128,6 +134,11 @@ module GitMaintain
128
134
  raise "Action #{opts[:action]} can NOT be done on 'master' suffixed branches"
129
135
  end
130
136
  end
137
+ if opts[:action] == :push
138
+ if opts[:stable] == true && opts[:push_force] == true then
139
+ raise "Action push can NOT be use both --stable and --force"
140
+ end
141
+ end
131
142
  opts[:version] = [ /.*/ ] if opts[:version].length == 0
132
143
  end
133
144
 
@@ -192,6 +203,8 @@ module GitMaintain
192
203
  sleep(opts[:watch])
193
204
  ci.emptyCache()
194
205
  end
206
+ GitMaintain::log(:INFO, "Done working on selected branches")
207
+
195
208
  end
196
209
 
197
210
  def initialize(repo, version, ci, branch_suff)
@@ -213,9 +226,15 @@ module GitMaintain
213
226
  @verbose_name = version
214
227
  end
215
228
 
216
- @head = @repo.runGit("rev-parse --verify --quiet #{@local_branch}")
229
+ @head = @repo.ref_exist?(@local_branch)
230
+ @valid_ref = "#{@repo.valid_repo}/#{@local_branch}"
217
231
  @remote_ref = "#{@repo.stable_repo}/#{@remote_branch}"
218
- @stable_head = @repo.runGit("rev-parse --verify --quiet #{@remote_ref}")
232
+ @stable_head =
233
+ begin
234
+ @repo.ref_exist?(@remote_ref)
235
+ rescue
236
+ nil
237
+ end
219
238
  case @branch_type
220
239
  when :std
221
240
  @stable_base = @repo.findStableBase(@local_branch)
@@ -223,7 +242,7 @@ module GitMaintain
223
242
  @stable_base = @remote_ref
224
243
  end
225
244
  end
226
- attr_reader :version, :local_branch, :head, :remote_branch, :remote_ref, :stable_head,
245
+ attr_reader :version, :local_branch, :head, :remote_branch, :valid_ref, :remote_ref, :stable_head,
227
246
  :verbose_name, :exists, :stable_base
228
247
 
229
248
  def log(lvl, str)
@@ -243,9 +262,10 @@ module GitMaintain
243
262
 
244
263
  # Checkout the repo to the given branch
245
264
  def checkout()
246
- print @repo.runGit("checkout -q #{@local_branch}")
247
- if $? != 0 then
248
- raise "Error: Failed to checkout the branch"
265
+ begin
266
+ print @repo.runGit("checkout -q #{@local_branch}")
267
+ rescue RuntimeError => e
268
+ crit("Failed to checkout the branch #{@local_branch}")
249
269
  end
250
270
  end
251
271
 
@@ -254,15 +274,16 @@ module GitMaintain
254
274
  opts[:commits].each(){|commit|
255
275
  prev_head=@repo.runGit("rev-parse HEAD")
256
276
  log(:INFO, "Applying #{@repo.getCommitHeadline(commit)}")
257
- @repo.runGitInteractive("cherry-pick #{commit}")
258
- if $? != 0 then
277
+ begin
278
+ @repo.runGitInteractive("cherry-pick #{commit}")
279
+ rescue RuntimeError
259
280
  log(:WARNING, "Cherry pick failure. Starting bash for manual fixes. Exit shell to continue")
260
- @repo.runBash()
261
- end
281
+ @repo.runBash("PS1_WARNING='CP FIX'")
282
+ end
262
283
  new_head=@repo.runGit("rev-parse HEAD")
263
284
  # Do not make commit pretty if it was not applied
264
285
  if new_head != prev_head
265
- make_pretty(commit)
286
+ make_pretty(commit)
266
287
  end
267
288
  }
268
289
  end
@@ -274,22 +295,26 @@ module GitMaintain
274
295
  # If we are not force checking everything,
275
296
  # try to start from the last tag we steal upto
276
297
  case opts[:steal_base]
277
- when nil
298
+ when nil
299
+ begin
278
300
  sha = @repo.runGit("rev-parse 'git-maintain/steal/last/#{@stable_base}' 2>&1")
279
- if $? == 0 then
280
- base_ref=sha
281
- log(:VERBOSE, "Starting from last successfull run:")
282
- log(:VERBOSE, @repo.getCommitHeadline(base_ref))
283
- end
284
- when :all
285
- base_ref=@stable_base
286
- else
301
+ base_ref=sha
302
+ log(:VERBOSE, "Starting from last successfull run:")
303
+ log(:VERBOSE, @repo.getCommitHeadline(base_ref))
304
+ rescue RuntimeError
305
+ # No matching tag found. Not an issue
306
+ end
307
+ when :all
308
+ base_ref=@stable_base
309
+ else
310
+ begin
287
311
  sha = @repo.runGit("rev-parse #{opts[:steal_base]} 2>&1")
288
- if $? == 0 then
289
- base_ref=sha
290
- log(:VERBOSE, "Starting from base:")
291
- log(:VERBOSE, @repo.getCommitHeadline(base_ref))
292
- end
312
+ base_ref=sha
313
+ log(:VERBOSE, "Starting from base:")
314
+ log(:VERBOSE, @repo.getCommitHeadline(base_ref))
315
+ rescue RuntimeError
316
+ crit("Could not find specified base '#{opts[:steal_base]}'")
317
+ end
293
318
  end
294
319
 
295
320
  master_sha=@repo.runGit("rev-parse origin/master")
@@ -305,16 +330,15 @@ module GitMaintain
305
330
  end
306
331
  end
307
332
 
308
- # List commits in the branch that are no in the stable branch
309
333
  def list(opts)
310
334
  GitMaintain::log(:INFO, "Working on #{@verbose_name}")
311
- GitMaintain::showLog(opts, @local_branch, @remote_ref)
312
- end
313
-
314
- # List commits in the stable_branch that are no in the latest release
315
- def list_stable(opts)
316
- GitMaintain::log(:INFO, "Working on #{@verbose_name}")
317
- GitMaintain::showLog(opts, @remote_ref, @repo.runGit("describe --abbrev=0 #{@local_branch}"))
335
+ if opts[:stable] == true then
336
+ # List commits in the stable_branch that are no in the latest release
337
+ GitMaintain::showLog(opts, @remote_ref, @repo.runGit("describe --abbrev=0 #{@local_branch}"))
338
+ else
339
+ # List commits in the branch that are no in the stable branch
340
+ GitMaintain::showLog(opts, @local_branch, @remote_ref)
341
+ end
318
342
  end
319
343
 
320
344
  # Merge merge_branch into this one
@@ -322,8 +346,9 @@ module GitMaintain
322
346
  merge_branch = @repo.versionToLocalBranch(@version, opts[:do_merge])
323
347
 
324
348
  # Make sure branch exists
325
- hash_to_merge = @repo.runGit("rev-parse --verify --quiet #{merge_branch}")
326
- if $? != 0 then
349
+ begin
350
+ hash_to_merge = @repo.ref_exist?(merge_branch)
351
+ rescue NoRefError
327
352
  log(:INFO, "Branch #{merge_branch} does not exists. Skipping...")
328
353
  return
329
354
  end
@@ -337,25 +362,68 @@ module GitMaintain
337
362
 
338
363
  rep = GitMaintain::checkLog(opts, merge_branch, @local_branch, "merge")
339
364
  if rep == "y" then
340
- @repo.runGitInteractive("merge #{merge_branch}")
341
- if $? != 0 then
365
+ begin
366
+ @repo.runGitInteractive("merge #{merge_branch}")
367
+ rescue RuntimeError
342
368
  log(:WARNING, "Merge failure. Starting bash for manual fixes. Exit shell to continue")
343
- @repo.runBash()
344
- end
369
+ @repo.runBash("PS1_WARNING='MERGING'")
370
+ end
345
371
  else
346
372
  log(:INFO, "Skipping merge")
347
373
  return
348
374
  end
349
375
  end
350
376
 
377
+ def pull(opts)
378
+ remoteRef = opts[:stable] == true ? @remote_ref : @valid_ref
379
+
380
+ # Make sure branch exists
381
+ begin
382
+ @repo.ref_exist?(remoteRef)
383
+ rescue NoRefError
384
+ log(:INFO, "Branch #{remoteRef} does not exists. Skipping...")
385
+ return
386
+ end
387
+ @repo.runGitInteractive("rebase #{remoteRef}")
388
+
389
+ end
351
390
  # Push the branch to the validation repo
352
391
  def push(opts)
353
- if same_sha?(@local_branch, @repo.valid_repo + "/" + @local_branch) ||
392
+ remoteRef = opts[:stable] == true ? @remote_ref : @valid_ref
393
+
394
+ # Check both where we want to push and the final remote_ref
395
+ # We may have destroyed the validation branch but if we already merged
396
+ # in the final repo, no need to worry about it.
397
+ if same_sha?(@local_branch, remoteRef) ||
354
398
  same_sha?(@local_branch, @remote_ref) then
355
399
  log(:INFO, "Nothing to push on #{@local_branch}")
356
400
  return
357
401
  end
358
- return "#{@local_branch}:#{@local_branch}"
402
+
403
+ # For stable branches, we need to check for CI
404
+ if opts[:stable] == true &&
405
+ (opts[:no_ci] != true && @NO_CI != true) &&
406
+ @ci.checkValidState(self, @head) != true then
407
+ log(:WARNING, "Build is not passed on CI. Skipping push to stable")
408
+ return
409
+ end
410
+
411
+ if opts[:check_only] == true then
412
+ GitMaintain::checkLog(opts, @local_branch, @remote_ref, "")
413
+ return
414
+ end
415
+
416
+ # For validation/CI push, let's go and push already
417
+ return "#{@local_branch}:#{@local_branch}" if opts[:stable] != true
418
+
419
+ # For stable, we need to confirm with the user that he really wants to push
420
+ rep = GitMaintain::checkLog(opts, @local_branch, @remote_ref, "submit")
421
+ if rep == "y" then
422
+ return "#{@local_branch}:#{@remote_branch}"
423
+ else
424
+ log(:INFO, "Skipping push to stable")
425
+ return
426
+ end
359
427
  end
360
428
 
361
429
  def self.push_epilogue(opts, branches)
@@ -364,17 +432,26 @@ module GitMaintain
364
432
 
365
433
  return if branches.length == 0
366
434
 
435
+ repo = (opts[:stable] == true) ? opts[:repo].stable_repo : opts[:repo].valid_repo
367
436
  opts[:repo].runGit("push #{opts[:push_force] == true ? "-f" : ""} "+
368
- "#{opts[:repo].valid_repo} #{branches.join(" ")}")
437
+ "#{repo} #{branches.join(" ")}")
369
438
  end
370
439
 
371
440
  # Monitor the build status on CI
372
441
  def monitor(opts)
373
- st = @ci.getValidState(self, @head)
442
+ ts = st = head = nil
374
443
  suff=""
444
+ if opts[:stable] == true then
445
+ st = @ci.getStableState(self, @stable_head)
446
+ ts = @ci.getStableTS(self, @stable_head) if st == "started"
447
+ else
448
+ st = @ci.getValidState(self, @head)
449
+ ts = @ci.getValidTS(self, @head) if st == "started"
450
+ end
451
+
375
452
  case st
376
453
  when "started"
377
- suff= " started at #{@ci.getValidTS(self, @head)}"
454
+ suff= " at #{ts}"
378
455
  end
379
456
  log(:INFO, "Status for v#{@version}: " + st + suff)
380
457
  if @ci.isErrored(self, st) && opts[:watch] == false
@@ -396,52 +473,6 @@ module GitMaintain
396
473
  end
397
474
  end
398
475
 
399
- # Push branch to the stable repo
400
- def push_stable(opts)
401
- if same_sha?(@local_branch, @remote_ref) then
402
- log(:INFO, "Stable is already up-to-date")
403
- return
404
- end
405
-
406
- if (opts[:no_ci] != true && @NO_CI != true) &&
407
- @ci.checkValidState(self, @head) != true then
408
- log(:WARNING, "Build is not passed on CI. Skipping push to stable")
409
- return
410
- end
411
-
412
- if opts[:check_only] == true then
413
- GitMaintain::checkLog(opts, @local_branch, @remote_ref, "")
414
- return
415
- end
416
-
417
- rep = GitMaintain::checkLog(opts, @local_branch, @remote_ref, "submit")
418
- if rep == "y" then
419
- return "#{@local_branch}:#{@remote_branch}"
420
- else
421
- log(:INFO, "Skipping push to stable")
422
- return
423
- end
424
- end
425
-
426
-
427
- def self.push_stable_epilogue(opts, branches)
428
- # Compact to remove empty entries
429
- branches.compact!()
430
-
431
- return if branches.length == 0
432
- opts[:repo].runGit("push #{opts[:repo].stable_repo} #{branches.join(" ")}")
433
- end
434
- # Monitor the build status of the stable branch on CI
435
- def monitor_stable(opts)
436
- st = @ci.getStableState(self, @stable_head)
437
- suff=""
438
- case st
439
- when "started"
440
- suff= " started at #{@ci.getStableTS(self, @stable_head)}"
441
- end
442
- log(:INFO, "Status for v#{@version}: " + st + suff)
443
- end
444
-
445
476
  # Reset the branch to the upstream stable one
446
477
  def reset(opts)
447
478
  if same_sha?(@local_branch, @remote_ref) then
@@ -470,8 +501,9 @@ module GitMaintain
470
501
 
471
502
  def delete(opts)
472
503
  if opts[:delete_remote] == true then
473
- @repo.runGit("rev-parse --verify --quiet #{@repo.valid_repo}/#{@local_branch}")
474
- if $? != 0 then
504
+ begin
505
+ @repo.ref_exist?("#{@repo.valid_repo}/#{@local_branch}")
506
+ rescue NoRefError
475
507
  log(:DEBUG, "Skipping non existing remote branch #{@local_branch}.")
476
508
  return
477
509
  end
@@ -507,13 +539,16 @@ module GitMaintain
507
539
 
508
540
  private
509
541
  def add_blacklist(commit)
510
- @repo.runGit("notes append -m \"#{@local_branch}\" #{commit}")
542
+ @repo.runGit("notes append -m \"#{@local_branch}\" #{commit}")
511
543
  end
512
544
 
513
545
  def is_blacklisted?(commit)
514
- @repo.runGit("notes show #{commit} 2> /dev/null").split("\n").each(){|br|
515
- return true if br == @local_branch
516
- }
546
+ begin
547
+ @repo.runGit("notes show #{commit} 2> /dev/null").split("\n").each(){|br|
548
+ return true if br == @local_branch
549
+ }
550
+ rescue
551
+ end
517
552
  return false
518
553
  end
519
554
 
@@ -523,113 +558,115 @@ module GitMaintain
523
558
 
524
559
  msg_path=`mktemp`.chomp()
525
560
  msg_file = File.open(msg_path, "w+")
526
- msg_file.puts @repo.runGit("log -1 --format=\"%s%n%n[ Upstream commit #{msg_commit} ]%n%n%b\" #{orig_commit}")
561
+ msg_file.puts @repo.runGit("log -1 --format=\"%s%n%n[ Upstream commit #{msg_commit} ]%n%n%b\" #{orig_commit}")
527
562
  msg_file.close()
528
- @repo.runGit("commit -s --amend -F #{msg_path}")
563
+ @repo.runGit("commit -s --amend -F #{msg_path}")
529
564
  `rm -f #{msg_path}`
530
565
  end
531
566
 
532
567
  def is_in_tree?(commit, src_commit=commit)
533
- fullhash=@repo.runGit("rev-parse --verify --quiet #{commit}")
568
+ fullhash=nil
569
+ begin
570
+ fullhash=@repo.ref_exist?(commit)
571
+ rescue NoRefError
534
572
  # This might happen if someone pointed to a commit that doesn't exist in our
535
573
  # tree.
536
- if $? != 0 then
537
574
  log(:WARNING, "Commit #{src_commit} points to a SHA #{commit} not in tree")
538
- return false
539
- end
540
-
541
- # Hope for the best, same commit is/isn't in the current branch
542
- if @repo.runGit("merge-base #{fullhash} HEAD") == fullhash then
543
- return true
544
- end
545
-
546
- # Grab the subject, since commit sha1 is different between branches we
547
- # have to look it up based on subject.
548
- subj=@repo.getCommitSubj(commit)
549
- if $? != 0 then
550
- return false
551
- end
552
-
553
- # Try and find if there's a commit with given subject the hard way
554
- @repo.runGit("log --pretty=\"%H\" -F --grep \"#{subj.gsub("\"", '\\"')}\" "+
575
+ return false
576
+ end
577
+
578
+ # Hope for the best, same commit is/isn't in the current branch
579
+ if @repo.runGit("merge-base #{fullhash} HEAD") == fullhash then
580
+ return true
581
+ end
582
+
583
+ # Grab the subject, since commit sha1 is different between branches we
584
+ # have to look it up based on subject.
585
+ subj=@repo.getCommitSubj(commit)
586
+
587
+ # Try and find if there's a commit with given subject the hard way
588
+ @repo.runGit("log --pretty=\"%H\" -F --grep \"#{subj.gsub("\"", '\\"')}\" "+
555
589
  "#{@stable_base}..HEAD").split("\n").each(){|cmt|
556
590
  cursubj=@repo.runGit("log -1 --format=\"%s\" #{cmt}")
557
591
  if cursubj = subj then
558
- return true
559
- end
560
- }
561
- return false
592
+ return true
593
+ end
594
+ }
595
+ return false
562
596
  end
563
597
 
564
598
  def is_relevant?(commit)
565
- # Let's grab the commit that this commit fixes (if exists (based on the "Fixes:" tag)).
566
- fixescmt=@repo.runGit("log -1 #{commit} | grep -i \"fixes:\" | head -n 1 | "+
599
+ # Let's grab the commit that this commit fixes (if exists (based on the "Fixes:" tag)).
600
+ fixescmt=@repo.runGit("log -1 #{commit} | grep -i \"fixes:\" | head -n 1 | "+
567
601
  "sed -e 's/^[ \\t]*//' | cut -f 2 -d ':' | "+
568
602
  "sed -e 's/^[ \\t]*//' -e 's/\\([0-9a-f]\\+\\)(/\\1 (/' | cut -f 1 -d ' '")
569
603
 
570
- # If this commit fixes anything, but the broken commit isn't in our branch we don't
571
- # need this commit either.
572
- if fixescmt != "" then
573
- if is_in_tree?(fixescmt, commit) then
574
- return true
575
- else
576
- return false
577
- end
604
+ # If this commit fixes anything, but the broken commit isn't in our branch we don't
605
+ # need this commit either.
606
+ if fixescmt != "" then
607
+ if is_in_tree?(fixescmt, commit) then
608
+ return true
609
+ else
610
+ return false
611
+ end
578
612
  end
579
613
 
580
- if @repo.runGit("show #{commit} | grep -i 'stable@' | wc -l") == "0" then
581
- return false
582
- end
614
+ if @repo.runGit("show #{commit} | grep -i 'stable@' | wc -l") == "0" then
615
+ return false
616
+ end
583
617
 
584
- # Let's see if there's a version tag in this commit
585
- full=@repo.runGit("show #{commit} | grep -i 'stable@'").gsub(/.* #?/, "")
618
+ # Let's see if there's a version tag in this commit
619
+ full=@repo.runGit("show #{commit} | grep -i 'stable@'").gsub(/.* #?/, "")
586
620
 
587
- # Sanity check our extraction
621
+ # Sanity check our extraction
588
622
  if full =~ /stable/ then
589
623
  return false
590
624
  end
591
625
 
592
626
  full = @repo.runGit("rev-parse #{full}^{commit}")
593
627
 
594
- # Make sure our branch contains this version
595
- if @repo.runGit("merge-base #{@head} #{full}") == full then
596
- return true
597
- end
628
+ # Make sure our branch contains this version
629
+ if @repo.runGit("merge-base #{@head} #{full}") == full then
630
+ return true
631
+ end
598
632
 
599
- # Tag is not in history, ignore
600
- return false
633
+ # Tag is not in history, ignore
634
+ return false
601
635
  end
602
636
 
603
637
  def pick_one(commit)
604
- @repo.runGitInteractive("cherry-pick --strategy=recursive -Xpatience -x #{commit} &> /dev/null")
605
- return if $? == 0
638
+ cpCmd="cherry-pick --strategy=recursive -Xpatience -x"
639
+ @repo.runGitInteractive("#{cpCmd} #{commit} &> /dev/null", :check_err => false)
640
+ return if $? == 0
641
+
606
642
  if @repo.runGit("status -uno --porcelain | wc -l") == "0" then
607
- @repo.runGit("reset --hard")
643
+ @repo.runGit("reset --hard")
608
644
  raise CherryPickErrorException.new("Failed to cherry pick commit #{commit}", commit)
609
- end
610
- @repo.runGit("reset --hard")
611
- # That didn't work? Let's try that with every variation of the commit
612
- # in other stable trees.
645
+ end
646
+ @repo.runGit("reset --hard")
647
+
648
+ # That didn't work? Let's try that with every variation of the commit
649
+ # in other stable trees.
613
650
  @repo.find_alts(commit).each(){|alt_commit|
614
- @repo.runGitInteractive("cherry-pick --strategy=recursive -Xpatience -x #{alt_commit} &> /dev/null")
615
- if $? == 0 then
616
- return
617
- end
618
- @repo.runGit("reset --hard")
651
+ @repo.runGitInteractive("#{cpCmd} #{alt_commit} &> /dev/null", :check_err => false)
652
+ if $? == 0 then
653
+ return
654
+ end
655
+ @repo.runGit("reset --hard")
619
656
  }
620
- # Still no? Let's go back to the original commit and hand it off to
621
- # the user.
622
- @repo.runGitInteractive("cherry-pick --strategy=recursive -Xpatience -x #{commit} &> /dev/null")
657
+
658
+ # Still no? Let's go back to the original commit and hand it off to
659
+ # the user.
660
+ @repo.runGitInteractive("#{cpCmd} #{commit} &> /dev/null", :check_err => false)
623
661
  raise CherryPickErrorException.new("Failed to cherry pick commit #{commit}", commit)
624
- return false
625
662
  end
626
663
 
627
664
  def confirm_one(opts, commit)
628
- rep=""
629
- do_cp=false
630
- puts @repo.getCommitHeadline(commit)
631
- while rep != "y" do
632
- puts "Do you want to steal this commit ? (y/n/b/?)"
665
+ rep=""
666
+ do_cp=false
667
+ puts @repo.getCommitHeadline(commit)
668
+ while rep != "y" do
669
+ puts "Do you want to steal this commit ? (y/n/b/?)"
633
670
  case opts[:yn_default]
634
671
  when :no
635
672
  log(:INFO, "Auto-replying no due to --no option")
@@ -642,38 +679,38 @@ module GitMaintain
642
679
  rep = STDIN.gets.chomp()
643
680
  end
644
681
 
645
- case rep
646
- when "n"
647
- log(:INFO, "Skip this commit")
648
- break
649
- when "b"
650
- log(:INFO, "Blacklisting this commit for the current branch")
651
- add_blacklist(commit)
652
- break
653
- when "y"
654
- rep="y"
655
- do_cp=true
656
- break
657
- when "?"
658
- puts @repo.runGit("show #{commit}")
682
+ case rep
683
+ when "n"
684
+ log(:INFO, "Skip this commit")
685
+ break
686
+ when "b"
687
+ log(:INFO, "Blacklisting this commit for the current branch")
688
+ add_blacklist(commit)
689
+ break
690
+ when "y"
691
+ rep="y"
692
+ do_cp=true
693
+ break
694
+ when "?"
695
+ puts @repo.runGit("show #{commit}")
659
696
  else
660
- log(:ERROR, "Invalid answer $rep")
661
- puts @repo.runGit("show --format=oneline --no-patch --no-decorate #{commit}")
697
+ log(:ERROR, "Invalid answer $rep")
698
+ puts @repo.runGit("show --format=oneline --no-patch --no-decorate #{commit}")
662
699
  end
663
- end
700
+ end
664
701
  return do_cp
665
702
  end
666
703
 
667
704
  def steal_one(opts, commit, mainline=false)
668
- msg=''
705
+ msg=''
669
706
  orig_cmt=commit
670
707
 
671
708
  if mainline == false then
672
- subj=@repo.getCommitSubj(commit)
709
+ subj=@repo.getCommitSubj(commit)
673
710
  subj.gsub!(/"/, '\"')
674
- # Let's grab the mainline commit id, this is useful if the version tag
675
- # doesn't exist in the commit we're looking at but exists upstream.
676
- orig_cmt=@repo.runGit("log --no-merges --format=\"%H\" -F --grep \"#{subj}\" " +
711
+ # Let's grab the mainline commit id, this is useful if the version tag
712
+ # doesn't exist in the commit we're looking at but exists upstream.
713
+ orig_cmt=@repo.runGit("log --no-merges --format=\"%H\" -F --grep \"#{subj}\" " +
677
714
  "#{@stable_base}..origin/master | tail -n1")
678
715
 
679
716
  if orig_cmt == "" then
@@ -681,24 +718,24 @@ module GitMaintain
681
718
  end
682
719
  end
683
720
  # If the commit doesn't apply for us, skip it
684
- if is_relevant?(orig_cmt) != true
721
+ if is_relevant?(orig_cmt) != true
685
722
  return true
686
- end
723
+ end
687
724
 
688
725
  log(:VERBOSE, "Found relevant commit #{@repo.getCommitHeadline(commit)}")
689
- if is_in_tree?(orig_cmt) == true
690
- # Commit is already in the stable branch, skip
726
+ if is_in_tree?(orig_cmt) == true
727
+ # Commit is already in the stable branch, skip
691
728
  log(:VERBOSE, "Commit is already in tree")
692
729
  return true
693
- end
730
+ end
694
731
 
695
- # Check if it's not blacklisted by a git-notes
696
- if is_blacklisted?(orig_cmt) == true then
697
- # Commit is blacklisted
698
- log(:INFO, "Skipping 'blacklisted' commit " +
699
- @repo.getCommitHeadline(orig_cmt))
732
+ # Check if it's not blacklisted by a git-notes
733
+ if is_blacklisted?(orig_cmt) == true then
734
+ # Commit is blacklisted
735
+ log(:INFO, "Skipping 'blacklisted' commit " +
736
+ @repo.getCommitHeadline(orig_cmt))
700
737
  return true
701
- end
738
+ end
702
739
 
703
740
  do_cp = confirm_one(opts, orig_cmt)
704
741
  return false if do_cp != true
@@ -706,39 +743,83 @@ module GitMaintain
706
743
  prev_head=@repo.runGit("rev-parse HEAD")
707
744
 
708
745
  begin
709
- pick_one(commit)
746
+ pick_one(commit)
710
747
  rescue CherryPickErrorException => e
711
- log(:WARNING, "Cherry pick failed. Fix, commit (or reset) and exit.")
712
- @repo.runSystem("/bin/bash")
748
+ log(:WARNING, "Cherry pick failed. Fix, commit (or reset) and exit.")
749
+ @repo.runBash("PS1_WARNING='CP FIX'")
713
750
  end
714
751
  new_head=@repo.runGit("rev-parse HEAD")
715
752
 
716
- # If we didn't find the commit upstream then this must be a custom commit
717
- # in the given tree - make sure the user checks this commit.
718
- if orig_cmt == "" then
719
- msg="Custom"
720
- orig_cmt=@repo.runGit("rev-parse HEAD")
721
- log(:WARNING, "Custom commit, please double-check!")
722
- @repo.runSystem("/bin/bash")
723
- end
753
+ # If we didn't find the commit upstream then this must be a custom commit
754
+ # in the given tree - make sure the user checks this commit.
755
+ if orig_cmt == "" then
756
+ msg="Custom"
757
+ orig_cmt=@repo.runGit("rev-parse HEAD")
758
+ log(:WARNING, "Custom commit, please double-check!")
759
+ @repo.runBash("PS1_WARNING='CHECK'")
760
+ end
724
761
  if new_head != prev_head
725
- make_pretty(orig_cmt, msg)
762
+ make_pretty(orig_cmt, msg)
726
763
  end
727
764
  end
728
765
 
729
766
  def steal_all(opts, range, mainline = false)
730
767
  res = true
731
- @repo.runGit("log --no-merges --format=\"%H\" #{range} | tac").split("\n").each(){|commit|
768
+ @repo.runGit("log --no-merges --format=\"%H\" #{range} | tac").split("\n").each(){|commit|
732
769
  res &= steal_one(opts, commit, mainline)
733
770
  }
734
771
  return res
735
- end
772
+ end
736
773
 
737
774
  def same_sha?(ref1, ref2)
738
- c1=@repo.runGit("rev-parse --verify --quiet #{ref1}")
739
- c2=@repo.runGit("rev-parse --verify --quiet #{ref2}")
740
- return c1 == c2
775
+ begin
776
+ c1=@repo.ref_exist?(ref1)
777
+ c2=@repo.ref_exist?(ref2)
778
+ return c1 == c2
779
+ rescue
780
+ return false
781
+ end
782
+ end
783
+
784
+
785
+ def release_do_add_commit(opts, filelist, commit_path, commit_msg=nil)
786
+ edit_flag = ""
787
+ edit_flag = "--edit" if opts[:no_edit] == false
788
+
789
+ raise("No commit message provided") if commit_path == nil && commit_msg == nil
790
+ commit_flag=""
791
+ if commit_msg != nil
792
+ commit_flag = "-m '#{commit_msg}'"
793
+ else
794
+ commit_flag = "-F '#{commit_path}'"
795
+ end
741
796
 
797
+ # Add and commit
798
+ begin
799
+ @repo.runGit("add " + filelist.join(" "))
800
+ @repo.runGitInteractive("commit #{commit_flag} --verbose #{edit_flag} --signoff")
801
+ rescue RuntimeError
802
+ raise("Failed to commit on branch #{@local_branch}")
803
+ end
804
+ return 0
742
805
  end
806
+
807
+ def release_do_tag(opts, version, tag_path)
808
+ edit_flag = ""
809
+ edit_flag = "--edit" if opts[:no_edit] == false
810
+ begin
811
+ @repo.runGitInteractive("tag -a -s #{version} #{edit_flag} -F #{tag_path}")
812
+ rescue RuntimeError
813
+ raise("Failed to tag branch #{@local_branch}")
814
+ end
815
+ return 0
816
+ end
817
+
818
+ def release_do_add_commit_tag(opts, filelist, version, message_path)
819
+ release_do_add_commit(opts, filelist, message_path)
820
+ release_do_tag(opts, version, message_path)
821
+ return 0
822
+ end
823
+
743
824
  end
744
825
  end