git_remote_branch 0.2.4 → 0.2.6

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.
@@ -0,0 +1,154 @@
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, tracking the new branch" do
24
+ setup do
25
+ in_directory_for :local2
26
+ run_grb_with 'track new_branch'
27
+ end
28
+
29
+ should_have_branch 'new_branch', :local, :remote
30
+ end
31
+
32
+ context "then deleting the branch" do
33
+ setup do
34
+ run_grb_with 'delete new_branch'
35
+ end
36
+
37
+ should_not_have_branch 'new_branch', :local, :remote
38
+
39
+ context "the remote repository" do
40
+ setup do
41
+ in_directory_for :remote
42
+ end
43
+
44
+ should_not_have_branch 'new_branch', :local
45
+ end
46
+ end
47
+
48
+ context "renaming the branch" do
49
+ setup do
50
+ in_directory_for :local1
51
+ in_branch :new_branch
52
+ run_grb_with 'rename renamed_branch'
53
+ end
54
+
55
+ should_not_have_branch 'new_branch', :local, :remote
56
+ should_have_branch 'renamed_branch', :local, :remote
57
+
58
+ context "the remote repository" do
59
+ setup do
60
+ in_directory_for :remote
61
+ end
62
+
63
+ should_not_have_branch 'new_branch', :local
64
+ should_have_branch 'renamed_branch', :local
65
+ end
66
+ end
67
+ end
68
+
69
+ context "having a local only branch" do
70
+ setup do
71
+ in_directory_for :local1
72
+ execute "git branch my_branch"
73
+ end
74
+
75
+ should_have_branch 'my_branch', :local #Sanity check
76
+
77
+ context "remotizing the branch" do
78
+ setup do
79
+ run_grb_with 'publish my_branch'
80
+ end
81
+
82
+ should_have_branch 'my_branch', :remote
83
+
84
+ context "the remote repository" do
85
+ setup do
86
+ in_directory_for :remote
87
+ end
88
+
89
+ should_have_branch 'my_branch', :local
90
+ end
91
+ end
92
+ end
93
+
94
+ context "running grb with a detailed explain" do
95
+ setup do
96
+ in_directory_for :local1
97
+ @text = run_grb_with 'explain create teh_branch somewhere'
98
+ end
99
+
100
+ should "display the commands to run with the user-specified values, including current_branch" do
101
+ %w{master somewhere refs/heads/teh_branch}.each do |word|
102
+ assert_match(/#{word}/, @text)
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ in_a_non_git_directory do
109
+ context "displaying help" do
110
+ setup do
111
+ @text = run_grb_with 'help'
112
+ end
113
+
114
+ should "work" do
115
+ words_in_help = %w{create delete explain git_remote_branch}
116
+ words_in_help.each do |word|
117
+ assert_match(/#{word}/, @text)
118
+ end
119
+ end
120
+
121
+ should "not complain" do
122
+ assert_no_match(/not a git repository/i, @text)
123
+ end
124
+ end
125
+
126
+ context "running grb with a generic explain" do
127
+ setup do
128
+ @text = run_grb_with 'explain create'
129
+ end
130
+
131
+ should "display the commands to run with dummy values filled in" do
132
+ #Not sure if this will turn out to be too precise to my liking...
133
+ generic_words_in_explain_create = %w{
134
+ origin current_branch refs/heads/branch_to_create
135
+ git push fetch checkout}
136
+ generic_words_in_explain_create.each do |word|
137
+ assert_match(/#{word}/, @text)
138
+ end
139
+ end
140
+ end
141
+
142
+ context "running grb with a detailed explain" do
143
+ setup do
144
+ @text = run_grb_with 'explain create teh_branch somewhere'
145
+ end
146
+
147
+ should "display the commands to run with the user-specified values (except for current_branch)" do
148
+ %w{somewhere current_branch refs/heads/teh_branch}.each do |word|
149
+ assert_match(/#{word}/, @text)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ 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
+
@@ -0,0 +1,25 @@
1
+ class DirStack
2
+ attr_reader :dir_stack
3
+
4
+ def current_dir
5
+ dir_stack.size == 0 ? Dir.pwd : dir_stack.last
6
+ end
7
+
8
+ def pushd(dirname)
9
+ dir_stack.push(File.expand_path(dirname))
10
+ end
11
+
12
+ def popd
13
+ return [] if dir_stack.size==0
14
+ dir_stack.pop
15
+ dir_stack
16
+ end
17
+
18
+ def to_s
19
+ dir_stack.inspect
20
+ end
21
+
22
+ def initialize
23
+ @dir_stack = []
24
+ end
25
+ end
@@ -0,0 +1,63 @@
1
+ module Extractable
2
+ # Hash#extract(*keys) => Hash
3
+ # Hash#extract([keys]) => Hash
4
+ # Hash#extract{|k,v| predicate } => Hash
5
+ #
6
+ # Returns a new Hash that contains only the k,v pairs where the k was
7
+ # specified in the keys array.
8
+ # If any k in keys is not present in the original Hash, it's simply
9
+ # not the resulting Hash.
10
+ #
11
+ # This is very useful to check that a Hash contains at least some desired keys
12
+ # or to get a sanitized Hash out of the one we currently have.
13
+ #
14
+ # Examples:
15
+ # h = {:bob=>'Marley',:mom=>'Barley'}
16
+ # h.extract(:bob) #=> {:bob=>'Marley'}
17
+ # h.extract(:bob, :mom) #=> {:bob=>'Marley',:mom=>'Barley'}
18
+ # h.extract([:bob, :mom]) #=> {:bob=>'Marley',:mom=>'Barley'}
19
+ # h.extract(:sos) #=> {}
20
+
21
+ def extract(*args, &block)
22
+ if block_given?
23
+ extract_block(&block)
24
+ elsif args[0].is_a? Proc
25
+ extract_block(&args[0])
26
+ elsif args.size == 0
27
+ raise ArgumentError, "extract requires either an array of keys, a block or a proc"
28
+ else
29
+ extract_keys(args)
30
+ end
31
+ end
32
+
33
+ # Returns two hashes. The first contains all pairs for which the block evaluated to true,
34
+ # the second contains all the others.
35
+ def split(&block)
36
+ trues, falses = self.class.new, self.class.new
37
+ each_pair do |k,v|
38
+ if yield(k,v)
39
+ trues[k] = v
40
+ else
41
+ falses[k] = v
42
+ end
43
+ end
44
+ #each_pair{ |k,v| (yield(k,v) ? trues : falses)[k] = v }
45
+ return trues, falses
46
+ end
47
+
48
+ private
49
+ def extract_keys(*keys)
50
+ extracted = self.class.new #Can therefore be included in any hash-like container
51
+ keys.flatten.each { |k| extracted[k] = self[k] if self.include?(k) }
52
+ extracted
53
+ end
54
+
55
+ def extract_block(&block)
56
+ extracted = self.class.new
57
+ each_pair{ |k,v| extracted[k] = v if yield(k,v) }
58
+ extracted
59
+ end
60
+ end
61
+
62
+
63
+ Hash.send :include, Extractable
@@ -0,0 +1,33 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+ require File.dirname(__FILE__) + '/temp_dir_helper'
4
+
5
+ # Instantiating a GitHelper object creates a temp directory containing 3 repos.
6
+ # 1 that's considered the remote repo and 2 peer local repos (local1 and local2).
7
+ # All 3 are synchronized with the same data (they contain a few dummy files).
8
+ # Once instantiated you can access the 3 full repo locations through attribute readers
9
+ # remote, local1 and local2.
10
+ class GitHelper < TempDirHelper
11
+
12
+ attr_reader :remote, :local1, :local2
13
+
14
+ def initialize
15
+ super('grb_test')
16
+
17
+ @remote = init_repo(directory, 'remote')
18
+ @local1 = clone_repo(@remote, directory, 'local1')
19
+ @local2 = clone_repo(@remote, directory, 'local2')
20
+ end
21
+
22
+ protected
23
+ def init_repo(path, name)
24
+ repo_dir = File.join(path, name)
25
+ `mkdir #{repo_dir}; cd $_; git init; touch file.txt; git add .; git commit -a -m "dummy file"`
26
+ repo_dir
27
+ end
28
+
29
+ def clone_repo(origin_path, clone_path, name)
30
+ `cd #{clone_path}; git clone #{File.join(origin_path, '.git')} #{name}`
31
+ return File.join(clone_path, name)
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ #require 'test/unit/assertionfailederror'
2
+ module MoreAssertions
3
+ include Test::Unit
4
+
5
+ def assert_false(condition, message = nil)
6
+ unless condition == false
7
+ raise AssertionFailedError, message || "assert_false failed"
8
+ end
9
+ end
10
+
11
+ def assert_array_content(expected_array, array, message = nil)
12
+ unless expected_array.count_all == array.count_all
13
+ raise AssertionFailedError, message || "arrays did not have the same content. Expected #{expected_array.inspect}, got #{array.inspect}"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,106 @@
1
+ module ShouldaFunctionalHelpers
2
+ include CaptureFu
3
+ GRB_COMMAND = File.expand_path(File.dirname(__FILE__) + '/../../bin/grb') unless defined?(GRB_COMMAND)
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.class_eval do
8
+ include ::ShouldaFunctionalHelpers::InstanceMethods
9
+ end
10
+ end
11
+
12
+ module InstanceMethods
13
+ def current_dir
14
+ @current_dir || raise("@current_dir is not set. Warning, Will Robinson!")
15
+ end
16
+
17
+ def current_dir=(value)
18
+ @current_dir = value
19
+ end
20
+
21
+ # Switches to one of the directories created by GitHelper:
22
+ # :local1, :local2, :non_git or :remote
23
+ # This affects commands run with ``, system and so on.
24
+ def in_directory_for(dir)
25
+ # Just a reminder for my dumb head
26
+ raise "'in_directory_for' depends on @gh being set" unless @gh
27
+
28
+ @current_dir = eval("@gh.#{dir}")
29
+ end
30
+
31
+ def in_branch(branch)
32
+ execute "git checkout #{branch}"
33
+ end
34
+
35
+
36
+ def run_grb_with(params='')
37
+ execute "#{GRB_COMMAND} #{params}"
38
+ end
39
+
40
+ def execute(command)
41
+ errno, returned_string = capture_process_output("cd #{current_dir} ; #{command}")
42
+ returned_string
43
+ end
44
+
45
+ private
46
+ def get_branch_location(location)
47
+ case location.to_sym
48
+ when :local
49
+ args = '-l'
50
+ when :remote
51
+ args = '-r'
52
+ else
53
+ raise ArgumentError, "Unknown branch location: #{location.inspect}"
54
+ end
55
+ end
56
+ end
57
+
58
+ module ClassMethods
59
+ def should_have_branch(what_branch, *wheres)
60
+ wheres.flatten.each do |where|
61
+ should "have the branch '#{what_branch}' #{where == :local ? 'locally' : 'remotely'}" do
62
+ args = get_branch_location(where)
63
+ assert_match(/#{what_branch}/, execute("git branch #{args}"))
64
+ end
65
+ end
66
+ end
67
+
68
+ def should_not_have_branch(what_branch, *wheres)
69
+ wheres.flatten.each do |where|
70
+ should "not have the branch '#{what_branch}' #{where == :local ? 'locally' : 'remotely'}" do
71
+ args = get_branch_location(where)
72
+ assert_no_match(/#{what_branch}/, execute("git branch #{args}"))
73
+ end
74
+ end
75
+ end
76
+
77
+ def on_a_repository
78
+ context "on a new repository" do
79
+ setup do
80
+ @gh = GitHelper.new
81
+ end
82
+
83
+ teardown do
84
+ @gh.cleanup
85
+ end
86
+
87
+ yield
88
+ end
89
+ end
90
+
91
+ def in_a_non_git_directory
92
+ context "on a non-git related directory" do
93
+ setup do
94
+ @temp_dir = TempDirHelper.new
95
+ @current_dir = @temp_dir.directory
96
+ end
97
+
98
+ teardown do
99
+ @temp_dir.cleanup
100
+ end
101
+
102
+ yield
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,88 @@
1
+ module ShouldaUnitHelpers
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ add_param_checkers(base)
5
+ end
6
+
7
+ def self.add_param_checkers(base)
8
+ # Excuse my french but:
9
+ %w(action branch origin current_branch silent explain).each do |param|
10
+ base.instance_eval(%Q!
11
+ def self.should_set_#{param}_to(#{param}_value)
12
+ should "set #{param} to #{ '#{' }#{ param }_value}" do
13
+ assert_equal #{param}_value, @p[:#{param}]
14
+ end
15
+ end
16
+ !)
17
+ end
18
+ # In other words, create a bunch of helpers like:
19
+ #
20
+ # def self.should_set_explain_to(explain_value)
21
+ # should "set explain to #{explain_value}" do
22
+ # assert_equal explain_value, @p[:explain]
23
+ # end
24
+ # end
25
+
26
+ end
27
+
28
+ module ClassMethods
29
+ def should_return_help_for_parameters(params, context_explanation)
30
+ context context_explanation do
31
+ setup do
32
+ @p = grb.read_params params
33
+ end
34
+
35
+ should "not even get to checking the current_branch" do
36
+ grb.expects(:get_current_branch).never
37
+ grb.read_params ['help']
38
+ end
39
+
40
+ should "only return a hash specifying the action" do
41
+ assert_array_content [:action], @p.keys
42
+ end
43
+
44
+ should_set_action_to :help
45
+ end
46
+ end
47
+
48
+ def should_explain_with_current_branch(current_branch_value, current_branch_explanation)
49
+ context "on an 'explain' command" do
50
+ context "with no information provided other than the action" do
51
+ setup do
52
+ @p = grb.read_params %w{explain create}
53
+ end
54
+
55
+ should_set_explain_to true
56
+ should_set_action_to :create
57
+ should_set_origin_to 'origin'
58
+
59
+ context current_branch_explanation do
60
+ should_set_current_branch_to current_branch_value
61
+ end
62
+
63
+ should "set a dummy new branch name" do
64
+ assert @p[:branch]
65
+ end
66
+ end
67
+
68
+ context "with all information provided" do
69
+ setup do
70
+ @p = grb.read_params %w{explain create specific_branch specific_origin}
71
+ end
72
+
73
+ should_set_explain_to true
74
+ should_set_action_to :create
75
+ should_set_current_branch_to current_branch_value
76
+
77
+ should "set the origin to 'specific_origin'" do
78
+ assert_equal 'specific_origin', @p[:origin]
79
+ end
80
+
81
+ should "set the specified branch name" do
82
+ assert_equal 'specific_branch', @p[:branch]
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,38 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+
4
+ class TempDirHelper
5
+ include FileUtils
6
+
7
+ attr_reader :directory
8
+
9
+ def initialize(namespace='temp_dir_helper')
10
+ @directory = get_temp_dir!(namespace)
11
+ end
12
+
13
+ def cleanup
14
+ rm_rf @directory
15
+ end
16
+
17
+ def to_s
18
+ directory
19
+ end
20
+
21
+ private
22
+ def get_temp_dir!(namespace='')
23
+ wd = File.expand_path( File.join( Dir::tmpdir, namespace) )
24
+ mkdir wd unless File.exists? wd
25
+
26
+ #Create new subdir with a random name
27
+ new_dir=''
28
+ begin
29
+ new_dir = File.join( wd, "#{rand(10000)}" )
30
+ mkdir new_dir
31
+
32
+ rescue
33
+ retry
34
+ end
35
+
36
+ new_dir
37
+ end
38
+ end
data/test/test_helper.rb CHANGED
@@ -3,19 +3,27 @@ require 'test/unit'
3
3
 
4
4
  test_dir = File.dirname(__FILE__)
5
5
 
6
- require 'redgreen'
6
+ # Install the non-Rails shoulda gem with 'gem install Shoulda'
7
+ # Notice the capitalization in the name.
8
+ require 'shoulda'
9
+ require 'mocha'
10
+
11
+ # Just load redgreen if not running tests from TextMate
12
+ IN_TM = !ENV['TM_DIRECTORY'].nil? unless defined?(IN_TM)
13
+ require 'redgreen' unless IN_TM
14
+
7
15
  require 'ruby-debug'
8
16
 
9
- require File.join(test_dir, 'git_helper')
10
17
  require File.join( [test_dir] + %w{ .. lib git_remote_branch} )
11
18
 
19
+ Dir[test_dir+'/helpers/**/*.rb'].each{|f| require f}
20
+
12
21
  class Test::Unit::TestCase
13
- include GitRemoteBranch
22
+ include MoreAssertions
14
23
 
15
- # Passes assertion if condition is false
16
- def assert_false(condition, message = nil)
17
- message = "assert_false failed" unless message
18
- assert condition == false, message
24
+ attr_reader :grb
25
+ def setup
26
+ @grb = Object.new
27
+ @grb.send :extend, GitRemoteBranch
19
28
  end
20
-
21
29
  end
@@ -0,0 +1,39 @@
1
+ require File.join( File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class GitRemoteBranchTest < Test::Unit::TestCase
4
+ context 'help' do
5
+ should 'contain examples for all basic commands' do
6
+ GitRemoteBranch::COMMANDS.keys.each do |k|
7
+ assert_match "grb #{k} branch_name", grb.get_usage
8
+ end
9
+ end
10
+
11
+ should 'contain an example for explain' do
12
+ assert_match 'grb explain', grb.get_usage
13
+ end
14
+
15
+ should 'contain an enumeration of all aliases' do
16
+ GitRemoteBranch::COMMANDS.each_pair do |k,v|
17
+ assert_match "#{k}: #{v[:aliases].join(', ')}", grb.get_usage
18
+ end
19
+ end
20
+ end
21
+
22
+ context "the reverse mapping for aliases" do
23
+ GitRemoteBranch::COMMANDS.each_pair do |cmd, params|
24
+ params[:aliases].each do |alias_|
25
+ should "contain the alias #{alias_}" do
26
+ assert GitRemoteBranch::ALIAS_REVERSE_MAP[alias_]
27
+ end
28
+ end
29
+ end
30
+
31
+ context "upon creation" do
32
+ should "raise an exception when there are duplicates" do
33
+ assert_raise(RuntimeError) do
34
+ GitRemoteBranch.get_reverse_map( GitRemoteBranch::COMMANDS.merge(:new_command => {:aliases => ['create']}) )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end