hitch 0.5.3 → 0.6.0

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/Rakefile CHANGED
@@ -1,18 +1,27 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ task :default => :spec
4
+
5
+ desc "Run specs"
6
+ Spec::Rake::SpecTask.new do |t|
7
+ t.spec_files = FileList['spec/**/*_spec.rb']
8
+ t.spec_opts = %w(-fs --color)
9
+ end
10
+
1
11
  begin
2
12
  require 'jeweler'
3
- require 'lib/hitch'
4
- require 'fileutils'
5
13
  Jeweler::Tasks.new do |gemspec|
6
14
  gemspec.name = %q{hitch}
7
- gemspec.version = Hitch::VERSION
15
+ gemspec.version = '0.6.0'
8
16
  gemspec.summary = %q{Hitch allows developers to be properly credited when Pair Programming and using Git.}
9
17
  gemspec.email = %q{rogelio@therubymug.com}
10
18
  gemspec.homepage = %q{http://github.com/therubymug/hitch}
11
19
  gemspec.has_rdoc = false
12
- gemspec.authors = ["Rogelio Samour", "Les Hill"]
20
+ gemspec.authors = ["Rogelio J. Samour"]
13
21
  gemspec.files = %w( README.rdoc Rakefile ) + Dir["{bin,lib}/**/*"].sort
14
22
  gemspec.extra_rdoc_files = ["README.rdoc"]
15
- gemspec.executables = ["hitch", "unhitch", "hitchrc"]
23
+ gemspec.executables = ["hitch"]
24
+ gemspec.add_development_dependency "rspec", ">= 1.3.0"
16
25
  gemspec.add_dependency('highline', '>= 1.5.0')
17
26
  end
18
27
  Jeweler::GemcutterTasks.new
data/bin/hitch CHANGED
@@ -1,9 +1,34 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch]))
5
- include Hitch
6
4
 
7
- if personal_info
8
- hitch
5
+ args = ARGV
6
+ options = []
7
+ opts = OptionParser.new do |opts|
8
+ opts.banner = "Usage: hitch [options] first_pair_username second_pair_username"
9
+ opts.separator ""
10
+ opts.separator "General options:"
11
+ opts.on("-s", "--setup", "Print out shell goodies") do
12
+ options = [:setup]
13
+ end
14
+ opts.on("-u", "--unhitch", "Clear pair information") do
15
+ options = [:unhitch]
16
+ end
17
+ opts.separator ""
18
+ opts.separator "Common options:"
19
+ opts.on_tail("-h", "--help", "Show this message") do
20
+ puts opts
21
+ exit
22
+ end
23
+ opts.on_tail("-v", "--version", "Show version") do
24
+ abort "hitch v#{Hitch.version}"
25
+ end
9
26
  end
27
+ if args.any?
28
+ opts.parse!(args)
29
+ options = [:export, args] if options.empty?
30
+ else
31
+ options = [:print_info]
32
+ end
33
+
34
+ Hitch.send(*options)
@@ -1,284 +1,134 @@
1
1
  require 'highline'
2
2
  require 'yaml'
3
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch options]))
3
+
4
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch author]))
5
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch ui]))
4
6
 
5
7
  module Hitch
6
8
 
7
- # :stopdoc:
8
- VERSION = '0.5.3'
9
- LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
10
- PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
11
- # :startdoc:
9
+ VERSION = '0.6.0'
12
10
 
13
- # Returns the version string for the library.
14
- #
15
11
  def self.version
16
12
  VERSION
17
13
  end
18
14
 
19
- # Returns the library path for the module. If any arguments are given,
20
- # they will be joined to the end of the libray path using
21
- # <tt>File.join</tt>.
22
- #
23
- def self.libpath( *args )
24
- args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
25
- end
26
-
27
- # Returns the lpath for the module. If any arguments are given,
28
- # they will be joined to the end of the path using
29
- # <tt>File.join</tt>.
30
- #
31
- def self.path( *args )
32
- args.empty? ? PATH : ::File.join(PATH, args.flatten)
33
- end
34
-
35
- # Utility method used to require all files ending in .rb that lie in the
36
- # directory below this file that has the same name as the filename passed
37
- # in. Optionally, a specific _directory_ name can be passed in such that
38
- # the _filename_ does not have to be equivalent to the directory.
39
- #
40
- def self.require_all_libs_relative_to( fname, dir = nil )
41
- dir ||= ::File.basename(fname, '.*')
42
- search_me = ::File.expand_path(
43
- ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
44
-
45
- Dir.glob(search_me).sort.each {|rb| require rb}
46
- end
47
-
48
- HighLine.track_eof = false
49
-
50
- def write_hitchrc
51
- personal_info['current_pair'] = current_pair
52
- File.open(hitchrc, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
53
- YAML.dump(personal_info, out)
15
+ def self.print_info
16
+ if Hitch.pairing?
17
+ Hitch::UI.highline.say("#{Hitch.git_author_name} <#{Hitch.git_author_email}>")
54
18
  end
55
19
  end
56
20
 
57
- def hitchrc
58
- @hitchrc ||= File.expand_path("~/.hitchrc")
59
- end
60
-
61
- def personal_info
62
- if File.exists?(hitchrc)
63
- @personal_info ||= YAML::load_file(hitchrc)
64
- else
65
- @personal_info ||= {}
66
- end
21
+ def self.export(pairs)
22
+ Hitch.current_pair = pairs
23
+ write_export_file
24
+ print_info
67
25
  end
68
26
 
69
- def hitch_pairs
70
- @hitch_pairs ||= File.expand_path("~/.hitch_pairs")
27
+ def self.unhitch
28
+ Hitch.current_pair = []
29
+ write_export_file
71
30
  end
72
31
 
73
- def pairs
74
- if File.exists?(hitch_pairs)
75
- @pairs ||= YAML::load_file(hitch_pairs)
32
+ def self.author_command
33
+ if Hitch.pairing?
34
+ "export GIT_AUTHOR_NAME='#{Hitch.git_author_name}' GIT_AUTHOR_EMAIL='#{Hitch.git_author_email}'"
76
35
  else
77
- @pairs ||= {}
36
+ "unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL"
78
37
  end
79
38
  end
80
39
 
81
- def write_hitch_pairs
82
- File.open(hitch_pairs, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
83
- YAML.dump(pairs, out)
84
- end
85
- end
86
-
87
- def ui
88
- @ui ||= HighLine.new
40
+ def self.group_email
41
+ config[:group_email] ||= Hitch::UI.prompt_for_group_email
89
42
  end
90
43
 
91
- def exporting_hitch_authors
92
- !!hitch_options.export_hitch_authors
44
+ def self.group_email=(email)
45
+ config[:group_email] = email
46
+ write_file
93
47
  end
94
48
 
95
- def write_hitch_authors
96
- File.open(File.expand_path('~/.hitch_export_authors'), "w") do |f|
97
- f.puts "# "
98
- f.puts "export GIT_AUTHOR_NAME='#{hitch_name}'"
99
- f.puts "export GIT_AUTHOR_EMAIL='#{hitch_email}'"
100
- end
49
+ def self.current_pair
50
+ config[:current_pair] ||= []
101
51
  end
102
52
 
103
- def write_gitconfig
104
- clean_gitconfig
105
- File.open(hitch_options.current_gitconfig, "a+") do |f|
106
- f.puts "# start - lines added by hitch #"
107
- f.puts "[user]"
108
- f.puts "\tname = '#{hitch_name}'"
109
- f.puts "\temail = #{hitch_email}"
110
- f.puts "# end - lines added by hitch #"
53
+ def self.current_pair=(pairs)
54
+ config[:current_pair] = []
55
+ pairs.each do |author|
56
+ if Hitch::Author.find(author)
57
+ config[:current_pair] << author
58
+ else
59
+ if new_author = Hitch::UI.prompt_for_pair(author)
60
+ config[:current_pair] << author
61
+ end
62
+ end
111
63
  end
64
+ write_file
112
65
  end
113
66
 
114
- def add_pair(git_name)
115
- current_pair << git_name
116
- current_pair.sort!
117
- current_pair.uniq!
67
+ def self.git_author_name
68
+ current_pair.sort.map {|pair| Hitch::Author.find(pair)}.join(' and ')
118
69
  end
119
70
 
120
- def current_pair
121
- @current_pair ||= (personal_info['current_pair'] or [])
71
+ def self.git_author_email
72
+ "#{group_prefix}+#{current_pair.sort.join('+')}@#{group_domain}"
122
73
  end
123
74
 
124
- def hitch_name
125
- my_pairs_and_i.map {|github, name| name}.join(' and ')
75
+ def self.group_prefix
76
+ group_email.split('@').first
126
77
  end
127
78
 
128
- def hitch_email
129
- "#{group_prefix}+#{my_pairs_and_i.map{|github, name| github}.join('+')}@#{group_domain}"
79
+ def self.group_domain
80
+ group_email.split('@').last
130
81
  end
131
82
 
132
- def my_pairs_and_i
133
- and_i = current_pair.map {|github| [github, pairs[github]]}
134
- and_i.sort_by {|github, name| github }
135
- end
136
-
137
- def group_prefix
138
- personal_info['group_email'].split('@').first
139
- end
83
+ def self.setup
84
+ Hitch::UI.highline.say <<-stp
140
85
 
141
- def group_domain
142
- personal_info['group_email'].split('@').last
143
- end
144
-
145
- def clean_hitch_authors
146
- authors_file = File.expand_path '~/.hitch_export_authors'
147
- File.open(authors_file, 'w') do |f|
148
- f.puts "unset GIT_AUTHOR_NAME"
149
- f.puts "unset GIT_AUTHOR_EMAIL"
150
- end
151
- end
86
+ # Add the following to your ~/.bashrc or ~/.zshrc
87
+ hitch() {
88
+ command hitch "$@"
89
+ if [[ -s "$HOME/.hitch_export_authors" ]] ; then source "$HOME/.hitch_export_authors" ; fi
90
+ }
91
+ alias unhitch='hitch -u'
92
+ # Uncomment to persist pair info between terminal instances
93
+ # hitch
152
94
 
153
- def clean_gitconfig(opts={:print => false})
154
- config_file = hitch_options.current_gitconfig
155
- ui.say " Clearing hitch info in: #{config_file}" if opts[:print]
156
- body = File.read(config_file)
157
- body.gsub!(/# start - lines added by hitch #\n.*?\n# end - lines added by hitch #\n/m, '')
158
- File.open(config_file + ".tmp", 'w') {|f| f.write(body)}
159
- File.rename(config_file + ".tmp", config_file)
95
+ stp
160
96
  end
161
97
 
162
- def prep_hitch_authors
163
- if pairing?
164
- write_hitch_authors
165
- else
166
- clean_hitch_authors
98
+ def self.write_file
99
+ File.open(hitchrc, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
100
+ YAML.dump(config, out)
167
101
  end
168
102
  end
169
103
 
170
- def prep_gitconfig
171
- if pairing?
172
- write_gitconfig
173
- else
174
- clean_gitconfig
175
- end
176
- end
104
+ private
177
105
 
178
- def unhitch
179
- if personal_info
180
- clear_pair_info
181
- write_hitchrc
182
- if exporting_hitch_authors
183
- clean_hitch_authors
184
- else
185
- clean_gitconfig(:print => true)
186
- end
187
- print_current_status
188
- end
106
+ def self.config
107
+ @config ||= get_config
189
108
  end
190
109
 
191
- def print_current_status
192
- if pairing?
193
- ui.say " Currently pairing with #{current_pair.join(' ')}."
194
- else
195
- ui.say " Currently coding solo."
110
+ def self.get_config
111
+ if File.exists?(hitchrc)
112
+ yamlized = YAML::load_file(hitchrc)
113
+ return yamlized if yamlized.kind_of?(Hash)
196
114
  end
115
+ return {}
197
116
  end
198
117
 
199
- def print_version
200
- ui.say "hitch v#{Hitch.version}"
201
- end
202
-
203
- def clear_pair_info
204
- personal_info['current_pair'] = []
205
- end
206
-
207
- def pairing?
208
- return false if personal_info.empty?
209
- return false if personal_info['current_pair'].nil? || personal_info['current_pair'].length.zero?
210
- return false if personal_info['current_pair'].length < 2
211
- true
118
+ def self.hitchrc
119
+ File.expand_path('~/.hitchrc')
212
120
  end
213
121
 
214
- def existing_pair?(pair)
215
- pairs.any? {|github, name| github == pair}
122
+ def self.hitch_export_authors
123
+ File.expand_path('~/.hitch_export_authors')
216
124
  end
217
125
 
218
- def hitch_options
219
- @hitch_options ||= Options.parse(ARGV)
126
+ def self.pairing?
127
+ current_pair.any?
220
128
  end
221
129
 
222
- def hitch
223
- case hitch_options.action
224
- when "manage_hitchrc"
225
- manage_hitchrc
226
- when "unhitch"
227
- unhitch
228
- when "hitch"
229
- if ARGV.any? && ARGV.size >= 2
230
- potential_pairs = ARGV
231
- save_pairs = false
232
- clear_pair_info
233
-
234
- potential_pairs.each do |pair|
235
- unless existing_pair?(pair)
236
- ui.say("I don't know who #{pair} is.")
237
- if ui.agree("Do you want to add #{pair} to ~/.hitch_pairs? ", true)
238
- pairs[pair] = ui.ask("What is #{pair}'s full name?") do |q|
239
- q.validate = /\A[-(\w|.,)+\s?]+\Z/
240
- end
241
- add_pair(pair)
242
- save_pairs ||= true
243
- else
244
- ui.say("Ignoring #{pair}.")
245
- end
246
- else
247
- add_pair(pair)
248
- end
249
- end
250
- write_hitchrc
251
- write_hitch_pairs if save_pairs
252
- if exporting_hitch_authors
253
- prep_hitch_authors
254
- else
255
- prep_gitconfig
256
- end
257
- else
258
- ui.say " Silly Rabbit! A pair is comprised of two." unless ARGV.size.zero?
259
- end
260
- print_current_status
261
- end
262
- end
263
-
264
- def manage_hitchrc
265
- begin
266
- unless File.exists?(hitchrc) and !ui.agree("Do you want to overwrite your #{ENV['HOME']}/.hitchrc file?", true)
267
- ui.say("Let's setup your #{ENV['HOME']}/.hitchrc file")
268
-
269
- personal_info['group_email'] = ui.ask("What is the group email? e.g. dev@hashrocket.com will become dev+therubymug+leshill@hashrocket.com") do |q|
270
- q.case = :down
271
- q.validate = /\A[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+\z/ # Simple email validation.
272
- end
273
-
274
- write_hitchrc
275
- end
276
- rescue EOFError # HighLine throws this if @input.eof?
277
- break
278
- end
279
-
280
- print_current_status
130
+ def self.write_export_file
131
+ File.open(hitch_export_authors, 'w'){|f| f.write(author_command) }
281
132
  end
282
- end # module Hitch
283
133
 
284
- Hitch.require_all_libs_relative_to(__FILE__)
134
+ end
@@ -0,0 +1,39 @@
1
+ module Hitch
2
+ class Author
3
+
4
+ def self.add(author_github, author_email)
5
+ unless find(author_github)
6
+ available_pairs[author_github] = author_email
7
+ end
8
+ end
9
+
10
+ def self.find(author_github)
11
+ available_pairs[author_github]
12
+ end
13
+
14
+ def self.write_file
15
+ File.open(hitch_pairs, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
16
+ YAML.dump(available_pairs, out)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def self.hitch_pairs
23
+ File.expand_path("~/.hitch_pairs")
24
+ end
25
+
26
+ def self.available_pairs
27
+ @available_pairs ||= get_available_pairs
28
+ end
29
+
30
+ def self.get_available_pairs
31
+ if File.exists?(hitch_pairs)
32
+ yamlized = YAML::load_file(hitch_pairs)
33
+ return yamlized if yamlized.kind_of?(Hash)
34
+ end
35
+ return {}
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ HighLine.track_eof = false
2
+
3
+ module Hitch
4
+ class UI
5
+
6
+ def self.prompt_for_group_email
7
+ Hitch.group_email = highline.ask("What is the group email? e.g. dev@hashrocket.com will become dev+therubymug+leshill@hashrocket.com") do |q|
8
+ q.case = :down
9
+ q.validate = /\A[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+\z/
10
+ end
11
+ end
12
+
13
+ def self.prompt_for_pair(new_author)
14
+ highline.say("I don't know who #{new_author} is.")
15
+ if highline.agree("Do you want to add #{new_author} to ~/.hitch_pairs?", true)
16
+ author_name = highline.ask("What is #{new_author}'s full name?") do |q|
17
+ q.validate = /\A[-(\w|.,)+\s?]+\Z/
18
+ end
19
+ Hitch::Author.add(new_author, author_name)
20
+ Hitch::Author.write_file
21
+ return new_author
22
+ else
23
+ highline.say("Ignoring #{new_author}.")
24
+ end
25
+ return nil
26
+ end
27
+
28
+ private
29
+
30
+ def self.highline
31
+ @highline ||= HighLine.new
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ require 'yaml'
2
+ require 'highline'
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'hitch')
7
+
8
+ Spec::Runner.configure do |config|
9
+ config.before(:each) do
10
+ Hitch.stub(:hitchrc).and_return(Tempfile.new('hitchrc').path)
11
+ Hitch.stub(:hitch_export_authors).and_return(Tempfile.new('hitch_export_authors').path)
12
+ Hitch::Author.stub(:hitch_pairs).and_return(Tempfile.new('hitch_pairs').path)
13
+ end
14
+ end
@@ -0,0 +1,57 @@
1
+ require 'helper'
2
+
3
+ describe Hitch::Author do
4
+
5
+ let(:base_pairs) do
6
+ {
7
+ 'bender' => 'Bender Bending Rodriguez',
8
+ 'fry' => 'Phillip J. Fry',
9
+ 'leela' => 'Turanga Leela'
10
+ }
11
+ end
12
+
13
+ before { Hitch::Author.stub(:available_pairs).and_return(base_pairs) }
14
+
15
+ describe ".write_file" do
16
+ it "writes the contents of Hitch::Author.available_pairs to the hitch_pairs file" do
17
+ YAML.should_receive(:dump)
18
+ Hitch::Author.write_file
19
+ end
20
+ end
21
+
22
+ describe ".add" do
23
+
24
+ before { Hitch::Author.stub(:available_pairs).and_return({}) }
25
+
26
+ context "when the author is not present" do
27
+ it "adds the author to Hitch::Author.available_pairs" do
28
+ Hitch::Author.add("therubymug", "Rogelio J. Samour")
29
+ Hitch::Author.available_pairs.should == {"therubymug" => "Rogelio J. Samour"}
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ describe ".find" do
36
+
37
+ context "when the author is present" do
38
+
39
+ before do
40
+ Hitch::Author.stub(:available_pairs).and_return({"therubymug" => "Rogelio J. Samour"})
41
+ end
42
+
43
+ it "and_return the full name" do
44
+ Hitch::Author.find("therubymug").should == "Rogelio J. Samour"
45
+ end
46
+
47
+ end
48
+
49
+ context "when the author is not present" do
50
+ it "and_return nil" do
51
+ Hitch::Author.find("nobody").should be_nil
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,78 @@
1
+ require 'helper'
2
+
3
+ describe Hitch::UI do
4
+
5
+ describe '.prompt_for_group_email' do
6
+
7
+ it 'prompts for group email' do
8
+ Hitch::UI.highline.should_receive(:ask).with("What is the group email? e.g. dev@hashrocket.com will become dev+therubymug+leshill@hashrocket.com")
9
+ Hitch::UI.prompt_for_group_email
10
+ end
11
+
12
+ it 'returns the given group email' do
13
+ Hitch::UI.highline.stub(:ask).with("What is the group email? e.g. dev@hashrocket.com will become dev+therubymug+leshill@hashrocket.com").and_return('dev@hashrocket.com')
14
+ Hitch::UI.prompt_for_group_email.should == 'dev@hashrocket.com'
15
+ end
16
+
17
+ it 'sets Hitch.group_email' do
18
+ Hitch.should_receive('group_email=').with('dev@hashrocket.com')
19
+ Hitch::UI.highline.stub(:ask).with("What is the group email? e.g. dev@hashrocket.com will become dev+therubymug+leshill@hashrocket.com").and_return('dev@hashrocket.com')
20
+ Hitch::UI.prompt_for_group_email
21
+ end
22
+
23
+ end
24
+
25
+ describe '.prompt_for_pair' do
26
+
27
+ let(:new_author) { 'leela' }
28
+ let(:new_author_name) { 'Turanga Leela' }
29
+
30
+ before do
31
+ Hitch::UI.highline.stub(:ask).and_return(new_author_name)
32
+ Hitch::UI.highline.stub(:say)
33
+ end
34
+
35
+ it 'states that the new pair is not in the hitch_pairs file' do
36
+ Hitch::UI.highline.should_receive(:say).with("I don't know who #{new_author} is.")
37
+ Hitch::UI.prompt_for_pair(new_author)
38
+ end
39
+
40
+ it 'prompts for pair' do
41
+ Hitch::UI.highline.should_receive(:agree).with("Do you want to add #{new_author} to ~/.hitch_pairs?", true)
42
+ Hitch::UI.prompt_for_pair(new_author)
43
+ end
44
+
45
+ context 'when user does not agree to add new author' do
46
+ it "states it's ignoring the author" do
47
+ Hitch::UI.highline.stub(:agree).and_return(false)
48
+ Hitch::UI.highline.should_receive(:say).with("Ignoring #{new_author}.")
49
+ Hitch::UI.prompt_for_pair(new_author)
50
+ end
51
+ end
52
+
53
+ context 'when user agrees to add new author' do
54
+
55
+ before do
56
+ Hitch::UI.highline.stub(:agree).and_return(true)
57
+ end
58
+
59
+ it "asks for the new author's name" do
60
+ Hitch::UI.highline.should_receive(:ask).with("What is #{new_author}'s full name?")
61
+ Hitch::UI.prompt_for_pair(new_author)
62
+ end
63
+
64
+ it "adds the new author" do
65
+ Hitch::Author.should_receive(:add).with(new_author, new_author_name)
66
+ Hitch::UI.prompt_for_pair(new_author)
67
+ end
68
+
69
+ it "writes the ~/.hitch_pairs file" do
70
+ Hitch::Author.should_receive(:write_file)
71
+ Hitch::UI.prompt_for_pair(new_author)
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,205 @@
1
+ require 'helper'
2
+
3
+ describe Hitch do
4
+
5
+ let(:hitch_pairs) {{'leela' => 'Turanga Leela', 'fry' => 'Philip J. Fry'}}
6
+
7
+ let(:hitch_config) do
8
+ { :group_email => 'dev@hashrocket.com',
9
+ :current_pair => ['leela', 'fry'] }
10
+ end
11
+
12
+ before do
13
+ Hitch.stub(:config).and_return(hitch_config)
14
+ Hitch::Author.stub(:available_pairs).and_return(hitch_pairs)
15
+ end
16
+
17
+ describe '.author_command' do
18
+
19
+ context 'when pairing' do
20
+ it 'returns the export shell command for GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL' do
21
+ Hitch.current_pair = ['leela', 'fry']
22
+ Hitch.author_command.should == "export GIT_AUTHOR_NAME='Philip J. Fry and Turanga Leela' GIT_AUTHOR_EMAIL='dev+fry+leela@hashrocket.com'"
23
+ end
24
+ end
25
+
26
+ context 'when not pairing' do
27
+ it 'returns the unset shell command for GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL' do
28
+ Hitch.current_pair = []
29
+ Hitch.author_command.should == "unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL"
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ describe '.unhitch' do
36
+
37
+ let(:pairs) { ['fry', 'leela'] }
38
+
39
+ it 'sets the current pair to an empty array' do
40
+ Hitch.should_receive(:current_pair=).with([])
41
+ Hitch.unhitch
42
+ end
43
+
44
+ it 'writes the export file' do
45
+ Hitch.should_receive(:write_export_file)
46
+ Hitch.unhitch
47
+ end
48
+
49
+ end
50
+
51
+ describe '.print_info' do
52
+
53
+ context 'when pairing' do
54
+ it 'returns the pair name and email being used' do
55
+ Hitch::UI.highline.should_receive(:say).with("Philip J. Fry and Turanga Leela <dev+fry+leela@hashrocket.com>")
56
+ Hitch.current_pair = ['leela', 'fry']
57
+ Hitch.print_info
58
+ end
59
+ end
60
+
61
+ context 'when not pairing' do
62
+ it 'returns nothing' do
63
+ Hitch.current_pair = []
64
+ Hitch.print_info.should be_nil
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ describe '.export' do
71
+
72
+ let(:pairs) { ['fry', 'leela'] }
73
+
74
+ before do
75
+ Hitch.stub(:print_info)
76
+ end
77
+
78
+ it 'sets the current pair' do
79
+ Hitch.should_receive(:current_pair=).with(pairs)
80
+ Hitch.export(pairs)
81
+ end
82
+
83
+ it 'writes the export file' do
84
+ Hitch.should_receive(:write_export_file)
85
+ Hitch.export(pairs)
86
+ end
87
+
88
+ it 'prints out pair info' do
89
+ Hitch.should_receive(:print_info)
90
+ Hitch.export(pairs)
91
+ end
92
+
93
+ end
94
+
95
+ describe '.current_pair=' do
96
+
97
+ before { Hitch.stub(:write_file) }
98
+
99
+ it 'writes the hitchrc file' do
100
+ Hitch.should_receive(:write_file)
101
+ Hitch.current_pair = ['leela', 'fry']
102
+ end
103
+
104
+ context 'when there are no new authors' do
105
+ it 'sets the current pair with the authors given' do
106
+ Hitch.current_pair = ['leela', 'fry']
107
+ Hitch.current_pair.should == ['leela', 'fry']
108
+ end
109
+ end
110
+
111
+ context 'when there are new authors' do
112
+
113
+ let(:new_author) { 'therubymug' }
114
+
115
+ it "prompts for the new author's info" do
116
+ Hitch::UI.should_receive(:prompt_for_pair).with(new_author)
117
+ Hitch.current_pair = [new_author, 'fry']
118
+ end
119
+
120
+ it 'adds the new author to current pair' do
121
+ Hitch::UI.stub(:prompt_for_pair).and_return(new_author)
122
+ Hitch.current_pair = [new_author, 'fry']
123
+ Hitch.current_pair.should == [new_author, 'fry']
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ describe '.current_pair' do
131
+ it 'returns an array of Github usernames' do
132
+ Hitch.stub(:config).and_return(hitch_config)
133
+ Hitch.current_pair.should == ['leela', 'fry']
134
+ end
135
+ end
136
+
137
+ describe '.group_email' do
138
+
139
+ context 'when absent from Hitch.config' do
140
+ before { Hitch.stub(:config).and_return({}) }
141
+ it 'prompts the user for it' do
142
+ Hitch::UI.should_receive(:prompt_for_group_email)
143
+ Hitch.group_email
144
+ end
145
+ end
146
+
147
+ context 'when present in Hitch.config' do
148
+ it 'returns the value' do
149
+ Hitch.group_email.should == 'dev@hashrocket.com'
150
+ end
151
+ end
152
+
153
+ end
154
+
155
+ describe '.group_email=' do
156
+
157
+ before { Hitch.stub(:write_file) }
158
+
159
+ it 'writes the hitchrc file' do
160
+ Hitch.should_receive(:write_file)
161
+ Hitch.group_email = 'dev@hashrocket.com'
162
+ end
163
+
164
+ it 'sets the current pair with the authors given' do
165
+ Hitch.group_email = 'dev@hashrocket.com'
166
+ Hitch.group_email.should == 'dev@hashrocket.com'
167
+ end
168
+
169
+ end
170
+
171
+ describe '.group_prefix' do
172
+ it 'returns the user portion of the group email' do
173
+ Hitch.group_prefix.should == 'dev'
174
+ end
175
+ end
176
+
177
+ describe '.group_domain' do
178
+ it 'returns the user portion of the group email' do
179
+ Hitch.group_domain.should == 'hashrocket.com'
180
+ end
181
+ end
182
+
183
+ describe '.git_author_name' do
184
+ it 'returns all author names joined by an "and" sorted alphabetically' do
185
+ Hitch.git_author_name.should == 'Philip J. Fry and Turanga Leela'
186
+ end
187
+ end
188
+
189
+ describe '.git_author_email' do
190
+ it 'returns all author github names coalesced into the group email' do
191
+ Hitch.git_author_email.should == 'dev+fry+leela@hashrocket.com'
192
+ end
193
+ end
194
+
195
+ describe ".write_file" do
196
+ it "writes the contents of Hitch.config to the hitchrc file" do
197
+ YAML.should_receive(:dump)
198
+ Hitch.write_file
199
+ end
200
+ end
201
+
202
+ describe '.command' do
203
+ end
204
+
205
+ end
metadata CHANGED
@@ -1,56 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hitch
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 7
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 5
8
- - 3
9
- version: 0.5.3
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
10
11
  platform: ruby
11
12
  authors:
12
- - Rogelio Samour
13
- - Les Hill
13
+ - Rogelio J. Samour
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-03-02 00:00:00 -05:00
19
- default_executable:
18
+ date: 2010-08-24 00:00:00 -04:00
19
+ default_executable: hitch
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: highline
22
+ name: rspec
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 27
30
+ segments:
31
+ - 1
32
+ - 3
33
+ - 0
34
+ version: 1.3.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: highline
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
28
46
  segments:
29
47
  - 1
30
48
  - 5
31
49
  - 0
32
50
  version: 1.5.0
33
51
  type: :runtime
34
- version_requirements: *id001
52
+ version_requirements: *id002
35
53
  description:
36
54
  email: rogelio@therubymug.com
37
55
  executables:
38
56
  - hitch
39
- - unhitch
40
- - hitchrc
41
57
  extensions: []
42
58
 
43
- extra_rdoc_files:
44
- - README.rdoc
59
+ extra_rdoc_files: []
60
+
45
61
  files:
46
- - README.rdoc
47
62
  - Rakefile
48
63
  - bin/hitch
49
- - bin/hitchrc
50
- - bin/hitchstatus
51
- - bin/unhitch
52
64
  - lib/hitch.rb
53
- - lib/hitch/options.rb
65
+ - lib/hitch/author.rb
66
+ - lib/hitch/ui.rb
67
+ - spec/helper.rb
68
+ - spec/hitch/author_spec.rb
69
+ - spec/hitch/ui_spec.rb
70
+ - spec/hitch_spec.rb
54
71
  has_rdoc: true
55
72
  homepage: http://github.com/therubymug/hitch
56
73
  licenses: []
@@ -61,25 +78,32 @@ rdoc_options:
61
78
  require_paths:
62
79
  - lib
63
80
  required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
64
82
  requirements:
65
83
  - - ">="
66
84
  - !ruby/object:Gem::Version
85
+ hash: 3
67
86
  segments:
68
87
  - 0
69
88
  version: "0"
70
89
  required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
71
91
  requirements:
72
92
  - - ">="
73
93
  - !ruby/object:Gem::Version
94
+ hash: 3
74
95
  segments:
75
96
  - 0
76
97
  version: "0"
77
98
  requirements: []
78
99
 
79
100
  rubyforge_project:
80
- rubygems_version: 1.3.6
101
+ rubygems_version: 1.3.7
81
102
  signing_key:
82
103
  specification_version: 3
83
104
  summary: Hitch allows developers to be properly credited when Pair Programming and using Git.
84
- test_files: []
85
-
105
+ test_files:
106
+ - spec/helper.rb
107
+ - spec/hitch/author_spec.rb
108
+ - spec/hitch/ui_spec.rb
109
+ - spec/hitch_spec.rb
@@ -1,76 +0,0 @@
1
- = hitch
2
- by Rogelio J. Samour
3
- http://therubymug.com
4
-
5
- == DESCRIPTION:
6
-
7
- Hitch allows developers to be properly credited when Pair Programming and using Git.
8
-
9
- == FEATURES:
10
-
11
- * Persists pair(s) between different terminal instances.
12
- * Creates a unique email address for the pair. (e.g. dev+leshill+therubymug@hashrocket.com) This provides the ability to create a Gravatar for the pair.
13
-
14
- == SYNOPSIS:
15
-
16
- - First, create your hitchrc by running:
17
- - hitch -m
18
- - For therubymug and leshill to pair in the current project:
19
- - hitch leshill therubymug
20
- - or globally:
21
- - hitch -g leshill therubymug
22
- - To clear pair info (for the local project):
23
- - hitch -u
24
- - To clear pair info in the global file:
25
- - hitch -u -g
26
- - For a complete list of features:
27
- - hitch -h
28
- - Creating a Gravatar for your pair:
29
- - Once I've hitched with my pair. (e.g. hitch leshill) I have now created a unique email: dev+leshill+therubymug@hashrocket.com
30
- - Then, I go to gravatar.com. Add an image to that particular email address and I'm done.
31
- - If you want to allow different committer vs author, then:
32
- - unhitch (unhitch the current project)
33
- - unhitch -g (globally unhitch)
34
- - add the following aliases to your .bashrc:
35
- alias hitch='hitch -p -g'
36
- alias unhitch='unhitch -p -g'
37
- alias git='. ~/.hitch_export_authors && git'
38
-
39
- == REQUIREMENTS:
40
-
41
- * Git, HighLine
42
-
43
- == INSTALL:
44
-
45
- * sudo gem install therubymug-hitch
46
-
47
- == ACKNOWLEDGEMENTS:
48
-
49
- * Les Hill
50
- * Tim Pope
51
- * Bodaniel Jeanes
52
-
53
- == LICENSE:
54
-
55
- (The MIT License)
56
-
57
- Copyright (c) 2009 Rogelio J. Samour
58
-
59
- Permission is hereby granted, free of charge, to any person obtaining
60
- a copy of this software and associated documentation files (the
61
- 'Software'), to deal in the Software without restriction, including
62
- without limitation the rights to use, copy, modify, merge, publish,
63
- distribute, sublicense, and/or sell copies of the Software, and to
64
- permit persons to whom the Software is furnished to do so, subject to
65
- the following conditions:
66
-
67
- The above copyright notice and this permission notice shall be
68
- included in all copies or substantial portions of the Software.
69
-
70
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
71
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
72
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
73
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
74
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
75
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
76
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch]))
5
- include Hitch
6
-
7
- manage_hitchrc
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
-
5
- require 'yaml'
6
- yaml = YAML.load(File.read(File.expand_path('~/.hitchrc')))
7
- pairs = yaml['current_pair']
8
- print pairs.join(':') if pairs
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch]))
5
- include Hitch
6
-
7
- unhitch
@@ -1,71 +0,0 @@
1
- require 'optparse'
2
- require 'optparse/time'
3
- require 'ostruct'
4
-
5
- module Hitch
6
-
7
- class Options
8
-
9
- def self.parse(args)
10
- options = OpenStruct.new
11
- options.action = "hitch"
12
-
13
- opts = OptionParser.new do |opts|
14
- opts.banner = "Usage: hitch [options] first_pair_username second_pair_username"
15
- opts.separator ""
16
- opts.separator "Hitch defaults to the current project's .git/config"
17
- opts.separator ""
18
- opts.separator "General options:"
19
-
20
- opts.on('-p', '--preserve_gitconfig', 'Preserves your ~/.gitconfig and .git/config files. Uses ~/.hitch_export_authors instead') do
21
- options.export_hitch_authors = true
22
- end
23
-
24
- opts.on("-g", "--global", "Modifies your global ~/.gitconfig") do
25
- options.current_gitconfig = File.expand_path("~/.gitconfig")
26
- end
27
-
28
- opts.on("-m", "--manage-hitchrc", "Creates or manages your personal information into ~/.hitchrc") do
29
- if options.action.empty? || options.action == "hitch"
30
- options.action = "manage_hitchrc"
31
- else
32
- abort "You can only perform one action at a time. hitch -h for more info."
33
- end
34
- end
35
-
36
- opts.on("-u", "--unhitch", "Clear pair information") do
37
- if options.action.empty? || options.action == "hitch"
38
- options.action = "unhitch"
39
- else
40
- abort "You can only perform one action at a time. hitch -h for more info."
41
- end
42
- end
43
-
44
- opts.separator ""
45
- opts.separator "Common options:"
46
-
47
- opts.on_tail("-h", "--help", "Show this message") do
48
- puts opts
49
- exit
50
- end
51
-
52
- opts.on_tail("-v", "--version", "Show version") do
53
- abort "hitch v#{Hitch.version}"
54
- end
55
- end
56
-
57
- opts.parse!(args)
58
-
59
- if options.current_gitconfig.nil?
60
- options.current_gitconfig = File.expand_path(File.join(Dir.pwd, ".git", "config"))
61
- end
62
-
63
- unless File.exists?(options.current_gitconfig)
64
- abort "Config File: #{options.current_gitconfig} does not exist. hitch -h for more info."
65
- end
66
-
67
- options
68
- end
69
-
70
- end
71
- end