hitch 0.5.2

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/README.rdoc ADDED
@@ -0,0 +1,76 @@
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.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ begin
6
+ require 'bones'
7
+ Bones.setup
8
+ rescue LoadError
9
+ begin
10
+ load 'tasks/setup.rb'
11
+ rescue LoadError
12
+ raise RuntimeError, '### please install the "bones" gem ###'
13
+ end
14
+ end
15
+
16
+ ensure_in_path 'lib'
17
+ require 'hitch'
18
+
19
+ task :default => 'spec:run'
20
+
21
+ PROJ.name = 'hitch'
22
+ PROJ.authors = 'Rogelio J. Samour (therubymug)'
23
+ PROJ.email = 'rogelio@therubymug.com'
24
+ PROJ.url = 'http://github.com/therubymug/hitch'
25
+ PROJ.version = Hitch::VERSION
26
+ PROJ.rubyforge.name = 'hitch'
27
+ PROJ.dependencies = ['highline']
28
+ PROJ.readme_file = 'README.rdoc'
29
+
30
+ PROJ.spec.opts << '--color'
31
+
32
+ require 'fileutils'
33
+
34
+ spec = Gem::Specification.new do |s|
35
+ s.name = %q{hitch}
36
+ s.version = Hitch::VERSION
37
+ s.summary = %q{Hitch allows developers to be properly credited when Pair Programming and using Git.}
38
+ s.email = %q{ro@hashrocket.com}
39
+ s.homepage = %q{http://github.com/therubymug/hitch}
40
+ s.has_rdoc = false
41
+ s.authors = ["Rogelio Samour", "Les Hill"]
42
+ s.files = %w( README.rdoc Rakefile ) + Dir["{bin,lib}/**/*"].sort
43
+ s.extra_rdoc_files = ["README.rdoc"]
44
+ s.executables = ["hitch", "unhitch", "hitchrc"]
45
+ s.add_dependency('highline', '>= 1.5.0')
46
+ end
47
+
48
+ desc "Generate the static gemspec required for github"
49
+ task :gemspec do
50
+ open("hitch.gemspec", "w").write(spec.to_ruby)
51
+ end
52
+
data/bin/hitch ADDED
@@ -0,0 +1,9 @@
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
+ if personal_info
8
+ hitch
9
+ end
data/bin/hitchrc ADDED
@@ -0,0 +1,7 @@
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
data/bin/hitchstatus ADDED
@@ -0,0 +1,8 @@
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
data/bin/unhitch ADDED
@@ -0,0 +1,7 @@
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
data/lib/hitch.rb ADDED
@@ -0,0 +1,283 @@
1
+ require 'highline'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib hitch options]))
3
+
4
+ module Hitch
5
+
6
+ # :stopdoc:
7
+ VERSION = '0.5.2'
8
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
9
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
10
+ # :startdoc:
11
+
12
+ # Returns the version string for the library.
13
+ #
14
+ def self.version
15
+ VERSION
16
+ end
17
+
18
+ # Returns the library path for the module. If any arguments are given,
19
+ # they will be joined to the end of the libray path using
20
+ # <tt>File.join</tt>.
21
+ #
22
+ def self.libpath( *args )
23
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
24
+ end
25
+
26
+ # Returns the lpath for the module. If any arguments are given,
27
+ # they will be joined to the end of the path using
28
+ # <tt>File.join</tt>.
29
+ #
30
+ def self.path( *args )
31
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
32
+ end
33
+
34
+ # Utility method used to require all files ending in .rb that lie in the
35
+ # directory below this file that has the same name as the filename passed
36
+ # in. Optionally, a specific _directory_ name can be passed in such that
37
+ # the _filename_ does not have to be equivalent to the directory.
38
+ #
39
+ def self.require_all_libs_relative_to( fname, dir = nil )
40
+ dir ||= ::File.basename(fname, '.*')
41
+ search_me = ::File.expand_path(
42
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
43
+
44
+ Dir.glob(search_me).sort.each {|rb| require rb}
45
+ end
46
+
47
+ HighLine.track_eof = false
48
+
49
+ def write_hitchrc
50
+ personal_info['current_pair'] = current_pair
51
+ File.open(hitchrc, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
52
+ YAML.dump(personal_info, out)
53
+ end
54
+ end
55
+
56
+ def hitchrc
57
+ @hitchrc ||= File.expand_path("~/.hitchrc")
58
+ end
59
+
60
+ def personal_info
61
+ if File.exists?(hitchrc)
62
+ @personal_info ||= YAML::load_file(hitchrc)
63
+ else
64
+ @personal_info ||= {}
65
+ end
66
+ end
67
+
68
+ def hitch_pairs
69
+ @hitch_pairs ||= File.expand_path("~/.hitch_pairs")
70
+ end
71
+
72
+ def pairs
73
+ if File.exists?(hitch_pairs)
74
+ @pairs ||= YAML::load_file(hitch_pairs)
75
+ else
76
+ @pairs ||= {}
77
+ end
78
+ end
79
+
80
+ def write_hitch_pairs
81
+ File.open(hitch_pairs, File::CREAT|File::TRUNC|File::RDWR, 0644) do |out|
82
+ YAML.dump(pairs, out)
83
+ end
84
+ end
85
+
86
+ def ui
87
+ @ui ||= HighLine.new
88
+ end
89
+
90
+ def exporting_hitch_authors
91
+ !!hitch_options.export_hitch_authors
92
+ end
93
+
94
+ def write_hitch_authors
95
+ File.open(File.expand_path('~/.hitch_export_authors'), "w") do |f|
96
+ f.puts "# "
97
+ f.puts "export GIT_AUTHOR_NAME='#{hitch_name}'"
98
+ f.puts "export GIT_AUTHOR_EMAIL='#{hitch_email}'"
99
+ end
100
+ end
101
+
102
+ def write_gitconfig
103
+ clean_gitconfig
104
+ File.open(hitch_options.current_gitconfig, "a+") do |f|
105
+ f.puts "# start - lines added by hitch #"
106
+ f.puts "[user]"
107
+ f.puts "\tname = '#{hitch_name}'"
108
+ f.puts "\temail = #{hitch_email}"
109
+ f.puts "# end - lines added by hitch #"
110
+ end
111
+ end
112
+
113
+ def add_pair(git_name)
114
+ current_pair << git_name
115
+ current_pair.sort!
116
+ current_pair.uniq!
117
+ end
118
+
119
+ def current_pair
120
+ @current_pair ||= (personal_info['current_pair'] or [])
121
+ end
122
+
123
+ def hitch_name
124
+ my_pairs_and_i.map {|github, name| name}.join(' and ')
125
+ end
126
+
127
+ def hitch_email
128
+ "#{group_prefix}+#{my_pairs_and_i.map{|github, name| github}.join('+')}@#{group_domain}"
129
+ end
130
+
131
+ def my_pairs_and_i
132
+ and_i = current_pair.map {|github| [github, pairs[github]]}
133
+ and_i.sort_by {|github, name| github }
134
+ end
135
+
136
+ def group_prefix
137
+ personal_info['group_email'].split('@').first
138
+ end
139
+
140
+ def group_domain
141
+ personal_info['group_email'].split('@').last
142
+ end
143
+
144
+ def clean_hitch_authors
145
+ authors_file = File.expand_path '~/.hitch_export_authors'
146
+ File.open(authors_file, 'w') do |f|
147
+ f.puts "unset GIT_AUTHOR_NAME"
148
+ f.puts "unset GIT_AUTHOR_EMAIL"
149
+ end
150
+ end
151
+
152
+ def clean_gitconfig(opts={:print => false})
153
+ config_file = hitch_options.current_gitconfig
154
+ ui.say " Clearing hitch info in: #{config_file}" if opts[:print]
155
+ body = File.read(config_file)
156
+ body.gsub!(/# start - lines added by hitch #\n.*?\n# end - lines added by hitch #\n/m, '')
157
+ File.open(config_file + ".tmp", 'w') {|f| f.write(body)}
158
+ File.rename(config_file + ".tmp", config_file)
159
+ end
160
+
161
+ def prep_hitch_authors
162
+ if pairing?
163
+ write_hitch_authors
164
+ else
165
+ clean_hitch_authors
166
+ end
167
+ end
168
+
169
+ def prep_gitconfig
170
+ if pairing?
171
+ write_gitconfig
172
+ else
173
+ clean_gitconfig
174
+ end
175
+ end
176
+
177
+ def unhitch
178
+ if personal_info
179
+ clear_pair_info
180
+ write_hitchrc
181
+ if exporting_hitch_authors
182
+ clean_hitch_authors
183
+ else
184
+ clean_gitconfig(:print => true)
185
+ end
186
+ print_current_status
187
+ end
188
+ end
189
+
190
+ def print_current_status
191
+ if pairing?
192
+ ui.say " Currently pairing with #{current_pair.join(' ')}."
193
+ else
194
+ ui.say " Currently coding solo."
195
+ end
196
+ end
197
+
198
+ def print_version
199
+ ui.say "hitch v#{Hitch.version}"
200
+ end
201
+
202
+ def clear_pair_info
203
+ personal_info['current_pair'] = []
204
+ end
205
+
206
+ def pairing?
207
+ return false if personal_info.empty?
208
+ return false if personal_info['current_pair'].nil? || personal_info['current_pair'].length.zero?
209
+ return false if personal_info['current_pair'].length < 2
210
+ true
211
+ end
212
+
213
+ def existing_pair?(pair)
214
+ pairs.any? {|github, name| github == pair}
215
+ end
216
+
217
+ def hitch_options
218
+ @hitch_options ||= Options.parse(ARGV)
219
+ end
220
+
221
+ def hitch
222
+ case hitch_options.action
223
+ when "manage_hitchrc"
224
+ manage_hitchrc
225
+ when "unhitch"
226
+ unhitch
227
+ when "hitch"
228
+ if ARGV.any? && ARGV.size >= 2
229
+ potential_pairs = ARGV
230
+ save_pairs = false
231
+ clear_pair_info
232
+
233
+ potential_pairs.each do |pair|
234
+ unless existing_pair?(pair)
235
+ ui.say("I don't know who #{pair} is.")
236
+ if ui.agree("Do you want to add #{pair} to ~/.hitch_pairs? ", true)
237
+ pairs[pair] = ui.ask("What is #{pair}'s full name?") do |q|
238
+ q.validate = /\A[-(\w|.,)+\s?]+\Z/
239
+ end
240
+ add_pair(pair)
241
+ save_pairs ||= true
242
+ else
243
+ ui.say("Ignoring #{pair}.")
244
+ end
245
+ else
246
+ add_pair(pair)
247
+ end
248
+ end
249
+ write_hitchrc
250
+ write_hitch_pairs if save_pairs
251
+ if exporting_hitch_authors
252
+ prep_hitch_authors
253
+ else
254
+ prep_gitconfig
255
+ end
256
+ else
257
+ ui.say " Silly Rabbit! A pair is comprised of two." unless ARGV.size.zero?
258
+ end
259
+ print_current_status
260
+ end
261
+ end
262
+
263
+ def manage_hitchrc
264
+ begin
265
+ unless File.exists?(hitchrc) and !ui.agree("Do you want to overwrite your #{ENV['HOME']}/.hitchrc file?", true)
266
+ ui.say("Let's setup your #{ENV['HOME']}/.hitchrc file")
267
+
268
+ 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|
269
+ q.case = :down
270
+ q.validate = /\A[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+\z/ # Simple email validation.
271
+ end
272
+
273
+ write_hitchrc
274
+ end
275
+ rescue EOFError # HighLine throws this if @input.eof?
276
+ break
277
+ end
278
+
279
+ print_current_status
280
+ end
281
+ end # module Hitch
282
+
283
+ Hitch.require_all_libs_relative_to(__FILE__)
@@ -0,0 +1,71 @@
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
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hitch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - Rogelio Samour
8
+ - Les Hill
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-11-19 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: highline
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.5.0
25
+ version:
26
+ description:
27
+ email: ro@hashrocket.com
28
+ executables:
29
+ - hitch
30
+ - unhitch
31
+ - hitchrc
32
+ - hitchstatus
33
+ extensions: []
34
+
35
+ extra_rdoc_files:
36
+ - README.rdoc
37
+ files:
38
+ - README.rdoc
39
+ - Rakefile
40
+ - bin/hitch
41
+ - bin/hitchrc
42
+ - bin/unhitch
43
+ - lib/hitch.rb
44
+ - lib/hitch/options.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/therubymug/hitch
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Hitch allows developers to be properly credited when Pair Programming and using Git.
73
+ test_files: []
74
+