cypriss-git_remote_branch 0.3.3
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/CHANGELOG +32 -0
- data/LICENSE +18 -0
- data/README.rdoc +184 -0
- data/Rakefile +17 -0
- data/bin/grb +44 -0
- data/lib/constants.rb +5 -0
- data/lib/git_remote_branch.rb +177 -0
- data/lib/monkey_patches.rb +17 -0
- data/lib/param_reader.rb +63 -0
- data/lib/state.rb +42 -0
- data/lib/version.rb +14 -0
- data/tasks/gem.rake +89 -0
- data/tasks/rdoc.rake +15 -0
- data/tasks/test.rake +18 -0
- data/test/functional/grb_test.rb +188 -0
- data/test/helpers/array_extensions.rb +14 -0
- data/test/helpers/constants.rb +15 -0
- data/test/helpers/extractable.rb +63 -0
- data/test/helpers/git_helper.rb +40 -0
- data/test/helpers/in_dir.rb +10 -0
- data/test/helpers/more_assertions.rb +16 -0
- data/test/helpers/shoulda_functional_helpers.rb +152 -0
- data/test/helpers/shoulda_unit_helpers.rb +88 -0
- data/test/helpers/temp_dir_helper.rb +38 -0
- data/test/test_helper.rb +36 -0
- data/test/unit/git_helper_test.rb +30 -0
- data/test/unit/git_remote_branch_test.rb +39 -0
- data/test/unit/param_reader_test.rb +215 -0
- data/test/unit/state_test.rb +56 -0
- data/vendor/capture_fu.rb +58 -0
- metadata +121 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# One nice thing about command-line tools is that nobody cares how
|
2
|
+
# much you monkey-patch :-)
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
def whisper(*msgs)
|
6
|
+
unless $WHISPER
|
7
|
+
puts *msgs
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class String
|
13
|
+
def path_for_os
|
14
|
+
WINDOWS ? self.gsub('/', '\\') : self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/lib/param_reader.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module GitRemoteBranch
|
2
|
+
|
3
|
+
private
|
4
|
+
HELP_PARAMS = {:action => :help}
|
5
|
+
|
6
|
+
public
|
7
|
+
def read_params(argv)
|
8
|
+
#TODO Some validation on the params
|
9
|
+
|
10
|
+
p={}
|
11
|
+
p[:silent] = silent!(argv)
|
12
|
+
p[:explain] = explain_mode!(argv)
|
13
|
+
|
14
|
+
p[:action] = get_action(argv[0]) or return HELP_PARAMS
|
15
|
+
|
16
|
+
return HELP_PARAMS if p[:action] == :help
|
17
|
+
|
18
|
+
p[:branch] = get_branch(argv[1])
|
19
|
+
p[:origin] = get_origin(argv[2])
|
20
|
+
|
21
|
+
# If in explain mode, the user doesn't have to specify a branch or be on in
|
22
|
+
# actual repo to get the explanation.
|
23
|
+
# Of course if he is, the explanation will be made better by using contextual info.
|
24
|
+
if p[:explain]
|
25
|
+
p[:branch] ||= "branch_to_#{p[:action]}"
|
26
|
+
p[:current_branch] = begin
|
27
|
+
get_current_branch
|
28
|
+
rescue NotOnGitRepositoryError, InvalidBranchError
|
29
|
+
'current_branch'
|
30
|
+
end
|
31
|
+
|
32
|
+
else
|
33
|
+
return HELP_PARAMS unless p[:branch]
|
34
|
+
p[:current_branch] = get_current_branch
|
35
|
+
end
|
36
|
+
return p
|
37
|
+
end
|
38
|
+
|
39
|
+
def explain_mode!(argv)
|
40
|
+
if argv[0].to_s.downcase == 'explain'
|
41
|
+
argv.shift
|
42
|
+
true
|
43
|
+
else
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def silent!(argv)
|
49
|
+
!!argv.delete('--silent')
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_action(action)
|
53
|
+
ALIAS_REVERSE_MAP[action.to_s.downcase]
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_branch(branch)
|
57
|
+
branch
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_origin(origin)
|
61
|
+
return origin || 'origin'
|
62
|
+
end
|
63
|
+
end
|
data/lib/state.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module GitRemoteBranch
|
2
|
+
include ::CaptureFu
|
3
|
+
|
4
|
+
public
|
5
|
+
def get_current_branch
|
6
|
+
local_branch_information[0]
|
7
|
+
end
|
8
|
+
|
9
|
+
def local_branches
|
10
|
+
local_branch_information[1]
|
11
|
+
end
|
12
|
+
|
13
|
+
def git_found?
|
14
|
+
ret, msg = capture_process_output "#{GIT} --version"
|
15
|
+
ret == 0
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
# Returns an array of 2 elements: [current_branch, [all local branches]]
|
20
|
+
def local_branch_information
|
21
|
+
#This is sensitive to checkouts of branches specified with wrong case
|
22
|
+
|
23
|
+
listing = capture_process_output("#{LOCAL_BRANCH_LISTING_COMMAND}")[1]
|
24
|
+
|
25
|
+
raise(NotOnGitRepositoryError, listing.chomp) if listing =~ /Not a git repository/i
|
26
|
+
if listing =~ /\(no branch\)/
|
27
|
+
raise InvalidBranchError, ["Couldn't identify the current local branch. The branch listing was:",
|
28
|
+
LOCAL_BRANCH_LISTING_COMMAND.red,
|
29
|
+
listing].join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
current_branch = nil
|
33
|
+
branches = listing.split("\n").map do |line|
|
34
|
+
current = line.include? '*'
|
35
|
+
clean_line = line.gsub('*','').strip
|
36
|
+
current_branch = clean_line if current
|
37
|
+
clean_line
|
38
|
+
end
|
39
|
+
|
40
|
+
return current_branch, branches
|
41
|
+
end
|
42
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module GitRemoteBranch
|
2
|
+
module VERSION #:nodoc:
|
3
|
+
MAJOR = 0
|
4
|
+
MINOR = 3
|
5
|
+
TINY = 3
|
6
|
+
|
7
|
+
STRING = [MAJOR, MINOR, TINY].join('.').freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
NAME = 'git_remote_branch'.freeze
|
11
|
+
COMPLETE_NAME = "#{NAME} #{VERSION::STRING}".freeze
|
12
|
+
COMMAND_NAME = 'grb'.freeze
|
13
|
+
SHORT_NAME = COMMAND_NAME
|
14
|
+
end
|
data/tasks/gem.rake
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = GitRemoteBranch::NAME
|
7
|
+
s.version = GitRemoteBranch::VERSION::STRING
|
8
|
+
s.summary = "git_remote_branch eases the interaction with remote branches"
|
9
|
+
s.description = "git_remote_branch is a learning tool to ease the interaction with " +
|
10
|
+
"remote branches in simple situations."
|
11
|
+
|
12
|
+
s.authors = ['Mathieu Martin', 'Carl Mercier', 'Jonathan Novak']
|
13
|
+
s.email = "jnovak@gmail.com"
|
14
|
+
s.homepage = "http://github.com/cypriss/git_remote_branch"
|
15
|
+
s.rubyforge_project = 'grb'
|
16
|
+
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.extra_rdoc_files << 'README.rdoc'
|
19
|
+
s.rdoc_options << '--main' << 'README.rdoc' << '--exclude' << 'lib'
|
20
|
+
|
21
|
+
s.test_files = Dir['test/**/*'].reject{|f| f =~ /test_runs/}
|
22
|
+
s.files = Dir['**/*'].reject{|f| f =~ /\Apkg|\Acoverage|\Ardoc|test_runs|\.gemspec\Z/}
|
23
|
+
|
24
|
+
s.executable = 'grb'
|
25
|
+
s.bindir = "bin"
|
26
|
+
s.require_path = "lib"
|
27
|
+
|
28
|
+
s.add_dependency( 'colored', '>= 1.1' )
|
29
|
+
end
|
30
|
+
|
31
|
+
#Creates clobber_package, gem, package and repackage tasks
|
32
|
+
#Note on clobber_package: fortunately, this will clobber the CODE package
|
33
|
+
Rake::GemPackageTask.new(spec) do |p|
|
34
|
+
p.gem_spec = spec
|
35
|
+
end
|
36
|
+
|
37
|
+
TAG_COMMAND = "git tag -m 'Tagging version #{GitRemoteBranch::VERSION::STRING}' -a v#{GitRemoteBranch::VERSION::STRING}"
|
38
|
+
task :tag_warn do
|
39
|
+
puts "*" * 40,
|
40
|
+
"Don't forget to tag the release:",
|
41
|
+
'',
|
42
|
+
" " + TAG_COMMAND,
|
43
|
+
'',
|
44
|
+
"or run rake tag",
|
45
|
+
"*" * 40
|
46
|
+
end
|
47
|
+
task :tag do
|
48
|
+
sh TAG_COMMAND
|
49
|
+
puts "Upload tags to repo with 'git push --tags'"
|
50
|
+
end
|
51
|
+
task :gem => :tag_warn
|
52
|
+
|
53
|
+
namespace :gem do
|
54
|
+
desc "Update the gemspec for GitHub's gem server"
|
55
|
+
task :github do
|
56
|
+
File.open("#{GitRemoteBranch::NAME}.gemspec", 'w'){|f| f.puts YAML::dump(spec) }
|
57
|
+
puts "gemspec generated here: #{GitRemoteBranch::NAME}.gemspec"
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'Upload gem to rubyforge.org'
|
61
|
+
task :rubyforge => :gem do
|
62
|
+
sh 'rubyforge login'
|
63
|
+
sh "rubyforge add_release grb grb '#{GitRemoteBranch::VERSION::STRING}' pkg/#{spec.full_name}.gem"
|
64
|
+
sh "rubyforge add_file grb grb #{GitRemoteBranch::VERSION::STRING} pkg/#{spec.full_name}.gem"
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Install the gem built locally'
|
68
|
+
task :install => [:clean, :gem] do
|
69
|
+
sh "#{SUDO} gem install pkg/#{spec.full_name}.gem"
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Uninstall version #{GitRemoteBranch::VERSION::STRING} of the gem"
|
73
|
+
task :uninstall do
|
74
|
+
sh "#{SUDO} gem uninstall -v #{GitRemoteBranch::VERSION::STRING} -x #{GitRemoteBranch::NAME}"
|
75
|
+
end
|
76
|
+
|
77
|
+
if WINDOWS
|
78
|
+
win_spec = spec.dup
|
79
|
+
win_spec.platform = Gem::Platform::CURRENT
|
80
|
+
win_spec.add_dependency( 'win32console', '~> 1.1' ) # Missing dependency in the 'colored' gem
|
81
|
+
|
82
|
+
desc "Generate the Windows version of the gem"
|
83
|
+
namespace :windows do
|
84
|
+
Rake::GemPackageTask.new(win_spec) do |p|
|
85
|
+
p.gem_spec = win_spec
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/tasks/rdoc.rake
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
|
3
|
+
desc 'Generate rdoc documentation'
|
4
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
5
|
+
rdoc.rdoc_dir = 'rdoc'
|
6
|
+
rdoc.title = GitRemoteBranch::NAME
|
7
|
+
rdoc.rdoc_files.include('README.rdoc')
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :rdoc do
|
11
|
+
desc 'Upload documentation to rubyforge'
|
12
|
+
task :upload => :rdoc do
|
13
|
+
sh "scp -r #{GRB_ROOT}/rdoc/* webmat@rubyforge.org:/var/www/gforge-projects/grb/"
|
14
|
+
end
|
15
|
+
end
|
data/tasks/test.rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
desc "Run all tests"
|
4
|
+
task :test => ["test:unit", "test:functional"]
|
5
|
+
|
6
|
+
namespace :test do
|
7
|
+
desc "Run functional tests"
|
8
|
+
Rake::TestTask.new(:functional) do |t|
|
9
|
+
t.pattern = 'test/functional/**/*_test.rb'
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run unit tests"
|
14
|
+
Rake::TestTask.new(:unit) do |t|
|
15
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
16
|
+
t.verbose = true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class GRBTest < Test::Unit::TestCase
|
4
|
+
include ShouldaFunctionalHelpers
|
5
|
+
|
6
|
+
on_a_repository do
|
7
|
+
context "creating a branch in a local clone" do
|
8
|
+
setup do
|
9
|
+
in_directory_for :local1
|
10
|
+
run_grb_with 'create new_branch'
|
11
|
+
end
|
12
|
+
|
13
|
+
should_have_branch 'new_branch', :local, :remote
|
14
|
+
|
15
|
+
context "the remote repository" do
|
16
|
+
setup do
|
17
|
+
in_directory_for :remote
|
18
|
+
end
|
19
|
+
|
20
|
+
should_have_branch 'new_branch', :local
|
21
|
+
end
|
22
|
+
|
23
|
+
context "the other local clone" do
|
24
|
+
setup do
|
25
|
+
in_directory_for :local2
|
26
|
+
end
|
27
|
+
|
28
|
+
context "not already having a branch of the same name" do
|
29
|
+
setup do
|
30
|
+
@output = run_grb_with 'track new_branch'
|
31
|
+
end
|
32
|
+
|
33
|
+
should_have_branch 'new_branch', :local, :remote
|
34
|
+
|
35
|
+
should "use the branch --track command" do
|
36
|
+
assert_match %r{branch --track}, @output
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "having a branch of the same name" do
|
41
|
+
setup do
|
42
|
+
execute "git branch new_branch"
|
43
|
+
@output = run_grb_with 'track new_branch'
|
44
|
+
end
|
45
|
+
|
46
|
+
should_have_branch 'new_branch', :local, :remote
|
47
|
+
|
48
|
+
should "use git config to connect the branches" do
|
49
|
+
assert_match %r{git\sconfig}, @output
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "then deleting the branch" do
|
55
|
+
setup do
|
56
|
+
run_grb_with 'delete new_branch'
|
57
|
+
end
|
58
|
+
|
59
|
+
should_not_have_branch 'new_branch', :local, :remote
|
60
|
+
|
61
|
+
context "the remote repository" do
|
62
|
+
setup do
|
63
|
+
in_directory_for :remote
|
64
|
+
end
|
65
|
+
|
66
|
+
should_not_have_branch 'new_branch', :local
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "renaming the branch" do
|
71
|
+
setup do
|
72
|
+
in_directory_for :local1
|
73
|
+
in_branch :new_branch
|
74
|
+
run_grb_with 'rename renamed_branch'
|
75
|
+
end
|
76
|
+
|
77
|
+
should_not_have_branch 'new_branch', :local, :remote
|
78
|
+
should_have_branch 'renamed_branch', :local, :remote
|
79
|
+
|
80
|
+
context "the remote repository" do
|
81
|
+
setup do
|
82
|
+
in_directory_for :remote
|
83
|
+
end
|
84
|
+
|
85
|
+
should_not_have_branch 'new_branch', :local
|
86
|
+
should_have_branch 'renamed_branch', :local
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "having a local only branch" do
|
92
|
+
setup do
|
93
|
+
in_directory_for :local1
|
94
|
+
execute "git branch my_branch"
|
95
|
+
end
|
96
|
+
|
97
|
+
should_have_branch 'my_branch', :local #Sanity check
|
98
|
+
|
99
|
+
context "remotizing the branch" do
|
100
|
+
setup do
|
101
|
+
run_grb_with 'publish my_branch'
|
102
|
+
end
|
103
|
+
|
104
|
+
should_have_branch 'my_branch', :remote
|
105
|
+
|
106
|
+
context "the remote repository" do
|
107
|
+
setup do
|
108
|
+
in_directory_for :remote
|
109
|
+
end
|
110
|
+
|
111
|
+
should_have_branch 'my_branch', :local
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "running grb with a detailed explain" do
|
117
|
+
setup do
|
118
|
+
in_directory_for :local1
|
119
|
+
@text = run_grb_with 'explain create teh_branch somewhere'
|
120
|
+
end
|
121
|
+
|
122
|
+
should "display the commands to run with the user-specified values, including current_branch" do
|
123
|
+
%w{master somewhere refs/heads/teh_branch}.each do |word|
|
124
|
+
assert_match(/#{word}/, @text)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
in_a_non_git_directory do
|
131
|
+
with_env_var :GRB_GIT, 'unknown_git_executable_name' do
|
132
|
+
context "when git is not in the path" do
|
133
|
+
setup do
|
134
|
+
@text = run_grb_with ''
|
135
|
+
end
|
136
|
+
should "complain about git not being in the path" do
|
137
|
+
assert_match %r{unknown_git_executable_name}, @text
|
138
|
+
assert_match %r{PATH}, @text
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "displaying help" do
|
144
|
+
setup do
|
145
|
+
@text = run_grb_with 'help'
|
146
|
+
end
|
147
|
+
|
148
|
+
should "work" do
|
149
|
+
words_in_help = %w{create delete explain git_remote_branch}
|
150
|
+
words_in_help.each do |word|
|
151
|
+
assert_match(/#{word}/, @text)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
should "not complain" do
|
156
|
+
assert_no_match(/not a git repository/i, @text)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "running grb with a generic explain" do
|
161
|
+
setup do
|
162
|
+
@text = run_grb_with 'explain create'
|
163
|
+
end
|
164
|
+
|
165
|
+
should "display the commands to run with dummy values filled in" do
|
166
|
+
#Not sure if this will turn out to be too precise to my liking...
|
167
|
+
generic_words_in_explain_create = %w{
|
168
|
+
origin current_branch refs/heads/branch_to_create
|
169
|
+
git push fetch checkout}
|
170
|
+
generic_words_in_explain_create.each do |word|
|
171
|
+
assert_match(/#{word}/, @text)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "running grb with a detailed explain" do
|
177
|
+
setup do
|
178
|
+
@text = run_grb_with 'explain create teh_branch somewhere'
|
179
|
+
end
|
180
|
+
|
181
|
+
should "display the commands to run with the user-specified values (except for current_branch)" do
|
182
|
+
%w{somewhere current_branch refs/heads/teh_branch}.each do |word|
|
183
|
+
assert_match(/#{word}/, @text)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|