git-duo 1.0.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.
- checksums.yaml +15 -0
- data/.autotest +5 -0
- data/.gitignore +17 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/Rakefile +19 -0
- data/bin/git-duo +5 -0
- data/bin/git-solo +6 -0
- data/git-duo.gemspec +26 -0
- data/lib/git/duo/author.rb +32 -0
- data/lib/git/duo/author_collection.rb +22 -0
- data/lib/git/duo/cli.rb +63 -0
- data/lib/git/duo/exceptions.rb +5 -0
- data/lib/git/duo/pair.rb +57 -0
- data/lib/git/duo/repo.rb +85 -0
- data/lib/git/duo/version.rb +5 -0
- data/lib/git/duo/wrapper.rb +15 -0
- data/lib/git/duo.rb +6 -0
- data/test/git/duo/author_collection_test.rb +28 -0
- data/test/git/duo/author_test.rb +43 -0
- data/test/git/duo/pair_test.rb +75 -0
- data/test/git/duo/repo_test.rb +91 -0
- data/test/test_helper.rb +44 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDNjMWI5YWM3YzYwOGE4OGNhMmE0NWIwZWMzYmU2ODE2MDYwNmEwZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDBmZTMwYTExNGY1ZjQyYWZhNGMxNzNkODNmZDI2MjYwZjhlNTExNA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OGU4MGViMzIzM2NlOWI3ZGFjZGJlYWViZDhmZmE5MmZhZDJiZmQ2ZWRlMWQy
|
10
|
+
NzRlYWMyYzcyODc4YWYyOWJiYjc0ZjQzMDg5MjFhMGUzNjM5MDgxNDYwZTlj
|
11
|
+
ZDRlNTRmNDZmMGRhNGRiNmZjMjEwYzJiZmU3NDdlNzlmZjc5YjU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDBkMWZjNGJlM2I0MjQ0MDA4NDQ3MTgzZTMzOTllZjM3ODhmMThlYmYxMjQy
|
14
|
+
Nzk5YWZmY2VjNDEwY2VmNTM1NTdhODAzMjc4Mzg0YjI5OWYwOTk2MGVhNzhi
|
15
|
+
NDE1MGRhOTRmMmVhNTM0YmQ4NWI0MjU5NWEwMzJhMzE5ZmQyYmU=
|
data/.autotest
ADDED
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Teo Ljungberg
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Git Duo
|
2
|
+
|
3
|
+
- [home](https://github.com/teoljungberg/git-duo)
|
4
|
+
- [code](https://github.com/teoljungberg/git-duo)
|
5
|
+
- [bugs](https://github.com/teoljungberg/git-duo/issues)
|
6
|
+
|
7
|
+
# Description
|
8
|
+
|
9
|
+
A git porcelain for duo programming. Changes git-config's user.name and
|
10
|
+
user.email settings so you can commit as more than one author.
|
11
|
+
|
12
|
+
# Features/problems:
|
13
|
+
|
14
|
+
* Keep pairs per repository
|
15
|
+
* Import pairs between repositories
|
16
|
+
* Pairing made easy(-ier)
|
17
|
+
|
18
|
+
# Synopsis
|
19
|
+
```bash
|
20
|
+
$ git duo --email "board+%names@gotham.travel"
|
21
|
+
```
|
22
|
+
|
23
|
+
```bash
|
24
|
+
$ git duo --add "bruce Bruce Wayne <bruce@gotham.travel>"
|
25
|
+
$ git duo --add "alfred Alfred Pennyworth <alfred@gotham.travel>"
|
26
|
+
```
|
27
|
+
|
28
|
+
```bash
|
29
|
+
$ git duo alfred bruce
|
30
|
+
Alfred Pennyworth + Bruce Wayne <board+alfred+bruce@gotham.travel>
|
31
|
+
```
|
32
|
+
|
33
|
+
```bash
|
34
|
+
$ git duo --add "jim Jim Gordon <jim@gotham.travel>"
|
35
|
+
$ git duo alfred bruce jim
|
36
|
+
Alfred Pennyworth + Bruce Wayne + Jim Gordon <dev+alfred+bruce+jim@gotham.travel>
|
37
|
+
```
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ git duo --list
|
41
|
+
Bruce Wayne <bruce@gotham.travel>
|
42
|
+
Alfred Pennyworth <alfred@gotham.travel>
|
43
|
+
Jim Gordon <jim@gotham.travel>
|
44
|
+
```
|
45
|
+
|
46
|
+
```bash
|
47
|
+
$ git duo --email "law+%names@gotham.travel"
|
48
|
+
Alfred Pennyworth + Bruce Wayne <law+alfred+bruce@gotham.travel>
|
49
|
+
```
|
50
|
+
|
51
|
+
```bash
|
52
|
+
$ cd ../new-project
|
53
|
+
$ git duo --import ../old-project
|
54
|
+
# this will import the authors and email from the `old-project` project
|
55
|
+
# into `new-project`
|
56
|
+
```
|
57
|
+
|
58
|
+
```bash
|
59
|
+
$ git solo
|
60
|
+
Teo Ljungberg <teo.ljungberg@gmail.com>
|
61
|
+
```
|
62
|
+
|
63
|
+
# Requirements
|
64
|
+
|
65
|
+
* Ruby 1.9 and above
|
66
|
+
* Rake
|
67
|
+
|
68
|
+
# Install
|
69
|
+
|
70
|
+
* Clone down this repository
|
71
|
+
* Run `rake install`
|
72
|
+
* Good to go
|
73
|
+
|
74
|
+
# Developers
|
75
|
+
|
76
|
+
After checking out the source, run:
|
77
|
+
|
78
|
+
```bash
|
79
|
+
$ rake newb
|
80
|
+
```
|
81
|
+
|
82
|
+
This task will install any missing dependencies, the gem itself and
|
83
|
+
run the tests
|
84
|
+
|
85
|
+
## Autotest
|
86
|
+
* Install autotest (as a part of [ZenTest][zentest])
|
87
|
+
* Install [autotest-suffix][autotest-suffix] (since I prefer `foo_test.rb` to `test_foo.rb`)
|
88
|
+
|
89
|
+
## Contributing
|
90
|
+
|
91
|
+
1. Fork it
|
92
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
93
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
94
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
95
|
+
5. Create new Pull Request
|
96
|
+
|
97
|
+
[zentest]: https://github.com/seattlerb/ZenTest
|
98
|
+
[autotest-suffix]: https://github.com/blowmage/autotest-suffix/
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.pattern = "test/**/*_test.rb"
|
7
|
+
end
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
desc 'Setup a new dev computer'
|
11
|
+
task newb: [:install_deps, :install, :test] do
|
12
|
+
puts
|
13
|
+
puts 'Happy hacking'
|
14
|
+
end
|
15
|
+
|
16
|
+
task :install_deps do
|
17
|
+
puts '--- installing dependencies'
|
18
|
+
system 'bundle install'
|
19
|
+
end
|
data/bin/git-duo
ADDED
data/bin/git-solo
ADDED
data/git-duo.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'git/duo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "git-duo"
|
8
|
+
spec.version = Git::Duo::VERSION
|
9
|
+
spec.authors = ["Teo Ljungberg"]
|
10
|
+
spec.email = ["teo.ljungberg@gmail.com"]
|
11
|
+
spec.description = %q{A git porcelain for duo programming. Changes git-config's user.name and user.email settings so you can commit as more than one author.}
|
12
|
+
spec.summary = %q{Git pairing made easy}
|
13
|
+
spec.homepage = "https://github.com/teoljungberg/git-duo"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "mocha"
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Git
|
2
|
+
module Duo
|
3
|
+
class Author
|
4
|
+
EMAIL_REGEXP = /(?:<?(.+@[^>]+)>?)/
|
5
|
+
|
6
|
+
def self.import(new_author)
|
7
|
+
key, *author = new_author.split(?\s)
|
8
|
+
first, last, email = author
|
9
|
+
|
10
|
+
new({ key: key,
|
11
|
+
name: "#{first} #{last}",
|
12
|
+
email: email.match(EMAIL_REGEXP)[1] })
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :key, :name, :email
|
16
|
+
|
17
|
+
def initialize(opts = {})
|
18
|
+
@key = opts[:key]
|
19
|
+
@name = opts[:name]
|
20
|
+
@email = opts[:email]
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
key && name && email
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{name} <#{email}>"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Git
|
2
|
+
module Duo
|
3
|
+
class AuthorCollection
|
4
|
+
attr_reader :authors
|
5
|
+
|
6
|
+
def initialize authors
|
7
|
+
@authors = authors
|
8
|
+
end
|
9
|
+
|
10
|
+
def where opts = {}
|
11
|
+
result = []
|
12
|
+
result += opts.
|
13
|
+
select {|k, _| authors.sample.respond_to? k }.
|
14
|
+
map do |k, v|
|
15
|
+
authors.select {|o| o.send(k) =~ /#{v}/i }
|
16
|
+
end.flatten
|
17
|
+
rescue NoMethodError
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/git/duo/cli.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'git/duo'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Git
|
5
|
+
module Duo
|
6
|
+
class CLI
|
7
|
+
def self.start
|
8
|
+
parser = OptionParser.new do |opts|
|
9
|
+
puts current_repo.committer if ARGV.empty?
|
10
|
+
|
11
|
+
opts.on '--add AUTHOR', 'Add an author. Format: "Key Author Name <author@example.com>"' do |string|
|
12
|
+
current_repo.authors = Author.import string
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on '--list', 'Lists the authors in the repository' do
|
16
|
+
puts current_repo.authors
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on '--email EMAIL', 'Set email format. Format: dev@example.com' do |email|
|
20
|
+
current_repo.email = email
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on '--import=PATH/TO/REPO', 'Import pairs from another repo' do |path|
|
24
|
+
import_repo = Repo.new path
|
25
|
+
current_repo.email = import_repo.email
|
26
|
+
current_repo.authors = import_repo.authors
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on '-h', 'Show this message' do
|
30
|
+
puts opts
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
parser.parse!
|
36
|
+
|
37
|
+
unless ARGV.empty?
|
38
|
+
authors = ARGV.sort.map do |key|
|
39
|
+
author = AuthorCollection.new(current_repo.authors).
|
40
|
+
where(key: key).first
|
41
|
+
abort "`#{key}` can't be found, see -h on how to add new authors" unless author
|
42
|
+
Author.new(key: key, name: author.name, email: author.email)
|
43
|
+
end
|
44
|
+
pair = Pair.new authors
|
45
|
+
pair.save
|
46
|
+
puts pair.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
current_repo.save
|
50
|
+
rescue OptionParser::MissingArgument
|
51
|
+
abort "missing required argument\n\n #{parser.help}"
|
52
|
+
rescue Git::Duo::EmailNotImplementedError
|
53
|
+
abort "`Email format isn't set, see -h on how to set the email format"
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def self.current_repo
|
59
|
+
@current_repo ||= Repo.current
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/git/duo/pair.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'git/duo/wrapper'
|
2
|
+
require 'git/duo/exceptions'
|
3
|
+
|
4
|
+
module Git
|
5
|
+
module Duo
|
6
|
+
class Pair
|
7
|
+
attr_reader :authors, :wrapper
|
8
|
+
|
9
|
+
def initialize authors, opts = {}
|
10
|
+
@authors = authors.sort_by {|author| author.key }
|
11
|
+
@wrapper = opts.fetch(:wrapper) { Git::Duo::Wrapper.new File.join(Dir.pwd, '.git') }
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
authors.map(&:name).join ' + '
|
16
|
+
end
|
17
|
+
|
18
|
+
def email
|
19
|
+
base_email.gsub "%names", authors.map(&:key).join(?+)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#{name} <#{email}>"
|
24
|
+
end
|
25
|
+
alias_method :inspect, :to_s
|
26
|
+
|
27
|
+
def save
|
28
|
+
save_pair_name
|
29
|
+
save_pair_email
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def base_email
|
35
|
+
wrapper.config("git-duo.email").first ||
|
36
|
+
guess_base_email_from_authors ||
|
37
|
+
raise(Git::Duo::EmailNotImplemented)
|
38
|
+
end
|
39
|
+
|
40
|
+
def guess_base_email_from_authors
|
41
|
+
domains = authors.map do |author|
|
42
|
+
author.email.split(?@).last
|
43
|
+
end.uniq
|
44
|
+
|
45
|
+
"dev+%names@#{domains.first}" if domains.size == 1
|
46
|
+
end
|
47
|
+
|
48
|
+
def save_pair_name
|
49
|
+
wrapper.config "user.name '#{name}'"
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_pair_email
|
53
|
+
wrapper.config "user.email '#{email}'"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/git/duo/repo.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'git/duo/wrapper'
|
2
|
+
require 'git/duo/author'
|
3
|
+
|
4
|
+
module Git
|
5
|
+
module Duo
|
6
|
+
class Repo
|
7
|
+
def self.current
|
8
|
+
new Dir.pwd
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :directory, :wrapper
|
12
|
+
|
13
|
+
def initialize(directory, opts = {})
|
14
|
+
@directory = File.expand_path(directory)
|
15
|
+
@wrapper = opts.fetch(:wrapper) { Git::Duo::Wrapper.new(git_directory) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def authors
|
19
|
+
return @authors if defined? @authors
|
20
|
+
config.
|
21
|
+
reject {|key| non_git_author? key }.
|
22
|
+
map {|a| Git::Duo::Author.import(a) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def authors=(new_authors)
|
26
|
+
@authors = new_authors
|
27
|
+
end
|
28
|
+
|
29
|
+
def committer
|
30
|
+
name = wrapper.config("user.name").shift
|
31
|
+
email = wrapper.config("user.email").shift
|
32
|
+
|
33
|
+
Author.new(name: name, email: email).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def email
|
37
|
+
return @email if defined? @email
|
38
|
+
config.
|
39
|
+
select {|key| non_git_author? key }.
|
40
|
+
map {|key| key.gsub(/^email\s/, '') }.
|
41
|
+
first
|
42
|
+
end
|
43
|
+
|
44
|
+
def email=(new_email)
|
45
|
+
@email = new_email
|
46
|
+
end
|
47
|
+
|
48
|
+
def solo!
|
49
|
+
wrapper.config '--remove-section user'
|
50
|
+
end
|
51
|
+
|
52
|
+
def save
|
53
|
+
save_email if email
|
54
|
+
save_authors if authors
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def non_git_author?(key)
|
60
|
+
key =~ /email/
|
61
|
+
end
|
62
|
+
|
63
|
+
def save_authors
|
64
|
+
authors.each do |author|
|
65
|
+
wrapper.config "git-duo.#{author.key} '#{author}'"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def save_email
|
70
|
+
wrapper.config "git-duo.email '#{email}'"
|
71
|
+
end
|
72
|
+
|
73
|
+
def config
|
74
|
+
wrapper.
|
75
|
+
config('--get-regexp git-duo').
|
76
|
+
select {|key| key.start_with? 'git-duo' }.
|
77
|
+
map {|config| config.gsub('git-duo.', '') }
|
78
|
+
end
|
79
|
+
|
80
|
+
def git_directory
|
81
|
+
File.join(directory, '.git')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Git
|
2
|
+
module Duo
|
3
|
+
class Wrapper
|
4
|
+
PIPE_STDOUT_TO_STDERR = '2>&1'
|
5
|
+
|
6
|
+
def initialize(directory)
|
7
|
+
@directory = directory
|
8
|
+
end
|
9
|
+
|
10
|
+
def config(args)
|
11
|
+
`git --git-dir=#{@directory} config #{args} #{PIPE_STDOUT_TO_STDERR}`.split("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/git/duo.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
require 'git/duo/author_collection'
|
3
|
+
|
4
|
+
module Git::Duo
|
5
|
+
class AuthorCollectionTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@collection = AuthorCollection.new alfred_and_bruce
|
8
|
+
end
|
9
|
+
attr_reader :collection
|
10
|
+
|
11
|
+
def test_where_with_existing_keys
|
12
|
+
assert_instance_of Author, collection.where(key: 'alfred').first
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_where_with_nonexisting_keys_returns_empty_array
|
16
|
+
assert_empty collection.where(omg: 0)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_where_returns_the_result_of_the_valid_query
|
20
|
+
refute_empty collection.where(key: 'alfred', omg: 0)
|
21
|
+
refute_empty collection.where(omg: 0, key: 'alfred')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_where_returns_empty_array_with_an_empty_search
|
25
|
+
assert_empty collection.where
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module Git::Duo
|
4
|
+
class AuthorTest < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
@author = Author.new(author_options)
|
7
|
+
end
|
8
|
+
attr_reader :author
|
9
|
+
|
10
|
+
def author_options
|
11
|
+
{
|
12
|
+
key: 'alfred',
|
13
|
+
name: 'Alfred Pennyworth',
|
14
|
+
email: 'alfred@gotham.travel'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_author_requires_name
|
19
|
+
author = Author.new author_options.merge(name: nil)
|
20
|
+
refute author.valid?
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_author_requires_email
|
24
|
+
author = Author.new author_options.merge(email: nil)
|
25
|
+
refute author.valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_author_requires_key
|
29
|
+
author = Author.new author_options.merge(key: nil)
|
30
|
+
refute author.valid?
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_import
|
34
|
+
author = Author.import("bruce Bruce Wayne <bruce@gotham.travel>")
|
35
|
+
assert author.valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_to_s
|
39
|
+
expected = "Alfred Pennyworth <alfred@gotham.travel>"
|
40
|
+
assert_equal expected, author.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module Git::Duo
|
4
|
+
class PairTest < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
@wrapper = DummyWrapper.new(:path_to_hell)
|
7
|
+
@pair = Pair.new alfred_and_bruce, wrapper: wrapper
|
8
|
+
end
|
9
|
+
attr_reader :pair, :wrapper
|
10
|
+
|
11
|
+
def test_pair_supports_multiple_authors
|
12
|
+
wrapper.expects(:config).with("git-duo.email").
|
13
|
+
returns(["board+%names@gotham.travel"]).at_least_once
|
14
|
+
|
15
|
+
pair = Pair.new alfred_and_bruce_rachel, wrapper: wrapper
|
16
|
+
expected_name = "Alfred Pennyworth + Bruce Wayne + Rachel Dawes"
|
17
|
+
expected_email = "board+alfred+bruce+rachel@gotham.travel"
|
18
|
+
|
19
|
+
assert_equal expected_name, pair.name
|
20
|
+
assert_equal expected_email, pair.email
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_name
|
24
|
+
expected = 'Alfred Pennyworth + Bruce Wayne'
|
25
|
+
assert_equal expected, pair.name
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_email
|
29
|
+
wrapper.expects(:config).with("git-duo.email").
|
30
|
+
returns(["board+%names@gotham.travel"]).at_least_once
|
31
|
+
|
32
|
+
expected = 'board+alfred+bruce@gotham.travel'
|
33
|
+
assert_equal expected, pair.email
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_email_guesses_the_email_domain_from_authors
|
37
|
+
wrapper.expects(:config).with("git-duo.email").
|
38
|
+
returns([]).at_least_once
|
39
|
+
|
40
|
+
expected = "dev+alfred+bruce@gotham.travel"
|
41
|
+
assert_equal expected, pair.email
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_email_raises_error_if_domain_could_not_be_guessed
|
45
|
+
wrapper.expects(:config).with("git-duo.email").
|
46
|
+
returns([]).at_least_once
|
47
|
+
|
48
|
+
assert_raises Git::Duo::EmailNotImplemented do
|
49
|
+
Pair.new(bruce_and_edward, wrapper: wrapper).email
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_to_s
|
54
|
+
wrapper.expects(:config).with("git-duo.email").
|
55
|
+
returns(["board+%names@gotham.travel"]).at_least_once
|
56
|
+
|
57
|
+
expected = 'Alfred Pennyworth + Bruce Wayne <board+alfred+bruce@gotham.travel>'
|
58
|
+
assert_equal expected, pair.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_inspect_is_to_s
|
62
|
+
assert_equal pair.to_s, pair.inspect
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_save
|
66
|
+
wrapper.expects(:config).with("git-duo.email").
|
67
|
+
returns(["board+%names@gotham.travel"]).at_least_once
|
68
|
+
|
69
|
+
wrapper.expects(:config).with("user.email 'board+alfred+bruce@gotham.travel'")
|
70
|
+
wrapper.expects(:config).with("user.name 'Alfred Pennyworth + Bruce Wayne'")
|
71
|
+
|
72
|
+
pair.save
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module Git::Duo
|
4
|
+
class RepoTest < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
@wrapper = DummyWrapper.new(:path_to_hell)
|
7
|
+
@repo = Repo.new '~/code/mynewsdesk', wrapper: wrapper
|
8
|
+
end
|
9
|
+
attr_reader :repo, :wrapper
|
10
|
+
|
11
|
+
def test_current_inits_repo_with_current_dir
|
12
|
+
repo = Repo.current
|
13
|
+
expected = Dir.pwd
|
14
|
+
|
15
|
+
assert_equal expected, repo.directory
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_initialize_expands_directory_path
|
19
|
+
expected = repo.directory
|
20
|
+
assert_equal expected, File.join(ENV['HOME'], 'code', 'mynewsdesk')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_authors_returns_author_objects
|
24
|
+
assert_instance_of Author, repo.authors.sample
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_importing_authors
|
28
|
+
wrapper.expects(:config).with('--get-regexp git-duo').returns(git_config).at_least_once
|
29
|
+
wrapper.expects(:config).with("git-duo.email 'board+%names@gotham.travel'")
|
30
|
+
wrapper.expects(:config).with("git-duo.jim 'Jim Gordon <jim@gotham.travel>'")
|
31
|
+
wrapper.expects(:config).with("git-duo.harvey 'Harvey Dent <harvey@gotham.travel>'")
|
32
|
+
|
33
|
+
repo.authors = jim_and_harvey
|
34
|
+
repo.save
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_committer
|
38
|
+
wrapper.expects(:config).with('user.name').returns ["Bruce Wayne"]
|
39
|
+
wrapper.expects(:config).with('user.email').returns ["bruce@gotham.travel"]
|
40
|
+
|
41
|
+
expected = "Bruce Wayne <bruce@gotham.travel>"
|
42
|
+
assert_equal expected, repo.committer
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_importing_email
|
46
|
+
wrapper.expects(:config).with('--get-regexp git-duo').returns(git_config).at_least_once
|
47
|
+
wrapper.expects(:config).with("git-duo.email 'law+%names@gotham.travel'")
|
48
|
+
wrapper.expects(:config).with("git-duo.alfred 'Alfred Pennyworth <alfred@gotham.travel>'")
|
49
|
+
wrapper.expects(:config).with("git-duo.bruce 'Bruce Wayne <bruce@gotham.travel>'")
|
50
|
+
|
51
|
+
repo.email = "law+%names@gotham.travel"
|
52
|
+
repo.save
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_email_returns_set_group_email
|
56
|
+
assert_equal "board+%names@gotham.travel", repo.email
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_solo_bang_resets_the_pair
|
60
|
+
wrapper.expects(:config).with('--remove-section user')
|
61
|
+
|
62
|
+
repo.solo!
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_save
|
66
|
+
wrapper.expects(:config).with('--get-regexp git-duo').returns(git_config).at_least_once
|
67
|
+
wrapper.expects(:config).with("git-duo.email 'board+%names@gotham.travel'")
|
68
|
+
wrapper.expects(:config).with("git-duo.alfred 'Alfred Pennyworth <alfred@gotham.travel>'")
|
69
|
+
wrapper.expects(:config).with("git-duo.bruce 'Bruce Wayne <bruce@gotham.travel>'")
|
70
|
+
|
71
|
+
repo.save
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_save_doesnt_save_email_if_nil
|
75
|
+
wrapper.expects(:config).with('--get-regexp git-duo').returns(git_config).at_least_once
|
76
|
+
wrapper.expects(:config).with("git-duo.alfred 'Alfred Pennyworth <alfred@gotham.travel>'")
|
77
|
+
wrapper.expects(:config).with("git-duo.bruce 'Bruce Wayne <bruce@gotham.travel>'")
|
78
|
+
|
79
|
+
repo.email = nil
|
80
|
+
repo.save
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_save_doesnt_save_authors_if_empty
|
84
|
+
wrapper.expects(:config).with('--get-regexp git-duo').returns(git_config).at_least_once
|
85
|
+
wrapper.expects(:config).with("git-duo.email 'board+%names@gotham.travel'")
|
86
|
+
|
87
|
+
repo.authors = []
|
88
|
+
repo.save
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require "mocha/setup"
|
3
|
+
|
4
|
+
$:<< File.dirname(__FILE__) + "/../lib"
|
5
|
+
require 'git/duo'
|
6
|
+
|
7
|
+
def alfred_and_bruce
|
8
|
+
[
|
9
|
+
Git::Duo::Author.import('bruce Bruce Wayne <bruce@gotham.travel>'),
|
10
|
+
Git::Duo::Author.import('alfred Alfred Pennyworth <alfred@gotham.travel>')
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
def alfred_and_bruce_rachel
|
15
|
+
alfred_and_bruce << Git::Duo::Author.import('rachel Rachel Dawes <rachel@gotham.travel>')
|
16
|
+
end
|
17
|
+
|
18
|
+
def bruce_and_edward
|
19
|
+
[
|
20
|
+
Git::Duo::Author.import('bruce Bruce Wayne <bruce@gotham.travel>'),
|
21
|
+
Git::Duo::Author.import('riddler Edward Nigma <riddler@guess.com>')
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
def jim_and_harvey
|
26
|
+
[
|
27
|
+
Git::Duo::Author.import('jim Jim Gordon <jim@gotham.travel>'),
|
28
|
+
Git::Duo::Author.import('harvey Harvey Dent <harvey@gotham.travel>')
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
class DummyWrapper < Struct.new(:directory)
|
33
|
+
def config(*)
|
34
|
+
git_config
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def git_config
|
39
|
+
[
|
40
|
+
'git-duo.bruce Bruce Wayne <bruce@gotham.travel>',
|
41
|
+
'git-duo.alfred Alfred Pennyworth <alfred@gotham.travel>',
|
42
|
+
'git-duo.email board+%names@gotham.travel'
|
43
|
+
]
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-duo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Teo Ljungberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: A git porcelain for duo programming. Changes git-config's user.name and
|
84
|
+
user.email settings so you can commit as more than one author.
|
85
|
+
email:
|
86
|
+
- teo.ljungberg@gmail.com
|
87
|
+
executables:
|
88
|
+
- git-duo
|
89
|
+
- git-solo
|
90
|
+
extensions: []
|
91
|
+
extra_rdoc_files: []
|
92
|
+
files:
|
93
|
+
- .autotest
|
94
|
+
- .gitignore
|
95
|
+
- .travis.yml
|
96
|
+
- Gemfile
|
97
|
+
- LICENSE.txt
|
98
|
+
- README.md
|
99
|
+
- Rakefile
|
100
|
+
- bin/git-duo
|
101
|
+
- bin/git-solo
|
102
|
+
- git-duo.gemspec
|
103
|
+
- lib/git/duo.rb
|
104
|
+
- lib/git/duo/author.rb
|
105
|
+
- lib/git/duo/author_collection.rb
|
106
|
+
- lib/git/duo/cli.rb
|
107
|
+
- lib/git/duo/exceptions.rb
|
108
|
+
- lib/git/duo/pair.rb
|
109
|
+
- lib/git/duo/repo.rb
|
110
|
+
- lib/git/duo/version.rb
|
111
|
+
- lib/git/duo/wrapper.rb
|
112
|
+
- test/git/duo/author_collection_test.rb
|
113
|
+
- test/git/duo/author_test.rb
|
114
|
+
- test/git/duo/pair_test.rb
|
115
|
+
- test/git/duo/repo_test.rb
|
116
|
+
- test/test_helper.rb
|
117
|
+
homepage: https://github.com/teoljungberg/git-duo
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata: {}
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 2.1.11
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Git pairing made easy
|
141
|
+
test_files:
|
142
|
+
- test/git/duo/author_collection_test.rb
|
143
|
+
- test/git/duo/author_test.rb
|
144
|
+
- test/git/duo/pair_test.rb
|
145
|
+
- test/git/duo/repo_test.rb
|
146
|
+
- test/test_helper.rb
|