This repository has been archived by the owner on Jul 10, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
git.rake
249 lines (231 loc) · 6.03 KB
/
git.rake
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
task 'git:helpers' do
class GitError < RuntimeError; end
class GitRebaseError < GitError; end
def git_branch
`git-branch`.grep(/^\*/).first.strip[(2..-1)]
end
def git_branches
`git-branch`.to_a.map { |b| b[(2..-1)].chomp }
end
def git?
`git-status`
(not ($?.exitstatus == 128))
end
def git_stash
`git-diff-files --quiet`
if ($?.exitstatus == 1) then
stash = true
clear = (`git-stash list`.scan("\n").size == 0)
puts("* Saving changes...")
`git-stash save`
else
stash = false
end
begin
yield rescue puts("* Encountered an error, backing out...")
ensure
if stash then
puts("* Applying changes...")
sh("git-stash apply")
`git-stash clear` if clear
end
end
end
def git_checkout(what = nil)
branch = git_branch
sh("git-checkout #{what}") if branch != what
if block_given?
yield
sh("git-checkout #{branch}") if branch != what
end
end
def git_fetch
sh("git#{"-svn" if git_svn?} fetch")
end
def assert_command_succeeded(*args)
raise *args if $?.exitstatus != 0
end
def assert_rebase_succeeded(what = nil)
assert_command_succeeded GitRebaseError, "conflict while rebasing branch #{what}"
end
def git_rebase(what = nil)
if git_svn? then
git_checkout what do
sh("git-svn rebase --local")
assert_rebase_succeeded what
end
else
sh("git-rebase origin/master #{what}")
assert_rebase_succeeded what
end
end
def git_push
git_svn? ? (sh("git-svn dcommit")) : (sh("git-push"))
end
def git_svn?
not File.readlines(".git/config").grep(/^\[svn-remote "svn"\]\s*$/).empty?
end
def argv
ARGV.inject([]) do |argv, arg|
if (argv.last and argv.last =~ /=$/) then
(argv.last << arg)
else
(argv << arg.dup)
end
argv
end
end
def correct_env_from_argv
argv.grep(/^[A-Z]+=/).each { |kv| ENV.send(:[]=, *kv.split("=", 2)) }
end
def env(name)
case val = ENV[name]
when "", nil then
nil
else
val
end
end
correct_env_from_argv
end
desc 'Pull new commits from the repository'
task 'git:update' => [ 'git:helpers' ] do
git_stash do
branch = git_branch
if (branch == "master") then
switch = false
else
switch = true
`git-checkout master`
puts("* Switching back to master...")
end
puts("* Pulling in new commits...")
git_fetch
git_rebase
if switch then
puts("* Porting changes into #{branch}...")
`git-checkout #{branch}`
sh("git-rebase master")
end
end
end
desc 'Push local commits into the remote repository'
task 'git:push' => [ 'git:update' ] do
git_stash do
puts("* Pushing changes...")
git_push
branch = git_branch
unless (branch == "master") then
`git-checkout master`
puts("* Porting changes into master")
git_rebase
`git-checkout #{branch}`
end
end
end
desc 'Delete the current branch and switch back to master'
task 'git:close' => [ 'git:helpers' ] do
branch = (env("NAME") or git_branch)
current = git_branch
if (branch == "master") then
$stderr.puts("* Cannot delete master branch")
exit(1)
end
if (current == branch) then
puts("* Switching to master")
`git-checkout master 2>/dev/null`
end
puts("* Deleting branch #{branch}")
`git-branch -d #{branch} 2>/dev/null`
if ($?.exitstatus == 1) then
$stderr.puts("* Branch #{branch} isn't a strict subset of master, quitting")
`git-checkout #{current} 2>/dev/null`
exit(1)
end
`git-checkout #{current} 2>/dev/null` unless (current == branch)
exit(0)
end
desc 'Create a new branch off master'
task 'git:open' => [ 'git:helpers' ] do
newbranch = (env("NAME") or begin
(require("readline")
print("* Name your branch: ")
Readline.readline.chomp)
end)
branch = git_branch
if git_branches.include?(newbranch)
if newbranch == branch
puts(%{* Already on branch "#{newbranch}"})
else
puts(%{* Switching to existing branch "#{newbranch}"})
git_checkout newbranch
end
exit(0)
end
unless (branch == "master") then
puts("* Switching to master")
git_checkout 'master'
end
`git-checkout -b #{newbranch}`
unless $?.exitstatus.zero? then
puts("* Couldn't create branch #{newbranch}, switching back to #{branch}")
git_checkout branch
exit(1)
end
exit(0)
end
desc 'Merge the current branch into the master branch.'
task 'git:fold' => [ 'git:helpers' ] do
branch = git_branch
if (branch == "master") then
$stderr.puts("* Cannot fold master branch")
exit(1)
end
puts("* Switching to master")
`git-checkout master 2>/dev/null`
puts("* Merging #{branch}")
system("git-merge #{@merge_flags} #{branch}")
if ($?.exitstatus == 1) then
$stderr.puts("* Merge had errors -- see to your friend")
exit(1)
end
puts("* Switching to #{branch}")
`git-checkout #{branch} 2>/dev/null`
end
desc 'Squash the current branch into the master branch.'
task 'git:squash' do
@merge_flags = "--squash"
Rake::Task["git:fold"].invoke
end
desc 'Update all branches'
task 'git:update:all' => [ 'git:helpers' ] do
git_stash do
branch = git_branch
switch = true
git_branches.each do |b|
puts("* Updating branch #{b}")
begin
git_rebase(b)
rescue GitRebaseError => e
puts("* Couldn't rebase #{b}, aborting so you can clean it up")
switch = false
break
end
end
`git-checkout #{branch} 2>/dev/null` if switch
end
end
desc 'Converts an existing Subversion Repo into a Git Repository'
task 'git:ify' do
# Make sure we're in an svn repo
unless File.directory?("./.svn")
$stderr.puts "This task can only be executed in an existing working copy! (No .svn-Folder found)"
exit(1)
end
# get svn info location
svnurl = %x(svn info).grep(/^URL:/).first.gsub('URL: ','').chomp
# project = basename
project = "../#{File.basename(Dir.pwd)}.git"
puts cmd = "git svn clone #{svnurl} #{project}"
`#{cmd}`
end