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 +10 -7
- data/gitscape.gemspec +4 -2
- data/lib/gitscape.rb +4 -0
- data/lib/gitscape/base.rb +129 -38
- data/lib/gitscape/version.rb +3 -3
- metadata +24 -14
data/bin/gitscape
CHANGED
@@ -8,12 +8,15 @@ rescue LoadError
|
|
8
8
|
end
|
9
9
|
|
10
10
|
if ARGV.size < 2
|
11
|
-
puts "
|
12
|
-
puts "\tgitscape diff master staging"
|
13
|
-
puts "\tgitscape deploy_iteration i22"
|
11
|
+
puts "TODO: write usage help text"
|
14
12
|
exit(1)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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 =
|
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/
|
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
data/lib/gitscape/base.rb
CHANGED
@@ -1,29 +1,121 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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.
|
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}"
|
data/lib/gitscape/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION =
|
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
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: "
|
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-
|
18
|
-
|
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
|
-
|
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.
|
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.
|