gitscape 0.2 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/gitscape CHANGED
@@ -8,12 +8,15 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  if ARGV.size < 2
11
- puts "Examples: "
12
- puts "\tgitscape diff master staging"
13
- puts "\tgitscape deploy_iteration i22"
11
+ puts "TODO: write usage help text"
14
12
  exit(1)
15
- elsif ARGV[0] == "diff"
16
- GitScape.compare(ARGV[1], ARGV[2])
17
- elsif ARGV[0] == "deploy_iteration"
18
- GitScape.deploy_iteration(ARGV[1])
13
+ else
14
+ case ARGV[0]
15
+ when "hotfix_start"
16
+ GitScape.new.hotfix_start
17
+ when "hotfix_finish"
18
+ GitScape.new.hotfix_finish
19
+ else
20
+ puts "Unknown command"
21
+ end
19
22
  end
data/gitscape.gemspec CHANGED
@@ -5,14 +5,16 @@ require "gitscape/version"
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "gitscape"
8
- s.version = GitScape::VERSION
8
+ s.version = Gitscape::VERSION
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.authors = ["Jon Botelho"]
11
11
  s.email = ["gitscape@eachscape.com"]
12
- s.homepage = "https://github.com/jon-eachscape/gitscape"
12
+ s.homepage = "https://github.com/eachscape/gitscape"
13
13
  s.summary = "Various Git utilities for cherry-pick/rebase workflows."
14
14
  s.description = "Various Git utilities for cherry-pick/rebase workflows."
15
15
 
16
+ s.add_dependency "git", "~> 1.2.5"
17
+
16
18
  s.files = `git ls-files`.split("\n")
17
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
data/lib/gitscape.rb CHANGED
@@ -1 +1,5 @@
1
+ require 'gitscape/version.rb'
2
+
3
+ # Add requires for other files you add to your project here, so
4
+ # you just need to require this one file in your bin file
1
5
  require "gitscape/base"
data/lib/gitscape/base.rb CHANGED
@@ -1,29 +1,121 @@
1
- class GitScape
2
- # Returns true if the supplied Git commit hash or reference exists
3
- def self.commit_exists?(commit_id)
4
- `git rev-parse #{commit_id}`
5
- if $? == 0
6
- true
1
+ require "git"
2
+
3
+
4
+ class Gitscape::Base
5
+
6
+ def initialize
7
+ # Use the current directory as our target repository
8
+ @repo = Git.open "."
9
+
10
+ # Always add a merge commit at the end of a merge
11
+ @merge_options = "--no-ff"
12
+ # Setup additional merge options based on the version of Git we have
13
+ if git_version_at_least "1.7.4.0"
14
+ @merge_options += "-s recursive -Xignore-space-change"
7
15
  else
8
- raise "Invalid commit/ref ID: #{commit_id}"
16
+ warn "Ignoring whitespace changes in merges is only available on Git 1.7.4+"
9
17
  end
10
18
  end
11
19
 
20
+ def branch_names
21
+ @repo.branches.map { |b| b.full }
22
+ end
12
23
 
13
- def self.abort!
24
+ # Get the system's current git version
25
+ def git_version
26
+ @git_version ||= `git --version`.strip.split(" ").last
27
+ end
14
28
 
29
+ def checkout(branch_name)
30
+ begin
31
+ @repo.revparse(branch_name)
32
+ rescue
33
+ raise Exception.new "No branch '#{branch_name}' found"
34
+ end
35
+ puts "Switching to branch '#{branch_name}'..."
36
+ @repo.checkout(branch_name)
15
37
  end
16
38
 
17
- def self.compare(upstream, head)
18
- puts "#" * 80
19
- puts "# Commits on #{head} not on #{upstream}"
20
- puts "#" * 80
21
- puts
22
- `git cherry #{upstream} #{head}`.split("\n").select { |x| x.start_with? "+" }.each do |x|
23
- puts `git show -s --format=medium #{x.split(" ").last}`
24
- puts
25
- puts "-" * 80
26
- puts
39
+ # Check if the system's git version is at least as recent as the version specified
40
+ def git_version_at_least(min_version)
41
+ def split_version(v)
42
+ v.split(".").map { |x| x.to_i }
43
+ end
44
+ local_version = split_version(git_version)
45
+ min_version = split_version(min_version)
46
+
47
+ raise "Git version string must have 4 parts" if min_version.size != 4
48
+
49
+ 4.times do |i|
50
+ return false unless local_version[i] >= min_version[i]
51
+ end
52
+ true
53
+ end
54
+
55
+ def hotfix_start(hotfix_branch_name=nil)
56
+ checkout "master"
57
+
58
+ hotfix_branch_name = "hotfix/#{hotfix_branch_name}"
59
+ puts "Creating hotfix branch '#{hotfix_branch_name}'..."
60
+ @repo.checkout(@repo.branch.create(hotfix_branch_name))
61
+ end
62
+
63
+ def hotfix_finish(hotfix_branch_name=nil)
64
+ # TODO:
65
+ # 1. Tag the new live revision with 'live/<branch_name_without_prefix>'
66
+
67
+ usage_string = "expected usage: hotfix_finish [<hotfix_branch_name>]
68
+ hotfix_branch_name: the name of the hotfix branch to finish.
69
+ if ommitted, you must currently be on a hotfix branch"
70
+
71
+ previous_branch = @repo.current_branch
72
+
73
+ if previous_branch.start_with? "hotfix"
74
+ hotfix_branch_name ||= previous_branch
75
+ end
76
+
77
+ unless @repo.branches.include? hotfix_branch_name
78
+ end
79
+
80
+ merge_master = true
81
+
82
+ if hotfix_branch_name.empty?
83
+ puts "!!! not currently on a hotfix branch, and no branch name was provided as an argument !!!"
84
+ puts usage_string
85
+ exit 1
86
+ end
87
+
88
+ hotfix_branch = @repo.branch hotfix_branch_name
89
+ development_branch = @repo.branches.select {|branch| branch.full.start_with? "release/"}.sort.last
90
+ development_branch = @repo.branch "master" if development_branch == nil
91
+ live_branch = @repo.branch "live"
92
+
93
+ # Collect the set of branches we'd like to merge the hotfix into
94
+ merge_branches = [development_branch, live_branch]
95
+
96
+ # Merge the hotfix into branches
97
+ for branch in merge_branches
98
+ merge_options = @merge_options
99
+ merge_options += " --log" if branch == "master"
100
+
101
+ `git checkout #{branch.full}`
102
+ `git merge #{merge_options} #{hotfix_branch.full}`
103
+ exit 1 if !$?.success?
104
+ raise "Merge on #{branch.full} has failed.\nResolve the conflicts and run the script again." if git_has_conflicts
105
+ end
106
+
107
+ # Checkout previous branch for user convenience
108
+ `git checkout #{previous_branch}`
109
+ end
110
+
111
+
112
+ # Returns true if the supplied Git commit hash or reference exists
113
+ def self.commit_exists?(commit_id)
114
+ `git rev-parse #{commit_id}`
115
+ if $? == 0
116
+ true
117
+ else
118
+ raise "Invalid commit/ref ID: #{commit_id}"
27
119
  end
28
120
  end
29
121
 
@@ -38,30 +130,16 @@ class GitScape
38
130
  $?.exitstatus
39
131
  end
40
132
 
41
- def promote_commit(commit_id, upstream)
42
- commit_exists? commit_id
43
- run_script <<-EOH
44
- git stash
45
- git checkout master
46
- git pull
47
- git checkout staging
48
- git reset --hard origin/staging
49
- git cherry-pick #{commit_id}
50
- git push origin staging
51
- EOH
52
- end
53
-
54
133
  def promote_branch(head, upstream)
55
134
  run_script <<-EOH
56
- git fetch
57
- git stash
58
- git checkout #{head}
59
- git reset --hard origin/#{head}
60
- git push -f origin #{head}:#{upstream}
135
+ git fetch
136
+ git stash
137
+ git checkout #{head}
138
+ git reset --hard origin/#{head}
139
+ git push -f origin #{head}:#{upstream}
61
140
  EOH
62
141
  end
63
142
 
64
-
65
143
  def self.result_ok?(result)
66
144
  if result.nil? or result == 0
67
145
  puts "done"
@@ -74,8 +152,21 @@ class GitScape
74
152
  end
75
153
  end
76
154
 
77
- def self.deploy_iteration(iteration, projects=%w{android-client builder ios-client rails3 web-client})
155
+ def self.start_iteration(iteration, projects=PROJECTS)
156
+ projects.each do |proj|
157
+ print "Cutting branch #{iteration} for #{proj}..."
158
+ result = run_script <<-EOH
159
+ cd /code/#{proj}/
160
+ git fetch
161
+ git branch #{iteration} origin/master
162
+ git push origin #{iteration}
163
+ git push -f origin #{iteration}:qa
164
+ EOH
165
+ return unless result_ok?(result)
166
+ end
167
+ end
78
168
 
169
+ def self.deploy_iteration(iteration, projects=PROJECTS)
79
170
  date = `date +%Y%m%d-%H%M`.strip
80
171
  tag = "#{iteration}-#{date}"
81
172
  puts "Starting deploy of #{iteration}"
@@ -1,3 +1,3 @@
1
- module GitScape
2
- VERSION = "0.2"
3
- end
1
+ module Gitscape
2
+ VERSION = '1.1'
3
+ end
metadata CHANGED
@@ -1,12 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitscape
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
- - 0
8
- - 2
9
- version: "0.2"
6
+ - 1
7
+ - 1
8
+ version: "1.1"
10
9
  platform: ruby
11
10
  authors:
12
11
  - Jon Botelho
@@ -14,9 +13,23 @@ autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2012-07-12 00:00:00 Z
18
- dependencies: []
19
-
16
+ date: 2012-12-19 00:00:00 -05:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: git
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 1
28
+ - 2
29
+ - 5
30
+ version: 1.2.5
31
+ type: :runtime
32
+ version_requirements: *id001
20
33
  description: Various Git utilities for cherry-pick/rebase workflows.
21
34
  email:
22
35
  - gitscape@eachscape.com
@@ -36,7 +49,8 @@ files:
36
49
  - lib/gitscape.rb
37
50
  - lib/gitscape/base.rb
38
51
  - lib/gitscape/version.rb
39
- homepage: https://github.com/jon-eachscape/gitscape
52
+ has_rdoc: true
53
+ homepage: https://github.com/eachscape/gitscape
40
54
  licenses: []
41
55
 
42
56
  post_install_message:
@@ -45,27 +59,23 @@ rdoc_options: []
45
59
  require_paths:
46
60
  - lib
47
61
  required_ruby_version: !ruby/object:Gem::Requirement
48
- none: false
49
62
  requirements:
50
63
  - - ">="
51
64
  - !ruby/object:Gem::Version
52
- hash: 3
53
65
  segments:
54
66
  - 0
55
67
  version: "0"
56
68
  required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
69
  requirements:
59
70
  - - ">="
60
71
  - !ruby/object:Gem::Version
61
- hash: 3
62
72
  segments:
63
73
  - 0
64
74
  version: "0"
65
75
  requirements: []
66
76
 
67
77
  rubyforge_project:
68
- rubygems_version: 1.8.15
78
+ rubygems_version: 1.3.6
69
79
  signing_key:
70
80
  specification_version: 3
71
81
  summary: Various Git utilities for cherry-pick/rebase workflows.