git-duet 0.3.0 → 0.4.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.
@@ -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