kch-git_remote_branch 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,14 @@
1
+ module GitRemoteBranch
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 3
5
+ TINY = 0
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
@@ -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']
13
+ s.email = "webmat@gmail.com"
14
+ s.homepage = "http://github.com/webmat/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
@@ -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
@@ -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
@@ -0,0 +1,14 @@
1
+ # Can be included in any class that responds to #each.
2
+ # Such as Array.
3
+ module CountDistinct
4
+ def count_all(purge_smaller_than=0)
5
+ h={}
6
+ self.each {|e|
7
+ h[e] ? h[e] += 1 : h[e] = 1
8
+ }
9
+ h.extract{|k,v| v >= purge_smaller_than}
10
+ end
11
+ end
12
+
13
+ Array.send :include, CountDistinct
14
+