edgecase-git-pair 0.2.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,5 @@
1
+ Autotest.add_hook :initialize do |autotest|
2
+ [/\.git/, /pkg\//, /\.gemspec$/, /\.log$/].each do |regexp|
3
+ autotest.add_exception regexp
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Kampmeier
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # git-pair
2
+
3
+ A git porcelain for changing `user.name` and `user.email` so you can commit as
4
+ more than one author.
5
+
6
+ ## Usage
7
+
8
+ Install the gem:
9
+
10
+ gem install edgecase-git-pair
11
+
12
+ And here's how to use it!
13
+
14
+ $ git pair
15
+
16
+ General Syntax:
17
+ git pair [reset | authors | options]
18
+
19
+ Options:
20
+ -a, --add AUTHOR Add an author. Format: "Author Name <author@example.com>"
21
+ -r, --remove NAME Remove an author. Use the full name.
22
+ -d, --reset Reset current author to default (global) config
23
+
24
+ Switching authors:
25
+ git pair aa [bb] Where AA and BB are any abbreviation of an
26
+ author's name. You can specify one or more authors.
27
+
28
+ Current config:
29
+ Author list: Adam McCrea
30
+ Jon Distad
31
+
32
+ Current author: Jon Distad + Adam McCrea
33
+ Current email: devs+jd+am@edgecase.com
34
+
35
+ ## How does it work?
36
+
37
+ The list of authors is maintained in the global git configuration file.
38
+ The current author is set in the git configuration local to the project.
39
+ The email address for a pair is generated using the default email address
40
+ from the global configuration along with the developer abbreviations.
41
+
42
+ ## About this version
43
+
44
+ This was forked from http://github.com/chrisk/git-pair. Many thanks to
45
+ Chris Kampmeier for the original version. Our version added the --reset
46
+ option, modified how email addresses are handled, and refactored much of
47
+ the code.
48
+
49
+ ## License
50
+
51
+ Copyright (c) 2009 Chris Kampmeier. See `LICENSE` for details.
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "edgecase-git-pair"
8
+ gem.summary = "Configure git to commit as more than one author"
9
+ gem.description = "A git porcelain for pair programming. Changes " +
10
+ "git-config's user.name and user.email settings so you " +
11
+ "can commit as more than one author."
12
+ gem.email = "adam@edgecase.com"
13
+ gem.homepage = "http://github.com/edgecase/git-pair"
14
+ gem.authors = ["Chris Kampmeier", "Adam McCrea", "Jon Distad"]
15
+ gem.add_development_dependency "cucumber", ">= 0"
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ begin
23
+ require 'cucumber/rake/task'
24
+ Cucumber::Rake::Task.new(:features)
25
+
26
+ task :features => :check_dependencies
27
+ rescue LoadError
28
+ task :features do
29
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
30
+ end
31
+ end
32
+
33
+ task :default => :features
34
+
35
+ # Don't print commands when shelling out (for example, running Cucumber)
36
+ RakeFileUtils.verbose(false)
37
+
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
4
+
5
+ require 'git-pair'
6
+
7
+ GitPair::Command.run!(ARGV)
8
+
@@ -0,0 +1,3 @@
1
+ default: --format progress --color features
2
+ autotest: --format pretty
3
+ autotest-all: --profile default
@@ -0,0 +1,21 @@
1
+ Feature: Adding an author
2
+ In order to commit as a pair
3
+ A user should be able to
4
+ add a name and email to the list of authors
5
+
6
+ Scenario: adding a name and email
7
+ When I add the author "Linus Torvalds <linus@example.org>"
8
+ Then `git pair` should display "Linus Torvalds" in its author list
9
+
10
+ Scenario: adding the same name and email twice
11
+ When I add the author "Linus Torvalds <linus@example.org>"
12
+ And I add the author "Linus Torvalds <linus@example.org>"
13
+ Then `git pair` should display "Linus Torvalds" in its author list only once
14
+ And the gitconfig should include "Linus Torvalds" in its author list only once
15
+
16
+ Scenario: adding the same name twice with different emails
17
+ When I add the author "Linus Torvalds <linus@example.org>"
18
+ And I add the author "Linus Torvalds <linus@example.com>"
19
+ Then `git pair` should display "Linus Torvalds" in its author list only once
20
+ And the gitconfig should include "Linus Torvalds" in its author list only once
21
+ And the gitconfig should include "linus@example.org" as the email of "Linus Torvalds"
@@ -0,0 +1,19 @@
1
+ Feature: Adding an author
2
+ In order remove old pairing partners
3
+ A user should be able to
4
+ remove a name from the list of authors
5
+
6
+ Scenario: removing a name
7
+ When I add the author "Linus Torvalds <linus@example.org>"
8
+ And I add the author "Junio C Hamano <junio@example.org>"
9
+ And I remove the name "Junio C Hamano"
10
+ Then `git pair` should display the following author list:
11
+ | name |
12
+ | Linus Torvalds |
13
+
14
+ Scenario: removing all names
15
+ When I add the author "Linus Torvalds <linus@example.org>"
16
+ And I add the author "Junio C Hamano <junio@example.org>"
17
+ And I remove the name "Linus Torvalds"
18
+ And I remove the name "Junio C Hamano"
19
+ Then `git pair` should display an empty author list
@@ -0,0 +1,7 @@
1
+
2
+ Scenario: resetting the current authors
3
+ Given I have added the author "Linus Torvalds <linus@example.org>"
4
+ And my global Git configuration is setup with user "Global User"
5
+ And I switch to the pair "LT"
6
+ When I reset the current authors
7
+ Then `git pair` should display "Global User" for the current author
@@ -0,0 +1,91 @@
1
+ Given /^I have added the author "([^\"]*)"$/ do |name_and_email|
2
+ When %(I add the author "#{name_and_email}")
3
+ end
4
+
5
+ Given /^my global Git configuration is setup with user "([^\"]*)"$/ do |name|
6
+ git_config "--global user.name \"#{name}\""
7
+ end
8
+
9
+ Given /^my global Git configuration is setup with email "([^\"]*)"$/ do |email|
10
+ git_config "--global user.email \"#{email}\""
11
+ end
12
+
13
+ When /^I add the author "([^\"]*)"$/ do |name_and_email|
14
+ git_pair %(--add "#{name_and_email}")
15
+ end
16
+
17
+ When /^I remove the name "([^\"]*)"$/ do |name|
18
+ git_pair %(--remove "#{name}")
19
+ end
20
+
21
+ When /^I (?:try to )?switch to the pair "([^\"]*)"$/ do |abbreviations|
22
+ @output = git_pair abbreviations
23
+ end
24
+
25
+ When /^I reset the current authors$/ do
26
+ git_pair '--reset'
27
+ end
28
+
29
+ Then /^`git pair` should display "([^\"]*)" in its author list$/ do |name|
30
+ output = git_pair
31
+ authors = authors_list_from_output(output)
32
+ assert authors.include?(name)
33
+ end
34
+
35
+ Then /^`git pair` should display "([^\"]*)" in its author list only once$/ do |name|
36
+ output = git_pair
37
+ authors = authors_list_from_output(output)
38
+ assert_equal 1, authors.select { |author| author == name}.size
39
+ end
40
+
41
+ Then /^`git pair` should display "([^\"]*)" for the current author$/ do |names|
42
+ output = git_pair
43
+ assert_equal names, current_author_from_output(output)
44
+ end
45
+
46
+ Then /^`git pair` should display "([^\"]*)" for the current email$/ do |email|
47
+ output = git_pair
48
+ assert_equal email, current_email_from_output(output)
49
+ end
50
+
51
+ Then /^the gitconfig should include "([^\"]*)" in its author list only once$/ do |name|
52
+ output = git_config
53
+ authors = output.split("\n").map { |line| line =~ /^git-pair\.authors=(.*) <[^>]+>$/; $1 }.compact
54
+ assert_equal 1, authors.select { |author| author == name}.size
55
+ end
56
+
57
+ Then /^the gitconfig should include "([^\"]*)" as the email of "([^\"]*)"$/ do |email, name|
58
+ output = git_config
59
+ authors = output.split("\n").map { |line| line =~ /^git-pair\.authors=.* <([^>]+)>$/; $1 }.compact
60
+ assert_equal 1, authors.select { |author| author == email}.size
61
+ end
62
+
63
+ Then /^`git pair` should display the following author list:$/ do |table|
64
+ output = git_pair
65
+ names = authors_list_from_output(output).map { |name| {"name" => name} }
66
+ table.diff! names
67
+ end
68
+
69
+ Then /^`git pair` should display an empty author list$/ do
70
+ output = git_pair
71
+ assert authors_list_from_output(output).empty?
72
+ end
73
+
74
+ Then /^the last command's output should include "([^\"]*)"$/ do |output|
75
+ assert @output.include?(output)
76
+ end
77
+
78
+ def authors_list_from_output(output)
79
+ output =~ /Author list: (.*?)\n\s?\n/im
80
+ $1.strip.split("\n").map { |name| name.strip }
81
+ end
82
+
83
+ def current_author_from_output(output)
84
+ output =~ /Current author: (.*?)\n/im
85
+ $1.strip
86
+ end
87
+
88
+ def current_email_from_output(output)
89
+ output =~ /Current email: (.*?)\n/im
90
+ $1.strip
91
+ end
@@ -0,0 +1,50 @@
1
+ require 'tmpdir'
2
+ require 'test/unit/assertions'
3
+ World(Test::Unit::Assertions)
4
+
5
+
6
+ module RepositoryHelper
7
+ # TODO: use 1.8.7's Dir.mktmpdir?
8
+ TEST_REPO_PATH = File.join(Dir::tmpdir, "git-pair-test-repo")
9
+ TEST_REPO_DOT_GIT_PATH = "#{TEST_REPO_PATH}/.git"
10
+
11
+ PROJECT_PATH = File.join(File.dirname(__FILE__), "../..")
12
+ GIT_PAIR = "#{PROJECT_PATH}/bin/git-pair"
13
+ CONFIG_BACKUP_PATH = "#{PROJECT_PATH}/tmp"
14
+
15
+ def git_pair(options = "")
16
+ output = `HOME=#{TEST_REPO_PATH} GIT_DIR=#{TEST_REPO_DOT_GIT_PATH} && #{GIT_PAIR} #{options} 2>&1`
17
+ output.gsub(/\e\[\d\d?m/, '') # strip any ANSI colors
18
+ end
19
+
20
+ def git_config(options = nil)
21
+ options ||= "--list"
22
+ `HOME=#{TEST_REPO_PATH} GIT_DIR=#{TEST_REPO_DOT_GIT_PATH} && git config #{options} 2>&1`
23
+ end
24
+
25
+ def backup_gitconfigs
26
+ FileUtils.mkdir_p CONFIG_BACKUP_PATH
27
+ FileUtils.cp File.expand_path("~/.gitconfig"), "#{CONFIG_BACKUP_PATH}/.gitconfig.backup"
28
+ FileUtils.cp "#{PROJECT_PATH}/.git/config", "#{CONFIG_BACKUP_PATH}/config.backup"
29
+ end
30
+
31
+ def restore_gitconfigs
32
+ FileUtils.cp "#{CONFIG_BACKUP_PATH}/config.backup", "#{PROJECT_PATH}/.git/config"
33
+ FileUtils.cp "#{CONFIG_BACKUP_PATH}/.gitconfig.backup", File.expand_path("~/.gitconfig")
34
+ FileUtils.rm_rf CONFIG_BACKUP_PATH
35
+ end
36
+ end
37
+
38
+ World(RepositoryHelper)
39
+
40
+
41
+ Before do
42
+ backup_gitconfigs
43
+ FileUtils.mkdir_p RepositoryHelper::TEST_REPO_PATH
44
+ `GIT_DIR=#{RepositoryHelper::TEST_REPO_DOT_GIT_PATH} && git init`
45
+ end
46
+
47
+ After do
48
+ FileUtils.rm_rf RepositoryHelper::TEST_REPO_PATH
49
+ restore_gitconfigs
50
+ end
@@ -0,0 +1,22 @@
1
+ Feature: Switching authors
2
+ In order to indicate which authors are committing
3
+ A user should be able to
4
+ change the currently active pair
5
+
6
+ Scenario: No authors have been added
7
+ When I try to switch to the pair "AA BB"
8
+ Then the last command's output should include "Please add some authors first"
9
+
10
+ Scenario: Pairing with a single author
11
+ Given I have added the author "Linus Torvalds <linus@example.org>"
12
+ When I switch to the pair "LT"
13
+ Then `git pair` should display "Linus Torvalds" for the current author
14
+ And `git pair` should display "linus@example.org" for the current email
15
+
16
+ Scenario: Pairing with two authors
17
+ Given I have added the author "Linus Torvalds <linus@example.org>"
18
+ And I have added the author "Junio C Hamano <junio@example.org>"
19
+ And my global Git configuration is setup with email "devs@example.com"
20
+ When I switch to the pair "LT JCH"
21
+ Then `git pair` should display "Junio C Hamano + Linus Torvalds" for the current author
22
+ And `git pair` should display "devs+jch+lt@example.com" for the current email
@@ -0,0 +1,12 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'git-pair/command'
4
+ require 'git-pair/author'
5
+ require 'git-pair/config'
6
+
7
+ module GitPair
8
+
9
+ class NoMatchingAuthorsError < ArgumentError; end
10
+ class MissingConfigurationError < RuntimeError; end
11
+
12
+ end
@@ -0,0 +1,52 @@
1
+ module GitPair
2
+ class Author
3
+
4
+ def self.all
5
+ Config.all_author_strings.map { |string| new(string) }
6
+ end
7
+
8
+ def self.find_all(abbrs)
9
+ raise MissingConfigurationError, "Please add some authors first" if all.empty?
10
+ abbrs.map { |abbr| self.find(abbr) }
11
+ end
12
+
13
+ def self.find(abbr)
14
+ all.find { |author| author.match?(abbr) } ||
15
+ raise(NoMatchingAuthorsError, "no authors matched #{abbr}")
16
+ end
17
+
18
+ def self.email(authors)
19
+ if authors.length == 1
20
+ authors.first.email
21
+ else
22
+ initials_string = '+' + authors.map { |a| a.initials }.join('+')
23
+ Config.default_email.sub("@", "#{initials_string}@")
24
+ end
25
+ end
26
+
27
+ def self.exists?(author)
28
+ self.all.find { |a| a.name == author.name }
29
+ end
30
+
31
+ attr_reader :name, :email
32
+
33
+ def initialize(string)
34
+ string =~ /^(.+)\s+<([^>]+)>$/
35
+ @name = $1.to_s
36
+ @email = $2.to_s
37
+ end
38
+
39
+ def <=>(other)
40
+ name.split.last <=> other.name.split.last
41
+ end
42
+
43
+ def initials
44
+ name.split.map { |word| word[0].chr }.join.downcase
45
+ end
46
+
47
+ def match?(abbr)
48
+ abbr.downcase == initials
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,88 @@
1
+ require 'optparse'
2
+
3
+ module GitPair
4
+ module Command
5
+ extend self
6
+
7
+ C_BOLD, C_REVERSE, C_RED, C_RESET = "\e[1m", "\e[7m", "\e[91m", "\e[0m"
8
+
9
+ def run!(args)
10
+ parser = OptionParser.new do |opts|
11
+ opts.banner = highlight('General Syntax:')
12
+ opts.separator ' git pair [reset | authors | options]'
13
+
14
+ opts.separator ' '
15
+ opts.separator highlight('Options:')
16
+ opts.on '-a', '--add AUTHOR', 'Add an author. Format: "Author Name <author@example.com>"' do |author|
17
+ Config.add_author Author.new(author)
18
+ end
19
+ opts.on '-r', '--remove NAME', 'Remove an author. Use the full name.' do |name|
20
+ Config.remove_author name
21
+ end
22
+ opts.on '-d', '--reset', 'Reset current author to default (global) config' do
23
+ Config.reset
24
+ end
25
+
26
+ opts.separator ' '
27
+ opts.separator highlight('Switching authors:')
28
+ opts.separator ' git pair aa [bb] Where AA and BB are any abbreviation of an'
29
+ opts.separator ' '*37 + 'author\'s name. You can specify one or more authors.'
30
+
31
+ opts.separator ' '
32
+ opts.separator highlight('Current config:')
33
+ opts.separator author_list.split("\n")
34
+ opts.separator ' '
35
+ opts.separator current_author_info.split("\n")
36
+ end
37
+
38
+ authors = parser.parse!(args.dup)
39
+
40
+ if args.empty?
41
+ puts parser.help
42
+ elsif authors.empty?
43
+ puts author_list
44
+ puts
45
+ puts current_author_info
46
+ else
47
+ Config.switch Author.find_all(authors)
48
+ puts current_author_info
49
+ end
50
+
51
+ rescue OptionParser::MissingArgument
52
+ abort "missing required argument", parser.help
53
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument => e
54
+ abort e.message.sub(':', ''), parser.help
55
+ rescue NoMatchingAuthorsError => e
56
+ abort e.message, "\n" + author_list
57
+ rescue MissingConfigurationError => e
58
+ abort e.message, parser.help
59
+ end
60
+
61
+ def author_list
62
+ " #{bold 'Author list:'} #{Author.all.sort.map { |a| a.name }.join "\n "}"
63
+ end
64
+
65
+ def current_author_info
66
+ " #{bold 'Current author:'} #{Config.current_author}\n" +
67
+ " #{bold 'Current email:'} #{Config.current_email}\n "
68
+ end
69
+
70
+ def abort(error_message, extra = "")
71
+ super red(" Error: #{error_message}\n") + extra
72
+ end
73
+
74
+ def highlight(string)
75
+ "#{C_REVERSE}#{string}#{C_RESET}"
76
+ end
77
+
78
+ def bold(string)
79
+ "#{C_BOLD}#{string}#{C_RESET}"
80
+ end
81
+
82
+ def red(string)
83
+ "#{C_RED}#{C_REVERSE}#{string}#{C_RESET}"
84
+ end
85
+
86
+ end
87
+ end
88
+
@@ -0,0 +1,44 @@
1
+ module GitPair
2
+ module Config
3
+ extend self
4
+
5
+ def all_author_strings
6
+ `git config --global --get-all git-pair.authors`.split("\n")
7
+ end
8
+
9
+ def add_author(author)
10
+ unless Author.exists?(author)
11
+ `git config --global --add git-pair.authors "#{author.name} <#{author.email}>"`
12
+ end
13
+ end
14
+
15
+ def remove_author(name)
16
+ `git config --global --unset-all git-pair.authors "^#{name} <"`
17
+ `git config --global --remove-section git-pair` if all_author_strings.empty?
18
+ end
19
+
20
+ def switch(authors)
21
+ authors.sort!
22
+
23
+ `git config user.name "#{authors.map { |a| a.name }.join(' + ')}"`
24
+ `git config user.email "#{Author.email(authors)}"`
25
+ end
26
+
27
+ def reset
28
+ `git config --remove-section user`
29
+ end
30
+
31
+ def default_email
32
+ `git config --global --get user.email`.strip
33
+ end
34
+
35
+ def current_author
36
+ `git config --get user.name`.strip
37
+ end
38
+
39
+ def current_email
40
+ `git config --get user.email`.strip
41
+ end
42
+
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: edgecase-git-pair
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Kampmeier
8
+ - Adam McCrea
9
+ - Jon Distad
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2010-02-18 00:00:00 -05:00
15
+ default_executable: git-pair
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: cucumber
19
+ type: :development
20
+ version_requirement:
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: "0"
26
+ version:
27
+ description: A git porcelain for pair programming. Changes git-config's user.name and user.email settings so you can commit as more than one author.
28
+ email: adam@edgecase.com
29
+ executables:
30
+ - git-pair
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - LICENSE
35
+ - README.markdown
36
+ files:
37
+ - .autotest
38
+ - .gitignore
39
+ - LICENSE
40
+ - README.markdown
41
+ - Rakefile
42
+ - bin/git-pair
43
+ - config/cucumber.yml
44
+ - features/adding_an_author.feature
45
+ - features/removing_an_author.feature
46
+ - features/resetting_the_pair.feature
47
+ - features/step_definitions/config_steps.rb
48
+ - features/support/env.rb
49
+ - features/switching_authors.feature
50
+ - lib/git-pair.rb
51
+ - lib/git-pair/author.rb
52
+ - lib/git-pair/command.rb
53
+ - lib/git-pair/config.rb
54
+ has_rdoc: true
55
+ homepage: http://github.com/edgecase/git-pair
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --charset=UTF-8
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.5
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Configure git to commit as more than one author
82
+ test_files: []
83
+