git-si 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/git-si.gemspec +2 -1
- data/lib/git/si.rb +68 -369
- data/lib/git/si/actions.rb +153 -0
- data/lib/git/si/errors.rb +20 -0
- data/lib/git/si/git-control.rb +112 -0
- data/lib/git/si/git-ignore.rb +23 -0
- data/lib/git/si/svn-control.rb +135 -0
- data/lib/git/si/util.rb +304 -0
- data/lib/git/si/version.rb +12 -1
- data/spec/actions_spec.rb +356 -0
- data/spec/git-control_spec.rb +254 -0
- data/spec/git-ignore_spec.rb +37 -0
- data/spec/svn-control_spec.rb +391 -0
- data/spec/util_spec.rb +458 -0
- data/spec/version_spec.rb +17 -0
- metadata +40 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f699eab35b01983b28c6a305f4f052bff51c877b
|
4
|
+
data.tar.gz: 66757783cb35d72353a1aea64c982148114771d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f47abf1fc81a97582940b27708e1e362c30d0947fb3d19017c7a91a07243704742d837d47eaf67b6273ad06209ebd570edeaa5781818b3f4f936494f75c54af
|
7
|
+
data.tar.gz: df346172fd8e64b4ef85cbcf106fa9d8952b8005fdf91ecfdf228d29b87bc60c76e6310b1d462372df3bb743c43fa35ea134c39b038cbd6bf542fbcd61d7cd2d
|
data/git-si.gemspec
CHANGED
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "bundler"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "thor"
|
24
24
|
spec.add_development_dependency "pager"
|
25
|
+
spec.add_development_dependency "rspec"
|
25
26
|
|
26
27
|
spec.add_runtime_dependency "thor"
|
27
28
|
spec.add_runtime_dependency "pager"
|
data/lib/git/si.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
require "git/si/version"
|
2
|
+
require "git/si/errors"
|
3
|
+
require "git/si/svn-control"
|
4
|
+
require "git/si/git-control"
|
5
|
+
require "git/si/git-ignore"
|
6
|
+
require "git/si/util"
|
7
|
+
require "git/si/actions"
|
2
8
|
require "thor"
|
3
9
|
require "pager"
|
4
10
|
|
@@ -6,41 +12,37 @@ module Git
|
|
6
12
|
|
7
13
|
module Si
|
8
14
|
|
9
|
-
class GitSiError < StandardError
|
10
|
-
end
|
11
|
-
|
12
|
-
class ShellError < GitSiError
|
13
|
-
end
|
14
|
-
|
15
|
-
class GitError < GitSiError
|
16
|
-
end
|
17
|
-
|
18
|
-
class SvnError < GitSiError
|
19
|
-
end
|
20
|
-
|
21
|
-
class VersionError < GitSiError
|
22
|
-
end
|
23
|
-
|
24
15
|
class SvnInterface < Thor
|
25
16
|
include Thor::Actions
|
26
17
|
include Pager
|
18
|
+
include Git::Si::Util
|
19
|
+
include Git::Si::Actions
|
27
20
|
|
28
|
-
|
21
|
+
class_option :debug, :type => :boolean, :desc => 'Print lots of output', :default => false
|
22
|
+
class_option :quiet, :type => :boolean, :desc => 'Print only the minimum output', :default => false
|
23
|
+
class_option :svn, :type => :string, :desc => 'The path to the svn binary', :default => 'svn'
|
24
|
+
class_option :git, :type => :string, :desc => 'The path to the git binary', :default => 'git'
|
29
25
|
|
30
|
-
|
26
|
+
default_task :usage
|
31
27
|
|
28
|
+
################
|
29
|
+
# Action: version
|
30
|
+
################
|
32
31
|
desc "version", "Print the version."
|
33
32
|
def version
|
34
|
-
say
|
33
|
+
say Git::Si::Version.version_string
|
35
34
|
end
|
36
35
|
|
36
|
+
################
|
37
|
+
# Action: usage
|
38
|
+
################
|
37
39
|
desc "usage", "How does this thing work?"
|
38
40
|
def usage
|
39
|
-
say "
|
41
|
+
say "#{Git::Si::Version.version_string}
|
40
42
|
|
41
43
|
Git Svn Interface: a simple git extention to use git locally with a remote svn
|
42
|
-
|
43
|
-
|
44
|
+
repository. It's like a simple version of git-svn just for using local
|
45
|
+
branching. It does not keep track of the full history of the svn repository.
|
44
46
|
|
45
47
|
Start with the init command to set up the mirror branch and from there you can
|
46
48
|
use the commands below.
|
@@ -49,387 +51,84 @@ use the commands below.
|
|
49
51
|
help
|
50
52
|
end
|
51
53
|
|
54
|
+
################
|
55
|
+
# Action: status
|
56
|
+
################
|
52
57
|
desc "status [FILES]", "Perform an svn status."
|
53
58
|
def status(*args)
|
54
|
-
|
55
|
-
|
56
|
-
svn_status = `#{command}`
|
57
|
-
raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
|
58
|
-
svn_status.each_line do |line|
|
59
|
-
case line.strip!
|
60
|
-
when /^X/, /\.git/, /\.swp$/
|
61
|
-
else
|
62
|
-
if STDOUT.tty?
|
63
|
-
print_colordiff line
|
64
|
-
else
|
65
|
-
say line
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
59
|
+
configure
|
60
|
+
do_status_action( args )
|
70
61
|
end
|
71
62
|
|
63
|
+
################
|
64
|
+
# Action: diff
|
65
|
+
################
|
72
66
|
desc "diff [FILES]", "Perform an svn diff piped through a colorizer. Also tests to be sure a rebase is not needed."
|
73
67
|
def diff(*args)
|
74
|
-
|
75
|
-
|
76
|
-
git_log = `git log --pretty=%B`
|
77
|
-
results = git_log.match(/svn update to version (\d+)/i)
|
78
|
-
last_rebased_version = results[1] if results
|
79
|
-
if last_fetched_version and last_rebased_version
|
80
|
-
if last_fetched_version > last_rebased_version
|
81
|
-
raise VersionError.new("This branch is out-of-date (rev #{last_rebased_version}; mirror branch is at #{last_fetched_version}). You should do a git si rebase.")
|
82
|
-
elsif last_fetched_version < last_rebased_version
|
83
|
-
return if ask("This branch is newer (rev #{last_rebased_version}) than the mirror branch (rev #{last_fetched_version}). That can happen when svn changes have been made directly and may be fine. Do you want to continue? [Y/n] ", :green) =~ /\s*^n/i
|
84
|
-
end
|
85
|
-
else
|
86
|
-
notice_message "Could not determine last version information. This may be fine if you haven't used git-si before."
|
87
|
-
end
|
88
|
-
|
89
|
-
notice_message "Adding any files that are not already in svn to ensure an accurate diff."
|
90
|
-
readd()
|
91
|
-
|
92
|
-
command = "svn diff " + args.join(' ')
|
93
|
-
notice_message "Running #{command}"
|
94
|
-
results = `#{command}`
|
95
|
-
if STDOUT.tty?
|
96
|
-
page
|
97
|
-
print_colordiff results
|
98
|
-
else
|
99
|
-
say results
|
100
|
-
end
|
101
|
-
end
|
68
|
+
configure
|
69
|
+
do_diff_action( args )
|
102
70
|
end
|
103
71
|
|
72
|
+
################
|
73
|
+
# Action: add
|
74
|
+
################
|
104
75
|
desc "add [FILES]", "Perform an svn and a git add on the files."
|
105
76
|
def add(*args)
|
106
|
-
|
107
|
-
|
108
|
-
run_command(command)
|
109
|
-
command = "git add " + args.join(' ')
|
110
|
-
run_command(command)
|
111
|
-
end
|
77
|
+
configure
|
78
|
+
do_add_action( args )
|
112
79
|
end
|
113
80
|
|
81
|
+
################
|
82
|
+
# Action: fetch
|
83
|
+
################
|
114
84
|
desc "fetch", "Updates mirror branch to latest svn commit."
|
115
85
|
def fetch
|
116
|
-
|
117
|
-
|
118
|
-
raise GitError.new("There are local changes; please commit them before continuing.") if git_status.match(/^[^\?]/)
|
119
|
-
end
|
120
|
-
on_mirror_branch do
|
121
|
-
notice_message "Fetching remote data from svn"
|
122
|
-
updated_files = `svn up --accept theirs-full --ignore-externals`
|
123
|
-
files_to_add = []
|
124
|
-
updated_files.each_line do |line|
|
125
|
-
say line
|
126
|
-
case line.strip!
|
127
|
-
when /^A\s+(\S.+)/, /^Restored '(.+)'\s*$/
|
128
|
-
files_to_add << '"' + $1 + '"'
|
129
|
-
end
|
130
|
-
end
|
131
|
-
notice_message "Reverting any local changes in mirror branch"
|
132
|
-
run_command("svn revert -R ./")
|
133
|
-
unless files_to_add.empty?
|
134
|
-
files_to_add.each do |filename|
|
135
|
-
say "Updating file in git: #{filename}"
|
136
|
-
end
|
137
|
-
notice_message "Adding all those files"
|
138
|
-
system("git add --all " + files_to_add.join(' '))
|
139
|
-
end
|
140
|
-
run_command("git commit --allow-empty -am 'svn update to version #{get_svn_version}'")
|
141
|
-
end
|
142
|
-
success_message "fetch complete!"
|
86
|
+
configure
|
87
|
+
do_fetch_action
|
143
88
|
end
|
144
89
|
|
90
|
+
################
|
91
|
+
# Action: rebase
|
92
|
+
################
|
145
93
|
desc "rebase", "Rebases current branch to mirror branch."
|
146
94
|
def rebase
|
147
|
-
|
148
|
-
|
149
|
-
success_message "rebase complete!"
|
150
|
-
end
|
95
|
+
configure
|
96
|
+
do_rebase_action
|
151
97
|
end
|
152
98
|
|
99
|
+
################
|
100
|
+
# Action: pull
|
101
|
+
################
|
153
102
|
desc "pull", "Fetch the latest svn commit and rebase the current branch."
|
154
103
|
def pull
|
155
|
-
|
156
|
-
rebase
|
104
|
+
do_pull_action
|
157
105
|
end
|
158
106
|
|
107
|
+
################
|
108
|
+
# Action: commit
|
109
|
+
################
|
159
110
|
desc "commit", "Perform an svn commit and update the mirror branch."
|
160
111
|
def commit
|
161
|
-
|
162
|
-
|
163
|
-
on_local_branch do
|
164
|
-
local_branch = get_local_branch()
|
165
|
-
if local_branch == 'master'
|
166
|
-
notice_message "Warning: you're using the master branch as working copy. This can
|
167
|
-
cause trouble because when your changes are committed and you try to
|
168
|
-
rebase on top of them, you may end up with merge errors as you are
|
169
|
-
trying to apply patches of previous versions of your code. If you
|
170
|
-
continue, it's wise to reset the master branch afterward."
|
171
|
-
return if ask("Do you want to continue with this commit? [Y/n] ", :green) =~ /\s*^n/i
|
172
|
-
end
|
173
|
-
|
174
|
-
git_status = `git status --porcelain`
|
175
|
-
raise GitError.new("There are local changes; please commit them before continuing.") if git_status.match(/^[^\?]/)
|
176
|
-
|
177
|
-
notice_message "Adding any files that are not already in svn to ensure changes are committed."
|
178
|
-
readd()
|
179
|
-
|
180
|
-
svn_diff = `svn diff`
|
181
|
-
raise SvnError.new("Failed to get the svn diff. I'm not sure why. Check for any errors above.") if ! $?.success?
|
182
|
-
raise SvnError.new("There are no changes to commit.") if svn_diff.strip.empty?
|
183
|
-
|
184
|
-
run_command("svn commit")
|
185
|
-
success_message "commit complete!"
|
186
|
-
|
187
|
-
files_unchanged = true
|
188
|
-
git_status = `git status --porcelain`
|
189
|
-
files_unchanged = false if git_status.match(/^[^\?]/)
|
190
|
-
unless files_unchanged
|
191
|
-
if yes? "Some files were added or modified during the commit; should I revert them? [y/N] ", :yellow
|
192
|
-
run_command("git reset --hard HEAD")
|
193
|
-
files_unchanged = true
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
if files_unchanged and yes? "Do you want to update the mirror branch to the latest commit? [y/N] ", :green
|
198
|
-
fetch
|
199
|
-
mirror_is_updated = true
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
if mirror_is_updated
|
204
|
-
local_branch = get_local_branch()
|
205
|
-
if local_branch == 'master'
|
206
|
-
if yes? "Do you want to reset the current branch to the latest commit (losing all git history)? [y/N] ", :green
|
207
|
-
run_command("git checkout #{@@mirror_branch}")
|
208
|
-
run_command("git branch -D '#{local_branch}'")
|
209
|
-
run_command("git checkout -b #{local_branch}")
|
210
|
-
success_message "branch '#{local_branch}' reset!"
|
211
|
-
end
|
212
|
-
else
|
213
|
-
if yes? "Do you want to switch to master and delete the committed branch '#{local_branch}'? [y/N] ", :green
|
214
|
-
run_command("git checkout master")
|
215
|
-
rebase
|
216
|
-
run_command("git branch -D '#{local_branch}'")
|
217
|
-
success_message "branch '#{local_branch}' deleted!"
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
112
|
+
configure
|
113
|
+
do_commit_action
|
221
114
|
end
|
222
115
|
|
116
|
+
################
|
117
|
+
# Action: readd
|
118
|
+
################
|
223
119
|
desc "readd", "Add files to svn that have been added to git."
|
224
|
-
def readd
|
225
|
-
|
226
|
-
|
227
|
-
svn_status = `#{command}`
|
228
|
-
raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
|
229
|
-
files_to_add = []
|
230
|
-
using_stderr do
|
231
|
-
svn_status.each_line do |line|
|
232
|
-
case line.strip!
|
233
|
-
when /^X/, /\.git/, /\.swp$/
|
234
|
-
when /^\?\s+(\S.+)/
|
235
|
-
filename = $1
|
236
|
-
file_in_git = `git ls-files #{filename}`
|
237
|
-
raise GitError.new("Failed to list git files. I'm not sure why. Check for any errors above.") unless $?.success?
|
238
|
-
if not file_in_git.empty?
|
239
|
-
files_to_add << filename if file_in_git
|
240
|
-
say filename
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
if files_to_add.empty?
|
246
|
-
notice_message "There are no files to add."
|
247
|
-
return
|
248
|
-
end
|
249
|
-
using_stderr do
|
250
|
-
if yes? "Do you want to add the above files to svn? [y/N] ", :green
|
251
|
-
command = "svn add " + files_to_add.join(' ')
|
252
|
-
run_command(command)
|
253
|
-
success_message "Added files to svn that had been added to git."
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
desc "blame <FILE>", "Alias for svn blame."
|
260
|
-
def blame(*args)
|
261
|
-
on_local_branch do
|
262
|
-
command = "svn blame " + args.join(' ')
|
263
|
-
run_command(command)
|
264
|
-
end
|
120
|
+
def readd
|
121
|
+
configure
|
122
|
+
do_readd_action
|
265
123
|
end
|
266
124
|
|
125
|
+
################
|
126
|
+
# Action: init
|
127
|
+
################
|
267
128
|
desc "init", "Initializes git-si in this directory with a gitignore and creates a special mirror branch."
|
268
129
|
def init
|
269
|
-
|
270
|
-
|
271
|
-
`svn info`
|
272
|
-
raise SvnError.new("No svn repository was found here. Maybe you're in the wrong directory?") unless $?.success?
|
273
|
-
make_a_commit = false
|
274
|
-
|
275
|
-
# check for existing .git repo
|
276
|
-
if File.exist? '.git'
|
277
|
-
notice_message "Looks like a git repository already exists here."
|
278
|
-
else
|
279
|
-
notice_message "Initializing git repository"
|
280
|
-
`git init`
|
281
|
-
raise GitError.new("Failed to initialize git repository. I'm not sure why. Check for any errors above.") unless $?.success?
|
282
|
-
make_a_commit = true
|
283
|
-
end
|
284
|
-
|
285
|
-
# check for existing .gitingore
|
286
|
-
gitignore = [".svn", "*.sw?", ".config", "*.err", "*.pid", "*.log", "svn-commit.*", "*.orig"]
|
287
|
-
command = "svn status --ignore-externals "
|
288
|
-
svn_status = `#{command}`
|
289
|
-
raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
|
290
|
-
externals = []
|
291
|
-
svn_status.each_line do |line|
|
292
|
-
externals << $1 if line.strip.match(/^X\s+(\S.+)/)
|
293
|
-
end
|
294
|
-
gitignore += externals
|
295
|
-
gitignore = gitignore.join("\n")
|
296
|
-
|
297
|
-
if File.exist? '.gitignore'
|
298
|
-
notice_message "Looks like a gitignore file already exists here."
|
299
|
-
error_message "Be SURE that the gitignore contains the following:\n#{gitignore}"
|
300
|
-
else
|
301
|
-
notice_message "Creating gitignore file."
|
302
|
-
create_file('.gitignore', gitignore)
|
303
|
-
run_command("git add .gitignore")
|
304
|
-
make_a_commit = true
|
305
|
-
end
|
306
|
-
|
307
|
-
# make initial commit
|
308
|
-
if make_a_commit
|
309
|
-
notice_message "Making initial commit."
|
310
|
-
run_command("git add .")
|
311
|
-
run_command("git commit -am 'initial commit by git-si'")
|
312
|
-
end
|
313
|
-
|
314
|
-
# check for exiting mirror branch
|
315
|
-
`git show-ref refs/heads/#{@@mirror_branch}`
|
316
|
-
if $?.success?
|
317
|
-
notice_message "Looks like the mirror branch already exists here."
|
318
|
-
else
|
319
|
-
notice_message "Creating mirror branch '#{@@mirror_branch}'."
|
320
|
-
run_command("git branch '#{@@mirror_branch}'")
|
321
|
-
end
|
322
|
-
|
323
|
-
success_message "init complete!"
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
|
328
|
-
private
|
329
|
-
|
330
|
-
def get_svn_version
|
331
|
-
svn_info = `svn info`
|
332
|
-
results = svn_info.match(/^Revision:\s+(\d+)/)
|
333
|
-
return results[1] if results
|
334
|
-
return nil
|
335
|
-
end
|
336
|
-
|
337
|
-
def get_svn_root
|
338
|
-
svn_info = `svn info`
|
339
|
-
results = svn_info.match(/Root Path:\s+(.+)/)
|
340
|
-
return results[1] if results
|
341
|
-
return nil
|
342
|
-
end
|
343
|
-
|
344
|
-
def get_local_branch
|
345
|
-
git_branches = `git branch`
|
346
|
-
results = git_branches.match(/^\*\s+(\S+)/)
|
347
|
-
local_branch = results[1] if results
|
348
|
-
raise GitError.new("Could not find local branch name.") unless local_branch
|
349
|
-
return local_branch
|
350
|
-
end
|
351
|
-
|
352
|
-
def in_svn_root(&block)
|
353
|
-
root_dir = get_svn_root
|
354
|
-
raise SvnError.new("Could not find the svn root directory.") unless root_dir
|
355
|
-
notice_message "Changing directory to svn root: #{root_dir}"
|
356
|
-
Dir.chdir(root_dir) do
|
357
|
-
yield
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
def on_local_branch(&block)
|
362
|
-
begin
|
363
|
-
in_svn_root do
|
364
|
-
yield
|
365
|
-
end
|
366
|
-
rescue GitSiError => err
|
367
|
-
error_message err
|
368
|
-
exit false
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
def on_mirror_branch(&block)
|
373
|
-
local_branch = get_local_branch()
|
374
|
-
run_command("git checkout #{@@mirror_branch}")
|
375
|
-
begin
|
376
|
-
in_svn_root do
|
377
|
-
yield
|
378
|
-
end
|
379
|
-
rescue GitSiError => err
|
380
|
-
error_message err
|
381
|
-
exit false
|
382
|
-
ensure
|
383
|
-
run_command("git checkout #{local_branch}")
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
def using_stderr(&block)
|
388
|
-
old_stdout = $stdout
|
389
|
-
$stdout = $stderr
|
390
|
-
@silent = true
|
391
|
-
begin
|
392
|
-
yield
|
393
|
-
ensure
|
394
|
-
$stdout = old_stdout
|
395
|
-
@silent = false
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def success_message(message)
|
400
|
-
$stderr.puts set_color message, :green
|
401
|
-
end
|
402
|
-
|
403
|
-
def notice_message(message)
|
404
|
-
$stderr.puts set_color message, :yellow
|
405
|
-
end
|
406
|
-
|
407
|
-
def error_message(message)
|
408
|
-
$stderr.puts set_color message, :red
|
409
|
-
end
|
410
|
-
|
411
|
-
def run_command(command, options={})
|
412
|
-
if STDOUT.tty? and not @silent
|
413
|
-
run(command, options)
|
414
|
-
else
|
415
|
-
run(command, options.update(verbose: false, capture: true))
|
416
|
-
end
|
417
|
-
raise ShellError.new("There was an error while trying to run the command: #{command}. Look above for any errors.") unless $?.success?
|
418
|
-
end
|
419
|
-
|
420
|
-
def print_colordiff(diff)
|
421
|
-
diff.each_line do |line|
|
422
|
-
line.rstrip!
|
423
|
-
case line
|
424
|
-
when /^\+/, /^A/
|
425
|
-
line = set_color line, :green
|
426
|
-
when /^\-/, /^M/
|
427
|
-
line = set_color line, :red
|
428
|
-
when /^\?/
|
429
|
-
line = set_color line, :yellow
|
430
|
-
end
|
431
|
-
say line
|
432
|
-
end
|
130
|
+
configure
|
131
|
+
do_init_action
|
433
132
|
end
|
434
133
|
|
435
134
|
end
|