git-duet 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/.simplecov +1 -0
- data/.travis.yml +4 -6
- data/Gemfile +1 -0
- data/LICENSE +1 -1
- data/README.md +1 -0
- data/Rakefile +7 -1
- data/bin/git-duet +2 -1
- data/bin/git-duet-commit +2 -1
- data/bin/git-duet-install-hook +2 -1
- data/bin/git-duet-pre-commit +2 -1
- data/bin/git-solo +2 -1
- data/git-duet.gemspec +5 -7
- data/lib/git-duet.rb +1 -0
- data/lib/git/duet.rb +4 -4
- data/lib/git/duet/author_mapper.rb +14 -10
- data/lib/git/duet/cli.rb +22 -26
- data/lib/git/duet/command_methods.rb +44 -12
- data/lib/git/duet/commit_command.rb +20 -15
- data/lib/git/duet/config.rb +11 -0
- data/lib/git/duet/duet_command.rb +11 -5
- data/lib/git/duet/install_hook_command.rb +14 -10
- data/lib/git/duet/pre_commit_command.rb +11 -8
- data/lib/git/duet/script_die_error.rb +2 -0
- data/lib/git/duet/solo_command.rb +21 -7
- data/lib/git/duet/version.rb +3 -1
- data/spec/integration/end_to_end_spec.rb +74 -54
- data/spec/lib/git/duet/author_mapper_spec.rb +45 -42
- data/spec/lib/git/duet/cli_spec.rb +20 -19
- data/spec/lib/git/duet/command_methods_spec.rb +21 -11
- data/spec/lib/git/duet/duet_command_spec.rb +75 -51
- data/spec/lib/git/duet/pre_commit_command_spec.rb +19 -14
- data/spec/lib/git/duet/solo_command_spec.rb +118 -73
- data/spec/spec_helper.rb +3 -16
- data/spec/support/author_mapper_helper.rb +22 -18
- metadata +25 -41
- data/.rbenv-version +0 -1
- data/bin/git-duet-pre-commit-tk +0 -3
- data/lib/git/duet/key_error.rb +0 -3
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 46323bd5392d627ae8bed46e4cd89f2bf8803885
|
4
|
+
data.tar.gz: b78bc212d1b95a47e28c8337b19cd5b3ebb38072
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28d686c6d459b9104b5c9279e98cc49b6119461bf6b19cf88b41c71b053465fc8c2bb8e66cc856571fc909206a6e4ea7946d2b0f090ae29c38ce50761635d5ba
|
7
|
+
data.tar.gz: ec5038f060832c4f7ed5ad35243ba9ef43498a07eff2722ac2d65e2846c10460d2c5fe879e1750dc1e913d624ebfdb3ce43732345534a3f86b5ce22b1003f03c
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p247
|
data/.simplecov
CHANGED
data/.travis.yml
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
---
|
1
2
|
language: ruby
|
2
3
|
env:
|
3
4
|
global:
|
@@ -6,12 +7,9 @@ matrix:
|
|
6
7
|
allow_failures:
|
7
8
|
- rvm: jruby-19mode
|
8
9
|
rvm:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
- ree
|
13
|
-
script:
|
14
|
-
- bundle exec rake spec --trace
|
10
|
+
- 1.9.3
|
11
|
+
- 2.0.0
|
12
|
+
- jruby-19mode
|
15
13
|
notifications:
|
16
14
|
email:
|
17
15
|
recipients:
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
# vim:fileencoding=utf-8
|
2
3
|
require "bundler/gem_tasks"
|
3
4
|
|
4
5
|
require 'rspec/core/rake_task'
|
5
6
|
|
7
|
+
desc 'Run rubocop'
|
8
|
+
task :rubocop do
|
9
|
+
sh('rubocop --format simple') { |r, _| r || abort }
|
10
|
+
end
|
11
|
+
|
6
12
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
13
|
t.rspec_opts = '--format documentation'
|
8
14
|
end
|
9
15
|
|
10
|
-
task :default => :spec
|
16
|
+
task :default => [:rubocop, :spec]
|
data/bin/git-duet
CHANGED
data/bin/git-duet-commit
CHANGED
data/bin/git-duet-install-hook
CHANGED
data/bin/git-duet-pre-commit
CHANGED
data/bin/git-solo
CHANGED
data/git-duet.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.summary = "Pair harmoniously! Decide who's driving. " <<
|
19
19
|
"Commit along the way. Don't make a mess of " <<
|
20
20
|
"the repository history."
|
21
|
-
gem.homepage = ''
|
21
|
+
gem.homepage = 'https://github.com/modcloth/git-duet'
|
22
22
|
gem.license = 'MIT'
|
23
23
|
|
24
24
|
gem.files = `git ls-files`.split($\)
|
@@ -27,14 +27,12 @@ Gem::Specification.new do |gem|
|
|
27
27
|
gem.name = 'git-duet'
|
28
28
|
gem.require_paths = %w(lib)
|
29
29
|
gem.version = Git::Duet::VERSION
|
30
|
-
gem.required_ruby_version = '>= 1.
|
30
|
+
gem.required_ruby_version = '>= 1.9.3'
|
31
31
|
|
32
|
-
gem.add_development_dependency 'nyan-cat-formatter'
|
33
32
|
gem.add_development_dependency 'rake'
|
34
33
|
gem.add_development_dependency 'rspec'
|
34
|
+
gem.add_development_dependency 'rubocop'
|
35
35
|
|
36
|
-
unless RUBY_PLATFORM == 'java'
|
37
|
-
|
38
|
-
gem.add_development_dependency 'simplecov'
|
39
|
-
end
|
36
|
+
gem.add_development_dependency 'pry' unless RUBY_PLATFORM == 'java'
|
37
|
+
gem.add_development_dependency 'simplecov' unless RUBY_PLATFORM == 'java'
|
40
38
|
end
|
data/lib/git-duet.rb
CHANGED
data/lib/git/duet.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
1
2
|
module Git
|
2
3
|
module Duet
|
4
|
+
autoload :VERSION, 'git/duet/version'
|
5
|
+
autoload :Cli, 'git/duet/cli'
|
6
|
+
autoload :Config, 'git/duet/config'
|
3
7
|
end
|
4
8
|
end
|
5
|
-
|
6
|
-
require 'git/duet/version'
|
7
|
-
require 'git/duet/cli'
|
8
|
-
require 'git/duet/key_error'
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
1
2
|
require 'yaml'
|
2
3
|
require 'erb'
|
3
4
|
require 'git/duet'
|
@@ -22,27 +23,30 @@ class Git::Duet::AuthorMapper
|
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
26
|
+
|
25
27
|
def author_info(initials)
|
26
28
|
author, username = author_map.fetch(initials).split(/;/).map(&:strip)
|
27
29
|
{
|
28
|
-
:
|
29
|
-
:
|
30
|
+
name: author,
|
31
|
+
email: lookup_author_email(initials, author, username)
|
30
32
|
}
|
31
33
|
end
|
32
34
|
|
33
35
|
def lookup_author_email(initials, author, username)
|
34
|
-
|
35
|
-
|
36
|
-
return author_email if !author_email.empty?
|
37
|
-
end
|
38
|
-
|
36
|
+
author_email = email_from_lookup(initials, author, username)
|
37
|
+
return author_email unless author_email.empty?
|
39
38
|
return email_addresses[initials] if email_addresses[initials]
|
40
39
|
return email_from_template(initials, author, username) if email_template
|
41
40
|
return "#{username}@#{email_domain}" if username
|
42
41
|
|
43
42
|
author_name_parts = author.split
|
44
|
-
|
45
|
-
|
43
|
+
"#{author_name_parts.first[0, 1].downcase}." <<
|
44
|
+
"#{author_name_parts.last.downcase}@#{email_domain}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def email_from_lookup(initials, author, username)
|
48
|
+
return '' unless @email_lookup
|
49
|
+
`#{@email_lookup} '#{initials}' '#{author}' '#{username}'`.strip
|
46
50
|
end
|
47
51
|
|
48
52
|
def email_from_template(initials, author, username)
|
@@ -69,7 +73,7 @@ class Git::Duet::AuthorMapper
|
|
69
73
|
end
|
70
74
|
|
71
75
|
def cfg
|
72
|
-
@cfg ||= YAML.load(IO.read(
|
76
|
+
@cfg ||= YAML.load(IO.read(authors_file))
|
73
77
|
rescue StandardError => e
|
74
78
|
$stderr.puts("git-duet: Missing or corrupt authors file: #{e.message}")
|
75
79
|
raise Git::Duet::ScriptDieError.new(3)
|
data/lib/git/duet/cli.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
1
2
|
require 'optparse'
|
2
3
|
require 'git/duet'
|
3
4
|
require 'git/duet/script_die_error'
|
@@ -5,30 +6,27 @@ require 'git/duet/script_die_error'
|
|
5
6
|
class Git::Duet::Cli
|
6
7
|
class << self
|
7
8
|
def run(prog, argv)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
return 0
|
15
|
-
when /pre-commit$/
|
16
|
-
pre_commit(parse_generic_options(argv.clone))
|
17
|
-
return 0
|
18
|
-
when /install-hook$/
|
19
|
-
install_hook(parse_generic_options(argv.clone))
|
20
|
-
return 0
|
21
|
-
when /commit$/
|
22
|
-
commit(parse_commit_options(argv.clone))
|
23
|
-
return 0
|
24
|
-
else
|
25
|
-
raise ScriptError.new('How did you get here???')
|
26
|
-
end
|
9
|
+
method_name = File.basename(prog)
|
10
|
+
.sub(/^git-duet-/, '').sub(/^git-/, '').tr('-', '_')
|
11
|
+
send(method_name, parse_options(method_name, argv.clone))
|
12
|
+
0
|
13
|
+
rescue NoMethodError
|
14
|
+
raise ScriptError.new('How did you get here???')
|
27
15
|
rescue Git::Duet::ScriptDieError => e
|
28
|
-
|
16
|
+
e.exit_code
|
29
17
|
end
|
30
18
|
|
31
19
|
private
|
20
|
+
|
21
|
+
def parse_options(method_name, argv)
|
22
|
+
case method_name
|
23
|
+
when 'pre_commit', 'install_hook'
|
24
|
+
parse_generic_options(argv)
|
25
|
+
else
|
26
|
+
send("parse_#{method_name}_options", argv)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
32
30
|
def with_common_opts(argv, banner)
|
33
31
|
options = {}
|
34
32
|
leftover_argv = OptionParser.new do |opts|
|
@@ -36,17 +34,15 @@ class Git::Duet::Cli
|
|
36
34
|
opts.on('-q', 'Silence output') do |q|
|
37
35
|
options[:quiet] = true
|
38
36
|
end
|
39
|
-
if block_given?
|
40
|
-
yield opts, options
|
41
|
-
end
|
37
|
+
yield opts, options if block_given?
|
42
38
|
end.parse!(argv)
|
43
|
-
|
39
|
+
[leftover_argv, options]
|
44
40
|
end
|
45
41
|
|
46
42
|
def parse_solo_options(argv)
|
47
43
|
leftover_argv, options = with_common_opts(
|
48
44
|
argv, 'Usage: __PROG__ [options] <soloist-initials>'
|
49
|
-
) do |opts,options_hash|
|
45
|
+
) do |opts, options_hash|
|
50
46
|
opts.on('-g', '--global', 'Change global git config') do |g|
|
51
47
|
options_hash[:global] = true
|
52
48
|
end
|
@@ -58,7 +54,7 @@ class Git::Duet::Cli
|
|
58
54
|
def parse_duet_options(argv)
|
59
55
|
leftover_argv, options = with_common_opts(
|
60
56
|
argv, 'Usage: __PROG__ [options] <alpha-initials> <omega-initials>'
|
61
|
-
) do |opts,options_hash|
|
57
|
+
) do |opts, options_hash|
|
62
58
|
opts.on('-g', '--global', 'Change global git config') do |g|
|
63
59
|
options_hash[:global] = true
|
64
60
|
end
|
@@ -1,40 +1,68 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
2
|
+
require 'English'
|
1
3
|
require 'git/duet'
|
2
4
|
require 'git/duet/script_die_error'
|
3
5
|
|
4
6
|
module Git::Duet::CommandMethods
|
7
|
+
|
5
8
|
private
|
9
|
+
|
6
10
|
def report_env_vars
|
7
|
-
var_map.each do |key,value|
|
11
|
+
var_map.each do |key, value|
|
8
12
|
info("#{key}='#{value}'")
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
12
16
|
def write_env_vars
|
13
17
|
in_repo_root do
|
14
|
-
var_map.each do |key,value|
|
15
|
-
exec_check(
|
18
|
+
var_map.each do |key, value|
|
19
|
+
exec_check(
|
20
|
+
"#{git_config} #{Git::Duet::Config.namespace}." <<
|
21
|
+
"#{key.downcase.gsub(/_/, '-')} '#{value}'"
|
22
|
+
)
|
16
23
|
end
|
17
|
-
exec_check("
|
24
|
+
exec_check("#{git_config} #{Git::Duet::Config
|
25
|
+
.namespace}.mtime #{Time.now.to_i}")
|
18
26
|
end
|
19
27
|
end
|
20
28
|
|
29
|
+
def git_config
|
30
|
+
"git config#{@global ? ' --global' : ''}"
|
31
|
+
end
|
32
|
+
|
21
33
|
def author_env_vars_set?
|
22
|
-
|
23
|
-
|
34
|
+
%x(#{get_author_name} && #{get_author_email})
|
35
|
+
$CHILD_STATUS == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_author_name
|
39
|
+
"git config --get #{Git::Duet::Config.namespace}.git-author-name"
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_author_email
|
43
|
+
"git config --get #{Git::Duet::Config.namespace}.git-author-email"
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_current_config
|
47
|
+
"git config --get-regexp #{Git::Duet::Config.namespace}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def show_current_config
|
51
|
+
info(exec_check(get_current_config))
|
24
52
|
end
|
25
53
|
|
26
54
|
def dump_env_vars
|
27
|
-
extract_env_vars_from_git_config.each do |k,v|
|
55
|
+
extract_env_vars_from_git_config.each do |k, v|
|
28
56
|
puts "#{k}='#{v}'"
|
29
57
|
end
|
30
58
|
end
|
31
59
|
|
32
60
|
def extract_env_vars_from_git_config
|
33
61
|
dest = {}
|
34
|
-
env_vars.each do |env_var,config_key|
|
62
|
+
env_vars.each do |env_var, config_key|
|
35
63
|
begin
|
36
|
-
value =
|
37
|
-
dest[env_var] = value
|
64
|
+
value = check_env_var_config_key(config_key)
|
65
|
+
dest[env_var] = value unless value.empty?
|
38
66
|
rescue StandardError => e
|
39
67
|
error("#{e.message}")
|
40
68
|
end
|
@@ -42,6 +70,10 @@ module Git::Duet::CommandMethods
|
|
42
70
|
dest
|
43
71
|
end
|
44
72
|
|
73
|
+
def check_env_var_config_key(config_key)
|
74
|
+
exec_check("git config #{Git::Duet::Config.namespace}.#{config_key}").chomp
|
75
|
+
end
|
76
|
+
|
45
77
|
def exec_git_commit
|
46
78
|
if author_env_vars_set?
|
47
79
|
exec 'git commit ' << signoff_arg << quoted_passthrough_args
|
@@ -58,8 +90,8 @@ module Git::Duet::CommandMethods
|
|
58
90
|
|
59
91
|
def exec_check(command, okay_statuses = [0].freeze)
|
60
92
|
output = `#{command}`
|
61
|
-
|
62
|
-
error("Command #{command.inspect} exited with #{
|
93
|
+
unless okay_statuses.include?($CHILD_STATUS.exitstatus)
|
94
|
+
error("Command #{command.inspect} exited with #{$CHILD_STATUS.to_i}")
|
63
95
|
raise Git::Duet::ScriptDieError.new(1)
|
64
96
|
end
|
65
97
|
output
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
1
2
|
require 'git/duet'
|
2
3
|
require 'git/duet/command_methods'
|
3
4
|
|
@@ -17,8 +18,9 @@ class Git::Duet::CommitCommand
|
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
21
|
+
|
20
22
|
def add_env_vars_to_env
|
21
|
-
extract_env_vars_from_git_config.each do |k,v|
|
23
|
+
extract_env_vars_from_git_config.each do |k, v|
|
22
24
|
ENV[k] = v
|
23
25
|
end
|
24
26
|
end
|
@@ -43,26 +45,29 @@ class Git::Duet::CommitCommand
|
|
43
45
|
soloing? ? '' : '--signoff '
|
44
46
|
end
|
45
47
|
|
48
|
+
SOLO_ENV_VARS = %w(
|
49
|
+
GIT_AUTHOR_NAME
|
50
|
+
GIT_AUTHOR_EMAIL
|
51
|
+
)
|
52
|
+
|
53
|
+
DUET_ENV_VARS = %w(
|
54
|
+
GIT_AUTHOR_NAME
|
55
|
+
GIT_AUTHOR_EMAIL
|
56
|
+
GIT_COMMITTER_NAME
|
57
|
+
GIT_COMMITTER_EMAIL
|
58
|
+
)
|
59
|
+
|
46
60
|
def env_var_names
|
47
|
-
if soloing?
|
48
|
-
|
49
|
-
GIT_AUTHOR_NAME
|
50
|
-
GIT_AUTHOR_EMAIL
|
51
|
-
)
|
52
|
-
else
|
53
|
-
%w(
|
54
|
-
GIT_AUTHOR_NAME
|
55
|
-
GIT_AUTHOR_EMAIL
|
56
|
-
GIT_COMMITTER_NAME
|
57
|
-
GIT_COMMITTER_EMAIL
|
58
|
-
)
|
59
|
-
end
|
61
|
+
return SOLO_ENV_VARS if soloing?
|
62
|
+
DUET_ENV_VARS
|
60
63
|
end
|
61
64
|
|
62
65
|
def soloing?
|
63
66
|
@soloing ||= begin
|
64
67
|
with_output_quieted do
|
65
|
-
exec_check(
|
68
|
+
exec_check(
|
69
|
+
"git config #{Git::Duet::Config.namespace}.git-committer-name"
|
70
|
+
).chomp
|
66
71
|
end
|
67
72
|
false
|
68
73
|
rescue StandardError
|