kch-git_remote_branch 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +164 -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 +120 -0
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
TEST_DIR = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
# Install version 2 the shoulda gem with
|
7
|
+
# gem install thoughtbot-shoulda --source http://gems.github.com
|
8
|
+
# Shoulda depends on ActiveSupport 2.0, so if you don't have Rails 2.x installed, install ActiveSupport before Shoulda:
|
9
|
+
# gem install activesupport
|
10
|
+
gem 'thoughtbot-shoulda', '~> 2.0'
|
11
|
+
require 'shoulda'
|
12
|
+
gem 'mocha', '~> 0.5'
|
13
|
+
require 'mocha'
|
14
|
+
|
15
|
+
# Just load redgreen if not running tests from TextMate
|
16
|
+
IN_TM = !ENV['TM_DIRECTORY'].nil? unless defined?(IN_TM)
|
17
|
+
begin
|
18
|
+
require 'redgreen' unless IN_TM
|
19
|
+
rescue LoadError => ex
|
20
|
+
puts "Couldn't load optional test dependencies: #{ex.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
require File.join( [TEST_DIR] + %w{ .. lib git_remote_branch} )
|
24
|
+
|
25
|
+
require "#{TEST_DIR}/helpers/in_dir"
|
26
|
+
Dir[TEST_DIR+'/helpers/**/*.rb'].each{|f| require f}
|
27
|
+
|
28
|
+
class Test::Unit::TestCase
|
29
|
+
include MoreAssertions
|
30
|
+
|
31
|
+
attr_reader :grb
|
32
|
+
def setup
|
33
|
+
@grb = Object.new
|
34
|
+
@grb.send :extend, GitRemoteBranch
|
35
|
+
end
|
36
|
+
end
|