hitch 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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
+