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,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,15 @@
|
|
1
|
+
REGULAR_BRANCH_LISTING = <<-STR
|
2
|
+
other_user/master
|
3
|
+
* stubbed_current_branch
|
4
|
+
rubyforge
|
5
|
+
STR
|
6
|
+
|
7
|
+
BRANCH_LISTING_WHEN_NOT_ON_BRANCH = <<-STR
|
8
|
+
* (no branch)
|
9
|
+
other_user/master
|
10
|
+
master
|
11
|
+
rubyforge
|
12
|
+
STR
|
13
|
+
|
14
|
+
WHEN_NOT_ON_GIT_REPOSITORY = "fatal: Not a git repository\n"
|
15
|
+
|
@@ -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,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/in_dir'
|
2
|
+
require File.dirname(__FILE__) + '/temp_dir_helper'
|
3
|
+
|
4
|
+
# Instantiating a GitHelper object creates a temp directory containing 3 repos.
|
5
|
+
# 1 that's considered the remote repo and 2 peer local repos (local1 and local2).
|
6
|
+
# All 3 are synchronized with the same data (they contain a few dummy files).
|
7
|
+
# Once instantiated you can access the 3 full repo locations through attribute readers
|
8
|
+
# remote, local1 and local2.
|
9
|
+
class GitHelper < TempDirHelper
|
10
|
+
include InDir
|
11
|
+
GIT = GitRemoteBranch::GIT
|
12
|
+
|
13
|
+
attr_reader :remote, :local1, :local2
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super("#{TEST_DIR}/test_runs")
|
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_p repo_dir
|
26
|
+
|
27
|
+
in_dir repo_dir do
|
28
|
+
`#{GIT} init && echo "foo" > file.txt && #{GIT} add . && #{GIT} commit -a -m "dummy file"`
|
29
|
+
end
|
30
|
+
raise "Error setting up repository #{name}" unless $?.exitstatus == 0
|
31
|
+
repo_dir
|
32
|
+
end
|
33
|
+
|
34
|
+
def clone_repo(origin_path, clone_path, name)
|
35
|
+
in_dir clone_path do
|
36
|
+
`#{GIT} clone #{File.join(origin_path, '.git').path_for_os} #{name}`
|
37
|
+
end
|
38
|
+
return File.join(clone_path, name)
|
39
|
+
end
|
40
|
+
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,152 @@
|
|
1
|
+
module ShouldaFunctionalHelpers
|
2
|
+
include CaptureFu
|
3
|
+
include InDir
|
4
|
+
|
5
|
+
GIT = GitRemoteBranch::GIT
|
6
|
+
|
7
|
+
def self.ruby_prefix
|
8
|
+
if ENV['RUBY']
|
9
|
+
warn " Forcing execution of grb with ruby interpreter #{ENV['RUBY']}"
|
10
|
+
ENV['RUBY'] + ' '
|
11
|
+
elsif WINDOWS
|
12
|
+
'ruby '
|
13
|
+
else
|
14
|
+
''
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Here we're only prepending with 'ruby'.
|
19
|
+
# When run as a gem, RubyGems takes care of generating a batch file that does this stuff.
|
20
|
+
GRB_COMMAND = ruby_prefix + File.expand_path(File.dirname(__FILE__) + '/../../bin/grb') unless defined?(GRB_COMMAND)
|
21
|
+
|
22
|
+
def self.included(base)
|
23
|
+
base.extend ClassMethods
|
24
|
+
base.class_eval do
|
25
|
+
include ::ShouldaFunctionalHelpers::InstanceMethods
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module InstanceMethods
|
30
|
+
def current_dir
|
31
|
+
@current_dir || raise("@current_dir is not set. Warning, Will Robinson!")
|
32
|
+
end
|
33
|
+
|
34
|
+
def current_dir=(value)
|
35
|
+
@current_dir = value
|
36
|
+
end
|
37
|
+
|
38
|
+
# Switches to one of the directories created by GitHelper:
|
39
|
+
# :local1, :local2, :non_git or :remote
|
40
|
+
# This affects commands run with ``, system and so on.
|
41
|
+
def in_directory_for(dir)
|
42
|
+
# Just a reminder for my dumb head
|
43
|
+
raise "'in_directory_for' depends on @gh being set" unless @gh
|
44
|
+
|
45
|
+
@current_dir = eval("@gh.#{dir}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def in_branch(branch)
|
49
|
+
execute "#{GIT} checkout #{branch}"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def run_grb_with(params='')
|
54
|
+
execute "#{GRB_COMMAND} #{params}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def execute(command)
|
58
|
+
in_dir current_dir do
|
59
|
+
errno, returned_string = capture_process_output(command)
|
60
|
+
returned_string
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def get_branch_location(location)
|
66
|
+
case location.to_sym
|
67
|
+
when :local
|
68
|
+
args = '-l'
|
69
|
+
when :remote
|
70
|
+
args = '-r'
|
71
|
+
else
|
72
|
+
raise ArgumentError, "Unknown branch location: #{location.inspect}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module ClassMethods
|
78
|
+
def should_have_branch(what_branch, *wheres)
|
79
|
+
wheres.flatten.each do |where|
|
80
|
+
should "have the branch '#{what_branch}' #{where == :local ? 'locally' : 'remotely'}" do
|
81
|
+
args = get_branch_location(where)
|
82
|
+
assert_match(/#{what_branch}/, execute("#{GIT} branch #{args}"))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def should_not_have_branch(what_branch, *wheres)
|
88
|
+
wheres.flatten.each do |where|
|
89
|
+
should "not have the branch '#{what_branch}' #{where == :local ? 'locally' : 'remotely'}" do
|
90
|
+
args = get_branch_location(where)
|
91
|
+
assert_no_match(/#{what_branch}/, execute("#{GIT} branch #{args}"))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def on_a_repository
|
97
|
+
context "on a new repository" do
|
98
|
+
setup do
|
99
|
+
@gh = GitHelper.new
|
100
|
+
end
|
101
|
+
|
102
|
+
teardown do
|
103
|
+
@gh.cleanup
|
104
|
+
end
|
105
|
+
|
106
|
+
context '' do
|
107
|
+
yield
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def in_a_non_git_directory
|
113
|
+
context "on a non-git related directory" do
|
114
|
+
setup do
|
115
|
+
@temp_dir = TempDirHelper.new
|
116
|
+
@current_dir = @temp_dir.directory
|
117
|
+
end
|
118
|
+
|
119
|
+
teardown do
|
120
|
+
@temp_dir.cleanup
|
121
|
+
end
|
122
|
+
|
123
|
+
context '' do
|
124
|
+
yield
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def with_env_var(name, value)
|
130
|
+
name = name.to_s
|
131
|
+
|
132
|
+
context "with environment variable '#{name}' set to '#{value}'" do
|
133
|
+
setup do
|
134
|
+
@env_previous_value = ENV[name] if ENV.keys.include?(name)
|
135
|
+
ENV[name] = value
|
136
|
+
end
|
137
|
+
|
138
|
+
teardown do
|
139
|
+
if @env_previous_value
|
140
|
+
ENV[name] = @env_previous_value
|
141
|
+
else
|
142
|
+
ENV.delete(name)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context '' do
|
147
|
+
yield
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
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(force_temp_dir=nil)
|
10
|
+
@directory = get_temp_dir!(force_temp_dir)
|
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!(parent_dir=nil)
|
23
|
+
temp_root = File.expand_path( File.join( parent_dir || Dir::tmpdir) )
|
24
|
+
mkdir_p temp_root
|
25
|
+
|
26
|
+
#Create new subdir with a random name
|
27
|
+
new_dir=''
|
28
|
+
begin
|
29
|
+
new_dir = File.join( temp_root, "#{rand(10000)}" )
|
30
|
+
mkdir new_dir
|
31
|
+
|
32
|
+
rescue
|
33
|
+
retry
|
34
|
+
end
|
35
|
+
|
36
|
+
new_dir
|
37
|
+
end
|
38
|
+
end
|