git-duet 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b0e935ea43b312f7b8f22a51c37ff101c8bcfa92
4
+ data.tar.gz: 5a01b500d7ed09135fd5f5acbd7500084ac72fe9
5
+ SHA512:
6
+ metadata.gz: 92aa13d5ad13ea7540e47ba48aec5b9ae2e70aed2457dca8a0746d20fe4c1df2ee8cb3468a099e9026f1a858af9d5459faac31dffa0d3135cc4d9d802db4211f
7
+ data.tar.gz: 6d2e39230cf987832d19f259140cacb4b8b5663e4b0db208a0cac4a16001906190207541fa5313ef3615955836224d9351663fe74acadada7b62af85a17102c1
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  Gemfile.lock
4
4
  /coverage/
5
5
  /tags
6
+ .idea/
@@ -1,3 +1,9 @@
1
1
  ---
2
2
  Documentation:
3
3
  Enabled: false
4
+
5
+ FileName:
6
+ Enabled: false
7
+
8
+ DoubleNegation:
9
+ Enabled: false
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.1.1
data/Gemfile CHANGED
@@ -3,4 +3,6 @@ source 'https://rubygems.org'
3
3
 
4
4
  gemspec
5
5
 
6
- gem 'codeclimate-test-reporter', group: :test, require: nil
6
+ unless RUBY_PLATFORM == 'java'
7
+ gem 'codeclimate-test-reporter', group: :test, require: nil
8
+ end
data/README.md CHANGED
@@ -64,11 +64,12 @@ Set the author and committer via `git duet`:
64
64
  git duet jd fb
65
65
  ~~~~~
66
66
 
67
- When you're ready to commit, use `git duet-commit` (or add an alias like
68
- a normal person. Something like `dci = duet-commit` should work.)
67
+ When you're ready to commit, use `git duet-commit` or `git dci`
69
68
 
70
69
  ~~~~~ bash
71
70
  git duet-commit -v [any other git options]
71
+ # or...
72
+ git dci -v [any other git options]
72
73
  ~~~~~
73
74
 
74
75
  When you're done pairing, set the author back to yourself with `git solo`:
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:fileencoding=utf-8
3
+ require 'git-duet'
4
+ exit Git::Duet::Cli.run($PROGRAM_NAME, ARGV)
@@ -33,6 +33,7 @@ Gem::Specification.new do |gem|
33
33
  gem.add_development_dependency 'rspec'
34
34
  gem.add_development_dependency 'rubocop'
35
35
 
36
+ gem.add_development_dependency 'posix-spawn' unless RUBY_PLATFORM == 'java'
36
37
  gem.add_development_dependency 'pry' unless RUBY_PLATFORM == 'java'
37
38
  gem.add_development_dependency 'simplecov' unless RUBY_PLATFORM == 'java'
38
39
  end
@@ -3,79 +3,85 @@ require 'yaml'
3
3
  require 'erb'
4
4
  require 'git/duet'
5
5
 
6
- class Git::Duet::AuthorMapper
7
- attr_accessor :authors_file
6
+ module Git
7
+ module Duet
8
+ class AuthorMapper
9
+ attr_accessor :authors_file
8
10
 
9
- def initialize(authors_file = nil, email_lookup = nil)
10
- @authors_file = authors_file ||
11
- ENV['GIT_DUET_AUTHORS_FILE'] ||
12
- File.join(ENV['HOME'], '.git-authors')
13
- @email_lookup = email_lookup ||
14
- ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND']
15
- end
11
+ def initialize(authors_file = nil, email_lookup = nil)
12
+ @authors_file = authors_file ||
13
+ ENV['GIT_DUET_AUTHORS_FILE'] ||
14
+ File.join(ENV['HOME'], '.git-authors')
15
+ @email_lookup = email_lookup ||
16
+ ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND']
17
+ end
16
18
 
17
- def map(*initials_list)
18
- author_map = {}
19
- initials_list.each do |initials|
20
- author_map[initials] = author_info(initials)
21
- end
22
- author_map
23
- end
19
+ def map(*initials_list)
20
+ author_map = {}
21
+ initials_list.each do |initials|
22
+ author_map[initials] = author_info(initials)
23
+ end
24
+ author_map
25
+ end
24
26
 
25
- private
27
+ private
26
28
 
27
- def author_info(initials)
28
- author, username = author_map.fetch(initials).split(/;/).map(&:strip)
29
- {
30
- name: author,
31
- email: lookup_author_email(initials, author, username)
32
- }
33
- end
29
+ def author_info(initials)
30
+ author, username = author_map.fetch(initials).split(/;/).map(&:strip)
31
+ {
32
+ name: author,
33
+ email: lookup_author_email(initials, author, username)
34
+ }
35
+ end
34
36
 
35
- def lookup_author_email(initials, author, username)
36
- author_email = email_from_lookup(initials, author, username)
37
- return author_email unless author_email.empty?
38
- return email_addresses[initials] if email_addresses[initials]
39
- return email_from_template(initials, author, username) if email_template
40
- return "#{username}@#{email_domain}" if username
37
+ def lookup_author_email(initials, author, username)
38
+ author_email = email_from_lookup(initials, author, username)
39
+ return author_email unless author_email.empty?
40
+ return email_addresses[initials] if email_addresses[initials]
41
+ if email_template
42
+ return email_from_template(initials, author, username)
43
+ end
44
+ return "#{username}@#{email_domain}" if username
41
45
 
42
- author_name_parts = author.split
43
- "#{author_name_parts.first[0, 1].downcase}." <<
44
- "#{author_name_parts.last.downcase}@#{email_domain}"
45
- end
46
+ author_name_parts = author.split
47
+ "#{author_name_parts.first[0, 1].downcase}." \
48
+ "#{author_name_parts.last.downcase}@#{email_domain}"
49
+ end
46
50
 
47
- def email_from_lookup(initials, author, username)
48
- return '' unless @email_lookup
49
- `#{@email_lookup} '#{initials}' '#{author}' '#{username}'`.strip
50
- end
51
+ def email_from_lookup(initials, author, username)
52
+ return '' unless @email_lookup
53
+ `#{@email_lookup} '#{initials}' '#{author}' '#{username}'`.strip
54
+ end
51
55
 
52
- def email_from_template(initials, author, username)
53
- return ERB.new(email_template).result(binding)
54
- rescue StandardError => e
55
- $stderr.puts("git-duet: email template rendering error: #{e.message}")
56
- raise Git::Duet::ScriptDieError, 8
57
- end
56
+ def email_from_template(initials, author, username)
57
+ return ERB.new(email_template).result(binding)
58
+ rescue StandardError => e
59
+ $stderr.puts("git-duet: email template rendering error: #{e.message}")
60
+ raise Git::Duet::ScriptDieError, 8
61
+ end
58
62
 
59
- def author_map
60
- @author_map ||= (cfg['authors'] || cfg['pairs'])
61
- end
63
+ def author_map
64
+ @author_map ||= (cfg['authors'] || cfg['pairs'])
65
+ end
62
66
 
63
- def email_addresses
64
- @email_addresses ||= (cfg['email_addresses'] || {})
65
- end
67
+ def email_addresses
68
+ @email_addresses ||= (cfg['email_addresses'] || {})
69
+ end
66
70
 
67
- def email_domain
68
- @email_domain ||= cfg.fetch('email').fetch('domain')
69
- end
71
+ def email_domain
72
+ @email_domain ||= cfg.fetch('email').fetch('domain')
73
+ end
70
74
 
71
- def email_template
72
- @email_template || cfg['email_template']
73
- end
75
+ def email_template
76
+ @email_template || cfg['email_template']
77
+ end
74
78
 
75
- def cfg
76
- @cfg ||= YAML.load(IO.read(authors_file))
77
- rescue StandardError => e
78
- $stderr.puts("git-duet: Missing or corrupt authors file: #{e.message}")
79
- raise Git::Duet::ScriptDieError, 3
79
+ def cfg
80
+ @cfg ||= YAML.load(IO.read(authors_file))
81
+ rescue StandardError => e
82
+ $stderr.puts("git-duet: Missing or corrupt authors file: #{e.message}")
83
+ raise Git::Duet::ScriptDieError, 3
84
+ end
85
+ end
80
86
  end
81
87
  end
@@ -3,115 +3,121 @@ require 'optparse'
3
3
  require 'git/duet'
4
4
  require 'git/duet/script_die_error'
5
5
 
6
- class Git::Duet::Cli
7
- class << self
8
- def run(prog, argv)
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, 'How did you get here???'
15
- rescue Git::Duet::ScriptDieError => e
16
- e.exit_code
17
- end
6
+ module Git
7
+ module Duet
8
+ class Cli
9
+ class << self
10
+ def run(prog, argv)
11
+ method_name = File.basename(prog)
12
+ .sub(/^git-duet-/, '').sub(/^git-/, '').tr('-', '_')
13
+ send(method_name, parse_options(method_name, argv.clone))
14
+ 0
15
+ rescue NoMethodError
16
+ raise ScriptError, 'How did you get here???'
17
+ rescue Git::Duet::ScriptDieError => e
18
+ e.exit_code
19
+ end
18
20
 
19
- private
21
+ private
20
22
 
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
23
+ def parse_options(method_name, argv)
24
+ case method_name
25
+ when 'pre_commit', 'install_hook'
26
+ parse_generic_options(argv)
27
+ else
28
+ send("parse_#{method_name}_options", argv)
29
+ end
30
+ end
29
31
 
30
- def with_common_opts(argv, banner)
31
- options = {}
32
- leftover_argv = OptionParser.new do |opts|
33
- opts.banner = banner.gsub(/__PROG__/, opts.program_name)
34
- opts.on('-q', 'Silence output') do |q|
35
- options[:quiet] = true
32
+ def with_common_opts(argv, banner)
33
+ options = {}
34
+ leftover_argv = OptionParser.new do |opts|
35
+ opts.banner = banner.gsub(/__PROG__/, opts.program_name)
36
+ opts.on('-q', 'Silence output') do |q|
37
+ options[:quiet] = true
38
+ end
39
+ yield opts, options if block_given?
40
+ end.parse!(argv)
41
+ [leftover_argv, options]
36
42
  end
37
- yield opts, options if block_given?
38
- end.parse!(argv)
39
- [leftover_argv, options]
40
- end
41
43
 
42
- def parse_solo_options(argv)
43
- parse_options_with_positional_args(
44
- argv, '<soloist-initials>') do |leftover_argv, options|
45
- options[:soloist] = leftover_argv.first
46
- end
47
- end
44
+ def parse_solo_options(argv)
45
+ parse_options_with_positional_args(
46
+ argv, '<soloist-initials>') do |leftover_argv, options|
47
+ options[:soloist] = leftover_argv.first
48
+ end
49
+ end
48
50
 
49
- def parse_duet_options(argv)
50
- parse_options_with_positional_args(
51
- argv, '<alpha-initials> <omega-initials>') do |leftover_argv, options|
52
- options[:alpha], options[:omega] = leftover_argv[0..1]
53
- end
54
- end
51
+ def parse_duet_options(argv)
52
+ parse_options_with_positional_args(
53
+ argv,
54
+ '<alpha-initials> <omega-initials>'
55
+ ) do |leftover_argv, options|
56
+ options[:alpha], options[:omega] = leftover_argv[0..1]
57
+ end
58
+ end
55
59
 
56
- def parse_options_with_positional_args(argv, usage)
57
- leftover_argv, options = with_common_opts(
58
- argv, 'Usage: __PROG__ [options] ' << usage
59
- ) do |opts, options_hash|
60
- opts.on('-g', '--global', 'Change global git config') do |g|
61
- options_hash[:global] = true
60
+ def parse_options_with_positional_args(argv, usage)
61
+ leftover_argv, options = with_common_opts(
62
+ argv, 'Usage: __PROG__ [options] ' << usage
63
+ ) do |opts, options_hash|
64
+ opts.on('-g', '--global', 'Change global git config') do |g|
65
+ options_hash[:global] = true
66
+ end
67
+ end
68
+ yield leftover_argv, options
69
+ options
62
70
  end
63
- end
64
- yield leftover_argv, options
65
- options
66
- end
67
71
 
68
- def parse_generic_options(argv)
69
- with_common_opts(argv, 'Usage: __PROG__').last
70
- end
72
+ def parse_generic_options(argv)
73
+ with_common_opts(argv, 'Usage: __PROG__').last
74
+ end
71
75
 
72
- def parse_commit_options(argv)
73
- opts_argv = []
74
- opts_argv << '-q' if argv.delete('-q')
75
- options = with_common_opts(opts_argv, 'Usage: __PROG__').last
76
- options[:passthrough_args] = argv
77
- options
78
- end
76
+ def parse_commit_options(argv)
77
+ opts_argv = []
78
+ opts_argv << '-q' if argv.delete('-q')
79
+ options = with_common_opts(opts_argv, 'Usage: __PROG__').last
80
+ options[:passthrough_args] = argv
81
+ options
82
+ end
79
83
 
80
- def solo(options)
81
- require 'git/duet/solo_command'
82
- Git::Duet::SoloCommand.new(
83
- options.fetch(:soloist),
84
- options[:quiet],
85
- options[:global]
86
- ).execute!
87
- end
84
+ def solo(options)
85
+ require 'git/duet/solo_command'
86
+ Git::Duet::SoloCommand.new(
87
+ options.fetch(:soloist),
88
+ options[:quiet],
89
+ options[:global]
90
+ ).execute!
91
+ end
88
92
 
89
- def duet(options)
90
- require 'git/duet/duet_command'
91
- Git::Duet::DuetCommand.new(
92
- options.fetch(:alpha),
93
- options.fetch(:omega),
94
- options[:quiet],
95
- options[:global]
96
- ).execute!
97
- end
93
+ def duet(options)
94
+ require 'git/duet/duet_command'
95
+ Git::Duet::DuetCommand.new(
96
+ options.fetch(:alpha),
97
+ options.fetch(:omega),
98
+ options[:quiet],
99
+ options[:global]
100
+ ).execute!
101
+ end
98
102
 
99
- def pre_commit(options)
100
- require 'git/duet/pre_commit_command'
101
- Git::Duet::PreCommitCommand.new(options[:quiet]).execute!
102
- end
103
+ def pre_commit(options)
104
+ require 'git/duet/pre_commit_command'
105
+ Git::Duet::PreCommitCommand.new(options[:quiet]).execute!
106
+ end
103
107
 
104
- def install_hook(options)
105
- require 'git/duet/install_hook_command'
106
- Git::Duet::InstallHookCommand.new(options[:quiet]).execute!
107
- end
108
+ def install_hook(options)
109
+ require 'git/duet/install_hook_command'
110
+ Git::Duet::InstallHookCommand.new(options[:quiet]).execute!
111
+ end
108
112
 
109
- def commit(options)
110
- require 'git/duet/commit_command'
111
- Git::Duet::CommitCommand.new(
112
- options[:passthrough_args],
113
- options[:quiet]
114
- ).execute!
113
+ def commit(options)
114
+ require 'git/duet/commit_command'
115
+ Git::Duet::CommitCommand.new(
116
+ options[:passthrough_args],
117
+ options[:quiet]
118
+ ).execute!
119
+ end
120
+ end
115
121
  end
116
122
  end
117
123
  end
@@ -3,132 +3,138 @@ require 'English'
3
3
  require 'git/duet'
4
4
  require 'git/duet/script_die_error'
5
5
 
6
- module Git::Duet::CommandMethods
7
- private
8
-
9
- def report_env_vars
10
- var_map.each do |key, value|
11
- info("#{key}='#{value}'")
12
- end
13
- end
14
-
15
- def write_env_vars
16
- in_repo_root do
17
- var_map.each do |key, value|
18
- exec_check(
19
- "#{git_config} #{Git::Duet::Config.namespace}." <<
20
- "#{key.downcase.gsub(/_/, '-')} '#{value}'"
21
- )
6
+ module Git
7
+ module Duet
8
+ module CommandMethods
9
+ private
10
+
11
+ def report_env_vars
12
+ var_map.each do |key, value|
13
+ info("#{key}='#{value}'")
14
+ end
22
15
  end
23
- exec_check("#{git_config} #{Git::Duet::Config
16
+
17
+ def write_env_vars
18
+ in_repo_root do
19
+ var_map.each do |key, value|
20
+ exec_check(
21
+ "#{git_config} #{Git::Duet::Config.namespace}." \
22
+ "#{key.downcase.gsub(/_/, '-')} '#{value}'"
23
+ )
24
+ end
25
+ exec_check("#{git_config} #{Git::Duet::Config
24
26
  .namespace}.mtime #{Time.now.to_i}")
25
- end
26
- end
27
+ end
28
+ end
27
29
 
28
- def git_config
29
- "git config#{@global ? ' --global' : ''}"
30
- end
30
+ def git_config
31
+ "git config#{@global ? ' --global' : ''}"
32
+ end
31
33
 
32
- def author_env_vars_set?
33
- %x(#{author_name_command} && #{author_email_command})
34
- $CHILD_STATUS == 0
35
- end
34
+ def author_env_vars_set?
35
+ %x(#{author_name_command} && #{author_email_command})
36
+ $CHILD_STATUS == 0
37
+ end
36
38
 
37
- def author_name_command
38
- "git config --get #{Git::Duet::Config.namespace}.git-author-name"
39
- end
39
+ def author_name_command
40
+ "git config --get #{Git::Duet::Config.namespace}.git-author-name"
41
+ end
40
42
 
41
- def author_email_command
42
- "git config --get #{Git::Duet::Config.namespace}.git-author-email"
43
- end
43
+ def author_email_command
44
+ "git config --get #{Git::Duet::Config.namespace}.git-author-email"
45
+ end
44
46
 
45
- def current_config_command
46
- "git config --get-regexp #{Git::Duet::Config.namespace}"
47
- end
47
+ def current_config_command
48
+ "git config --get-regexp #{Git::Duet::Config.namespace}"
49
+ end
48
50
 
49
- def show_current_config
50
- info(exec_check(current_config_command))
51
- end
51
+ def show_current_config
52
+ info(exec_check(current_config_command))
53
+ end
52
54
 
53
- def dump_env_vars
54
- extract_env_vars_from_git_config.each do |k, v|
55
- puts "#{k}='#{v}'"
56
- end
57
- end
55
+ def dump_env_vars
56
+ extract_env_vars_from_git_config.each do |k, v|
57
+ puts "#{k}='#{v}'"
58
+ end
59
+ end
58
60
 
59
- def extract_env_vars_from_git_config
60
- dest = {}
61
- env_vars.each do |env_var, config_key|
62
- begin
63
- value = check_env_var_config_key(config_key)
64
- dest[env_var] = value unless value.empty?
65
- rescue StandardError => e
66
- error("#{e.message}")
61
+ def extract_env_vars_from_git_config
62
+ dest = {}
63
+ env_vars.each do |env_var, config_key|
64
+ begin
65
+ value = check_env_var_config_key(config_key)
66
+ dest[env_var] = value unless value.empty?
67
+ rescue StandardError => e
68
+ error("#{e.message}")
69
+ end
70
+ end
71
+ dest
67
72
  end
68
- end
69
- dest
70
- end
71
73
 
72
- def check_env_var_config_key(config_key)
73
- exec_check("git config #{Git::Duet::Config.namespace}.#{config_key}").chomp
74
- end
74
+ def check_env_var_config_key(config_key)
75
+ exec_check(
76
+ "git config #{Git::Duet::Config.namespace}.#{config_key}"
77
+ ).chomp
78
+ end
75
79
 
76
- def exec_git_commit
77
- if author_env_vars_set?
78
- exec 'git commit ' << signoff_arg << quoted_passthrough_args
79
- else
80
- fail Git::Duet::ScriptDieError, 17
81
- end
82
- end
80
+ def exec_git_commit
81
+ if author_env_vars_set?
82
+ exec 'git commit ' << signoff_arg << quoted_passthrough_args
83
+ else
84
+ fail Git::Duet::ScriptDieError, 17
85
+ end
86
+ end
83
87
 
84
- def in_repo_root
85
- Dir.chdir(exec_check('git rev-parse --show-toplevel').chomp) do
86
- yield
87
- end
88
- end
88
+ def in_repo_root
89
+ Dir.chdir(exec_check('git rev-parse --show-toplevel').chomp) do
90
+ yield
91
+ end
92
+ end
89
93
 
90
- def exec_check(command, okay_statuses = [0].freeze)
91
- output = `#{command}`
92
- unless okay_statuses.include?($CHILD_STATUS.exitstatus)
93
- error("Command #{command.inspect} exited with #{$CHILD_STATUS.to_i}")
94
- fail Git::Duet::ScriptDieError, 1
95
- end
96
- output
97
- end
94
+ def exec_check(command, okay_statuses = [0].freeze)
95
+ output = `#{command}`
96
+ unless okay_statuses.include?($CHILD_STATUS.exitstatus)
97
+ error("Command #{command.inspect} exited with #{$CHILD_STATUS.to_i}")
98
+ fail Git::Duet::ScriptDieError, 1
99
+ end
100
+ output
101
+ end
98
102
 
99
- def with_output_unquieted(&block)
100
- @old_quiet = @quiet
101
- @quiet = false
102
- block.call
103
- @quiet = @old_quiet
104
- rescue StandardError => e
105
- @quiet = @old_quiet
106
- raise e
107
- end
103
+ def with_output_unquieted(&block)
104
+ @old_quiet = @quiet
105
+ @quiet = false
106
+ block.call
107
+ @quiet = @old_quiet
108
+ rescue StandardError => e
109
+ @quiet = @old_quiet
110
+ raise e
111
+ end
108
112
 
109
- def with_output_quieted(&block)
110
- @old_quiet = @quiet
111
- @quiet = true
112
- block.call
113
- rescue StandardError => e
114
- raise e
115
- ensure
116
- @quiet = @old_quiet
117
- end
113
+ def with_output_quieted(&block)
114
+ @old_quiet = @quiet
115
+ @quiet = true
116
+ block.call
117
+ rescue StandardError => e
118
+ raise e
119
+ ensure
120
+ @quiet = @old_quiet
121
+ end
118
122
 
119
- def info(msg)
120
- $stdout.puts(msg) unless quiet?
121
- end
123
+ def info(msg)
124
+ $stdout.puts(msg) unless quiet?
125
+ end
122
126
 
123
- def error(msg)
124
- $stderr.puts(msg) unless quiet?
125
- end
127
+ def error(msg)
128
+ $stderr.puts(msg) unless quiet?
129
+ end
126
130
 
127
- def prompt
128
- $stdout.print '> '
129
- end
131
+ def prompt
132
+ $stdout.print '> '
133
+ end
130
134
 
131
- def quiet?
132
- ENV['GIT_DUET_QUIET'] == '1' || @quiet
135
+ def quiet?
136
+ ENV['GIT_DUET_QUIET'] == '1' || @quiet
137
+ end
138
+ end
133
139
  end
134
140
  end