git-duet 0.4.0 → 0.4.1
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 +4 -4
- data/.travis.yml +6 -0
- data/README.md +3 -4
- data/git-duet.gemspec +8 -8
- data/lib/git/duet/author_mapper.rb +3 -3
- data/lib/git/duet/cli.rb +2 -2
- data/lib/git/duet/command_methods.rb +1 -1
- data/lib/git/duet/version.rb +1 -1
- data/spec/lib/git/duet/duet_command_spec.rb +1 -1
- data/test/git-duet-commit.bats +71 -0
- data/test/git-duet-install-hooks.bats +15 -0
- data/test/git-duet.bats +63 -0
- data/test/git-solo.bats +45 -0
- data/test/test_helper.bash +122 -0
- metadata +7 -6
- data/bin/git-dci +0 -4
- data/spec/integration/end_to_end_spec.rb +0 -376
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c0d1aba2d97cec79a441df782543cd66f943074
|
4
|
+
data.tar.gz: bde7359043a472e8971bb22c8310d60e94b99687
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60244f94949de3e18600cb59358128ccea448e87f96468fd4a3677d0e2cc42ce4add71309f7a008ef4b523da340fa95ca662f6ad8ee4a36f4291aa267ce67aa3
|
7
|
+
data.tar.gz: ff54e2644dcf6d61c00a382ddc99c821ef7c15b1a8d419da3e02879b5bbc47a36dc1bf0a063af30fa305a9fe26681e538e6f5c1d6a44168224a173842b5a7a52
|
data/.travis.yml
CHANGED
@@ -10,6 +10,12 @@ rvm:
|
|
10
10
|
- 2.0.0
|
11
11
|
- 2.1.0
|
12
12
|
- jruby-19mode
|
13
|
+
before_script:
|
14
|
+
- git clone https://github.com/sstephenson/bats.git
|
15
|
+
- cd bats && sudo ./install.sh /usr/local
|
16
|
+
script:
|
17
|
+
- bundle exec rake
|
18
|
+
- bats test
|
13
19
|
notifications:
|
14
20
|
email: github+git-duet@modcloth.com
|
15
21
|
deploy:
|
data/README.md
CHANGED
@@ -64,12 +64,11 @@ 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
|
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.)
|
68
69
|
|
69
70
|
~~~~~ bash
|
70
71
|
git duet-commit -v [any other git options]
|
71
|
-
# or...
|
72
|
-
git dci -v [any other git options]
|
73
72
|
~~~~~
|
74
73
|
|
75
74
|
When you're done pairing, set the author back to yourself with `git solo`:
|
@@ -266,6 +265,6 @@ github](https://github.com/modcloth/git-duet/issues/new).
|
|
266
265
|
|
267
266
|
1. Fork it
|
268
267
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
269
|
-
3. Commit your changes (`git
|
268
|
+
3. Commit your changes (`git dci -am 'Added some feature'`)
|
270
269
|
4. Push to the branch (`git push origin my-new-feature`)
|
271
270
|
5. Create new Pull Request
|
data/git-duet.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
'Dan Buch',
|
7
7
|
'Jesse Szwedko',
|
8
8
|
'Rafe Colton',
|
9
|
-
'Sheena McCoy'
|
9
|
+
'Sheena McCoy'
|
10
10
|
]
|
11
11
|
gem.email = %w(
|
12
12
|
d.buch@modcloth.com
|
@@ -14,16 +14,16 @@ Gem::Specification.new do |gem|
|
|
14
14
|
r.colton@modcloth.com
|
15
15
|
sp.mccoy@modcloth.com
|
16
16
|
)
|
17
|
-
gem.description = %q
|
18
|
-
gem.summary = "Pair harmoniously! Decide who's driving. "
|
19
|
-
"Commit along the way. Don't make a mess of "
|
20
|
-
|
17
|
+
gem.description = %q(Pair programming git identity thingy)
|
18
|
+
gem.summary = "Pair harmoniously! Decide who's driving. " \
|
19
|
+
"Commit along the way. Don't make a mess of " \
|
20
|
+
'the repository history.'
|
21
21
|
gem.homepage = 'https://github.com/modcloth/git-duet'
|
22
22
|
gem.license = 'MIT'
|
23
23
|
|
24
|
-
gem.files = `git ls-files`.split(
|
25
|
-
gem.executables = gem.files.grep(
|
26
|
-
gem.test_files = gem.files.grep(
|
24
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
25
|
+
gem.executables = gem.files.grep(/^bin\//).map { |f| File.basename(f) }
|
26
|
+
gem.test_files = gem.files.grep(/^spec\//)
|
27
27
|
gem.name = 'git-duet'
|
28
28
|
gem.require_paths = %w(lib)
|
29
29
|
gem.version = Git::Duet::VERSION
|
@@ -38,9 +38,7 @@ module Git
|
|
38
38
|
author_email = email_from_lookup(initials, author, username)
|
39
39
|
return author_email unless author_email.empty?
|
40
40
|
return email_addresses[initials] if email_addresses[initials]
|
41
|
-
if email_template
|
42
|
-
return email_from_template(initials, author, username)
|
43
|
-
end
|
41
|
+
return email_from_template(initials, author, username) if email_template
|
44
42
|
return "#{username}@#{email_domain}" if username
|
45
43
|
|
46
44
|
author_name_parts = author.split
|
@@ -53,6 +51,8 @@ module Git
|
|
53
51
|
`#{@email_lookup} '#{initials}' '#{author}' '#{username}'`.strip
|
54
52
|
end
|
55
53
|
|
54
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
55
|
+
# arguments are used via binding
|
56
56
|
def email_from_template(initials, author, username)
|
57
57
|
return ERB.new(email_template).result(binding)
|
58
58
|
rescue StandardError => e
|
data/lib/git/duet/cli.rb
CHANGED
@@ -33,7 +33,7 @@ module Git
|
|
33
33
|
options = {}
|
34
34
|
leftover_argv = OptionParser.new do |opts|
|
35
35
|
opts.banner = banner.gsub(/__PROG__/, opts.program_name)
|
36
|
-
opts.on('-q', 'Silence output') do |
|
36
|
+
opts.on('-q', 'Silence output') do |_|
|
37
37
|
options[:quiet] = true
|
38
38
|
end
|
39
39
|
yield opts, options if block_given?
|
@@ -61,7 +61,7 @@ module Git
|
|
61
61
|
leftover_argv, options = with_common_opts(
|
62
62
|
argv, 'Usage: __PROG__ [options] ' << usage
|
63
63
|
) do |opts, options_hash|
|
64
|
-
opts.on('-g', '--global', 'Change global git config') do |
|
64
|
+
opts.on('-g', '--global', 'Change global git config') do |_|
|
65
65
|
options_hash[:global] = true
|
66
66
|
end
|
67
67
|
end
|
data/lib/git/duet/version.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
load test_helper
|
4
|
+
|
5
|
+
@test "lists the alpha of the duet as author in the log" {
|
6
|
+
git duet -q jd fb
|
7
|
+
add_file
|
8
|
+
git duet-commit -q -m 'Testing set of alpha as author'
|
9
|
+
run git log -1 --format='%an <%ae>'
|
10
|
+
assert_success 'Jane Doe <jane@hamsters.biz.local>'
|
11
|
+
}
|
12
|
+
|
13
|
+
@test "lists the omega of the duet as committer in the log" {
|
14
|
+
git duet -q jd fb
|
15
|
+
add_file
|
16
|
+
git duet-commit -q -m 'Testing set of omega as committer'
|
17
|
+
run git log -1 --format='%cn <%ce>'
|
18
|
+
assert_success 'Frances Bar <f.bar@hamster.info.local>'
|
19
|
+
}
|
20
|
+
|
21
|
+
@test "lists the soloist as author in the log" {
|
22
|
+
git solo -q jd
|
23
|
+
add_file
|
24
|
+
git duet-commit -q -m 'Testing set of soloist as author'
|
25
|
+
run git log -1 --format='%an <%ae>'
|
26
|
+
assert_success 'Jane Doe <jane@hamsters.biz.local>'
|
27
|
+
}
|
28
|
+
|
29
|
+
@test "lists the soloist as committer in the log" {
|
30
|
+
git solo -q jd
|
31
|
+
add_file
|
32
|
+
git duet-commit -q -m 'Testing set of soloist as committer'
|
33
|
+
run git log -1 --format='%cn <%ce>'
|
34
|
+
assert_success 'Jane Doe <jane@hamsters.biz.local>'
|
35
|
+
}
|
36
|
+
|
37
|
+
@test "does not inclued Signed-off-by whene soloing" {
|
38
|
+
git solo -q jd
|
39
|
+
add_file
|
40
|
+
git duet-commit -q -m 'Testing omitting signoff'
|
41
|
+
run grep 'Signed-off-by' .git/COMMIT_EDITMSG
|
42
|
+
assert_failure ''
|
43
|
+
}
|
44
|
+
|
45
|
+
@test "rejects commits with no author" {
|
46
|
+
add_file
|
47
|
+
run git duet-commit -q -m 'Testing commit with no author'
|
48
|
+
assert_failure
|
49
|
+
}
|
50
|
+
|
51
|
+
@test "rejects commits with stale soloists with hook" {
|
52
|
+
git solo -q jd
|
53
|
+
git duet-install-hook -q
|
54
|
+
git config --unset-all "$GIT_DUET_CONFIG_NAMESPACE.mtime"
|
55
|
+
add_file
|
56
|
+
run git duet-commit -q -m 'Testing stale hook fire'
|
57
|
+
|
58
|
+
assert_failure
|
59
|
+
assert_line 0 "Your git duet settings are stale, human!"
|
60
|
+
}
|
61
|
+
|
62
|
+
@test "rejects commits with stale duetists with hook" {
|
63
|
+
git duet -q jd fb
|
64
|
+
git duet-install-hook -q
|
65
|
+
git config --unset-all "$GIT_DUET_CONFIG_NAMESPACE.mtime"
|
66
|
+
add_file
|
67
|
+
run git duet-commit -q -m 'Testing stale hook fire'
|
68
|
+
|
69
|
+
assert_failure
|
70
|
+
assert_line 0 "Your git duet settings are stale, human!"
|
71
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
load test_helper
|
4
|
+
|
5
|
+
@test "writes the hook to the pre-commit hook file" {
|
6
|
+
git duet-install-hook -q
|
7
|
+
assert_success
|
8
|
+
[ -f .git/hooks/pre-commit ]
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "makes the pre-commit hook executable" {
|
12
|
+
git duet-install-hook -q
|
13
|
+
assert_success
|
14
|
+
[ -x .git/hooks/pre-commit ]
|
15
|
+
}
|
data/test/git-duet.bats
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
load test_helper
|
4
|
+
|
5
|
+
@test "sets the git user name" {
|
6
|
+
git duet -q jd fb
|
7
|
+
run git config user.name
|
8
|
+
assert_success 'Jane Doe'
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "sets the git user email" {
|
12
|
+
git duet -q jd fb
|
13
|
+
run git config user.email
|
14
|
+
assert_success 'jane@hamsters.biz.local'
|
15
|
+
}
|
16
|
+
|
17
|
+
@test "caches the git committer name" {
|
18
|
+
git duet -q jd fb
|
19
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-committer-name"
|
20
|
+
assert_success 'Frances Bar'
|
21
|
+
}
|
22
|
+
|
23
|
+
@test "caches the git committer email" {
|
24
|
+
git duet -q jd fb
|
25
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-committer-email"
|
26
|
+
assert_success 'f.bar@hamster.info.local'
|
27
|
+
}
|
28
|
+
|
29
|
+
@test "looks up external author email" {
|
30
|
+
GIT_DUET_EMAIL_LOOKUP_COMMAND=$GIT_DUET_TEST_LOOKUP git duet -q jd fb
|
31
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-email"
|
32
|
+
assert_success 'jane_doe@lookie.me.local'
|
33
|
+
}
|
34
|
+
|
35
|
+
@test "looks up external committer email" {
|
36
|
+
GIT_DUET_EMAIL_LOOKUP_COMMAND=$GIT_DUET_TEST_LOOKUP git duet -q jd fb
|
37
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-committer-email"
|
38
|
+
assert_success 'fb9000@dalek.info.local'
|
39
|
+
}
|
40
|
+
|
41
|
+
@test "uses custom email template for author when provided" {
|
42
|
+
local suffix=$RANDOM
|
43
|
+
|
44
|
+
set_custom_email_template "<%= \"#{author.split.first.downcase}#{author.split.last[0].chr.downcase}$suffix@mompopshop.local\" %>"
|
45
|
+
|
46
|
+
git duet zp fb
|
47
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-email"
|
48
|
+
assert_success "zubazp$suffix@mompopshop.local"
|
49
|
+
|
50
|
+
clear_custom_email_template
|
51
|
+
}
|
52
|
+
|
53
|
+
@test "uses custom email template for committer when provided" {
|
54
|
+
local suffix=$RANDOM
|
55
|
+
|
56
|
+
set_custom_email_template "<%= \"#{author.split.first.downcase}#{author.split.last[0].chr.downcase}$suffix@mompopshop.local\" %>"
|
57
|
+
|
58
|
+
git duet -q jd fb
|
59
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-committer-email"
|
60
|
+
assert_success "francesb$suffix@mompopshop.local"
|
61
|
+
|
62
|
+
clear_custom_email_template
|
63
|
+
}
|
data/test/git-solo.bats
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
load test_helper
|
4
|
+
|
5
|
+
@test "sets the git user name" {
|
6
|
+
git solo -q jd
|
7
|
+
run git config user.name
|
8
|
+
assert_success 'Jane Doe'
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "sets the git user email" {
|
12
|
+
git solo jd
|
13
|
+
run git config user.email
|
14
|
+
assert_success 'jane@hamsters.biz.local'
|
15
|
+
}
|
16
|
+
|
17
|
+
@test "caches the git user name as author name" {
|
18
|
+
git solo -q jd
|
19
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-name"
|
20
|
+
assert_success 'Jane Doe'
|
21
|
+
}
|
22
|
+
|
23
|
+
@test "caches the git user email as author email" {
|
24
|
+
git solo -q jd
|
25
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-email"
|
26
|
+
assert_success 'jane@hamsters.biz.local'
|
27
|
+
}
|
28
|
+
|
29
|
+
@test "looks up external email" {
|
30
|
+
GIT_DUET_EMAIL_LOOKUP_COMMAND=$GIT_DUET_TEST_LOOKUP git solo -q jd
|
31
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-email"
|
32
|
+
assert_success 'jane_doe@lookie.me.local'
|
33
|
+
}
|
34
|
+
|
35
|
+
@test "uses custom email template when provided" {
|
36
|
+
local suffix=$RANDOM
|
37
|
+
|
38
|
+
set_custom_email_template "<%= \"#{author.split.first.downcase}#{author.split.last[0].chr.downcase}$suffix@mompopshop.local\" %>"
|
39
|
+
|
40
|
+
git solo -q zp
|
41
|
+
run git config "$GIT_DUET_CONFIG_NAMESPACE.git-author-email"
|
42
|
+
assert_success "zubazp$suffix@mompopshop.local"
|
43
|
+
|
44
|
+
clear_custom_email_template
|
45
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
setup() {
|
2
|
+
GIT_DUET_TEST_DIR="${BATS_TMPDIR}/git-duet"
|
3
|
+
|
4
|
+
mkdir "$GIT_DUET_TEST_DIR"
|
5
|
+
|
6
|
+
export GIT_DUET_CONFIG_NAMESPACE='foo.bar'
|
7
|
+
export GIT_DUET_AUTHORS_FILE="${GIT_DUET_TEST_DIR}/.git-authors"
|
8
|
+
export GIT_DUET_TEST_LOOKUP="${GIT_DUET_TEST_DIR}/email-lookup"
|
9
|
+
export GIT_DUET_TEST_REPO="${GIT_DUET_TEST_DIR}/repo"
|
10
|
+
|
11
|
+
cat > "$GIT_DUET_AUTHORS_FILE" <<EOF
|
12
|
+
pairs:
|
13
|
+
jd: Jane Doe
|
14
|
+
fb: Frances Bar
|
15
|
+
zp: Zubaz Pants
|
16
|
+
|
17
|
+
email:
|
18
|
+
domain: hamster.info.local
|
19
|
+
|
20
|
+
email_addresses:
|
21
|
+
jd: jane@hamsters.biz.local
|
22
|
+
EOF
|
23
|
+
|
24
|
+
cat > "$GIT_DUET_TEST_LOOKUP" <<EOF
|
25
|
+
#!/usr/bin/env ruby
|
26
|
+
addr = {
|
27
|
+
'jd' => 'jane_doe@lookie.me.local',
|
28
|
+
'fb' => 'fb9000@dalek.info.local'
|
29
|
+
}[ARGV.first]
|
30
|
+
puts addr
|
31
|
+
EOF
|
32
|
+
chmod +x "$GIT_DUET_TEST_LOOKUP"
|
33
|
+
git init -q "$GIT_DUET_TEST_REPO"
|
34
|
+
cd "$GIT_DUET_TEST_REPO"
|
35
|
+
}
|
36
|
+
|
37
|
+
teardown() {
|
38
|
+
rm -rf "$GIT_DUET_TEST_DIR"
|
39
|
+
}
|
40
|
+
|
41
|
+
add_file() {
|
42
|
+
touch file.txt
|
43
|
+
git add file.txt
|
44
|
+
}
|
45
|
+
|
46
|
+
set_custom_email_template() {
|
47
|
+
clear_custom_email_template
|
48
|
+
echo "email_template: $1" >> "$GIT_DUET_AUTHORS_FILE"
|
49
|
+
}
|
50
|
+
|
51
|
+
clear_custom_email_template() {
|
52
|
+
cat "$GIT_DUET_AUTHORS_FILE" | grep -v email_template > "$GIT_DUET_AUTHORS_FILE.bak"
|
53
|
+
mv "$GIT_DUET_AUTHORS_FILE.bak" "$GIT_DUET_AUTHORS_FILE"
|
54
|
+
}
|
55
|
+
|
56
|
+
flunk() {
|
57
|
+
{ if [ "$#" -eq 0 ]; then cat -
|
58
|
+
else echo "$@"
|
59
|
+
fi
|
60
|
+
} >&2
|
61
|
+
return 1
|
62
|
+
}
|
63
|
+
|
64
|
+
assert_success() {
|
65
|
+
if [ "$status" -ne 0 ]; then
|
66
|
+
flunk "command failed with exit status $status"
|
67
|
+
elif [ "$#" -gt 0 ]; then
|
68
|
+
assert_output "$1"
|
69
|
+
fi
|
70
|
+
}
|
71
|
+
|
72
|
+
assert_failure() {
|
73
|
+
if [ "$status" -eq 0 ]; then
|
74
|
+
flunk "expected failed exit status"
|
75
|
+
elif [ "$#" -gt 0 ]; then
|
76
|
+
assert_output "$1"
|
77
|
+
fi
|
78
|
+
}
|
79
|
+
|
80
|
+
assert_equal() {
|
81
|
+
if [ "$1" != "$2" ]; then
|
82
|
+
{ echo "expected: $1"
|
83
|
+
echo "actual: $2"
|
84
|
+
} | flunk
|
85
|
+
fi
|
86
|
+
}
|
87
|
+
|
88
|
+
assert_output() {
|
89
|
+
local expected
|
90
|
+
if [ $# -eq 0 ]; then expected="$(cat -)"
|
91
|
+
else expected="$1"
|
92
|
+
fi
|
93
|
+
assert_equal "$expected" "$output"
|
94
|
+
}
|
95
|
+
|
96
|
+
assert_line() {
|
97
|
+
if [ "$1" -ge 0 ] 2>/dev/null; then
|
98
|
+
assert_equal "$2" "${lines[$1]}"
|
99
|
+
else
|
100
|
+
local line
|
101
|
+
for line in "${lines[@]}"; do
|
102
|
+
if [ "$line" = "$1" ]; then return 0; fi
|
103
|
+
done
|
104
|
+
flunk "expected line \`$1'"
|
105
|
+
fi
|
106
|
+
}
|
107
|
+
|
108
|
+
refute_line() {
|
109
|
+
if [ "$1" -ge 0 ] 2>/dev/null; then
|
110
|
+
local num_lines="${#lines[@]}"
|
111
|
+
if [ "$1" -lt "$num_lines" ]; then
|
112
|
+
flunk "output has $num_lines lines"
|
113
|
+
fi
|
114
|
+
else
|
115
|
+
local line
|
116
|
+
for line in "${lines[@]}"; do
|
117
|
+
if [ "$line" = "$1" ]; then
|
118
|
+
flunk "expected to not find line \`$line'"
|
119
|
+
fi
|
120
|
+
done
|
121
|
+
fi
|
122
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-duet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Buch
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-
|
14
|
+
date: 2014-06-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rake
|
@@ -104,7 +104,6 @@ email:
|
|
104
104
|
- r.colton@modcloth.com
|
105
105
|
- sp.mccoy@modcloth.com
|
106
106
|
executables:
|
107
|
-
- git-dci
|
108
107
|
- git-duet
|
109
108
|
- git-duet-commit
|
110
109
|
- git-duet-install-hook
|
@@ -124,7 +123,6 @@ files:
|
|
124
123
|
- LICENSE
|
125
124
|
- README.md
|
126
125
|
- Rakefile
|
127
|
-
- bin/git-dci
|
128
126
|
- bin/git-duet
|
129
127
|
- bin/git-duet-commit
|
130
128
|
- bin/git-duet-install-hook
|
@@ -144,7 +142,6 @@ files:
|
|
144
142
|
- lib/git/duet/script_die_error.rb
|
145
143
|
- lib/git/duet/solo_command.rb
|
146
144
|
- lib/git/duet/version.rb
|
147
|
-
- spec/integration/end_to_end_spec.rb
|
148
145
|
- spec/lib/git/duet/author_mapper_spec.rb
|
149
146
|
- spec/lib/git/duet/cli_spec.rb
|
150
147
|
- spec/lib/git/duet/command_methods_spec.rb
|
@@ -153,6 +150,11 @@ files:
|
|
153
150
|
- spec/lib/git/duet/solo_command_spec.rb
|
154
151
|
- spec/spec_helper.rb
|
155
152
|
- spec/support/author_mapper_helper.rb
|
153
|
+
- test/git-duet-commit.bats
|
154
|
+
- test/git-duet-install-hooks.bats
|
155
|
+
- test/git-duet.bats
|
156
|
+
- test/git-solo.bats
|
157
|
+
- test/test_helper.bash
|
156
158
|
homepage: https://github.com/modcloth/git-duet
|
157
159
|
licenses:
|
158
160
|
- MIT
|
@@ -179,7 +181,6 @@ specification_version: 4
|
|
179
181
|
summary: Pair harmoniously! Decide who's driving. Commit along the way. Don't make
|
180
182
|
a mess of the repository history.
|
181
183
|
test_files:
|
182
|
-
- spec/integration/end_to_end_spec.rb
|
183
184
|
- spec/lib/git/duet/author_mapper_spec.rb
|
184
185
|
- spec/lib/git/duet/cli_spec.rb
|
185
186
|
- spec/lib/git/duet/command_methods_spec.rb
|
data/bin/git-dci
DELETED
@@ -1,376 +0,0 @@
|
|
1
|
-
# vim:fileencoding=utf-8
|
2
|
-
require 'tmpdir'
|
3
|
-
require 'posix-spawn' unless RUBY_PLATFORM == 'java'
|
4
|
-
|
5
|
-
describe 'git-duet end to end', integration: true do
|
6
|
-
EMAIL_LOOKUP_SCRIPT = <<-EOF.gsub(/^ /, '')
|
7
|
-
#!/usr/bin/env ruby
|
8
|
-
addr = {
|
9
|
-
'jd' => 'jane_doe@lookie.me.local',
|
10
|
-
'fb' => 'fb9000@dalek.info.local'
|
11
|
-
}[ARGV.first]
|
12
|
-
puts addr
|
13
|
-
EOF
|
14
|
-
|
15
|
-
@capture_status = nil
|
16
|
-
|
17
|
-
def sh(cmd)
|
18
|
-
return `#{cmd}` if RUBY_PLATFORM == 'java'
|
19
|
-
|
20
|
-
pid, input, output, _ = POSIX::Spawn.popen4(cmd, err: '/dev/null')
|
21
|
-
input.close
|
22
|
-
@capture_status = Process.waitpid2(pid).last
|
23
|
-
output.read
|
24
|
-
ensure
|
25
|
-
output.close
|
26
|
-
end
|
27
|
-
|
28
|
-
def install_hook
|
29
|
-
Dir.chdir(@repo_dir) do
|
30
|
-
sh('git duet-install-hook -q')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def uninstall_hook
|
35
|
-
Dir.chdir(@repo_dir) do
|
36
|
-
FileUtils.rm_f('.git/hooks/pre-commit')
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def make_an_edit
|
41
|
-
Dir.chdir(@repo_dir) do
|
42
|
-
File.open('file.txt', 'w') { |f| f.puts "foo-#{rand(100_000)}" }
|
43
|
-
sh('git add file.txt')
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
before :all do
|
48
|
-
ENV['GIT_DUET_CONFIG_NAMESPACE'] = 'foo.bar'
|
49
|
-
|
50
|
-
@startdir = Dir.pwd
|
51
|
-
@tmpdir = Dir.mktmpdir('git-duet-specs')
|
52
|
-
@git_authors = File.join(@tmpdir, '.git-authors')
|
53
|
-
@email_lookup_path = File.join(@tmpdir, 'email-lookup')
|
54
|
-
|
55
|
-
File.open(@git_authors, 'w') do |f|
|
56
|
-
f.puts YAML.dump(
|
57
|
-
'pairs' => {
|
58
|
-
'jd' => 'Jane Doe',
|
59
|
-
'fb' => 'Frances Bar',
|
60
|
-
'zp' => 'Zubaz Pants'
|
61
|
-
},
|
62
|
-
'email' => {
|
63
|
-
'domain' => 'hamster.info.local'
|
64
|
-
},
|
65
|
-
'email_addresses' => {
|
66
|
-
'jd' => 'jane@hamsters.biz.local'
|
67
|
-
}
|
68
|
-
)
|
69
|
-
end
|
70
|
-
ENV['GIT_DUET_AUTHORS_FILE'] = @git_authors
|
71
|
-
|
72
|
-
top_bin = File.expand_path('../../../bin', __FILE__)
|
73
|
-
ENV['PATH'] = "#{top_bin}:#{ENV['PATH']}"
|
74
|
-
|
75
|
-
File.open(@email_lookup_path, 'w') { |f| f.puts EMAIL_LOOKUP_SCRIPT }
|
76
|
-
FileUtils.chmod(0755, @email_lookup_path)
|
77
|
-
|
78
|
-
@repo_dir = File.join(@tmpdir, 'foo')
|
79
|
-
Dir.chdir(@tmpdir) do
|
80
|
-
sh("git init #{@repo_dir}")
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
after :all do
|
85
|
-
Dir.chdir(@startdir)
|
86
|
-
if ENV['RSPEC_NO_CLEANUP']
|
87
|
-
File.open('integration-end-to-end-test-dir.txt', 'w') do |f|
|
88
|
-
f.puts @tmpdir
|
89
|
-
end
|
90
|
-
else
|
91
|
-
FileUtils.rm_rf(@tmpdir)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context 'when installing the pre-commit hook' do
|
96
|
-
before(:each) do
|
97
|
-
Dir.chdir(@repo_dir)
|
98
|
-
install_hook
|
99
|
-
end
|
100
|
-
|
101
|
-
after(:each) { uninstall_hook }
|
102
|
-
|
103
|
-
it 'writes the hook to the `pre-commit` hook file' do
|
104
|
-
File.exist?('.git/hooks/pre-commit').should be_true
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'makes the `pre-commit` hook file executable' do
|
108
|
-
File.executable?('.git/hooks/pre-commit').should be_true
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'when setting the author via solo' do
|
113
|
-
before :each do
|
114
|
-
Dir.chdir(@repo_dir)
|
115
|
-
sh('git solo jd -q')
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'sets the git user name' do
|
119
|
-
sh('git config user.name').chomp.should == 'Jane Doe'
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'sets the git user email' do
|
123
|
-
sh('git config user.email').chomp.should == 'jane@hamsters.biz.local'
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'caches the git user name as author name' do
|
127
|
-
sh("git config #{Git::Duet::Config.namespace}.git-author-name").chomp
|
128
|
-
.should == 'Jane Doe'
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'caches the git user email as author email' do
|
132
|
-
sh("git config #{Git::Duet::Config.namespace}.git-author-email").chomp
|
133
|
-
.should == 'jane@hamsters.biz.local'
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'when an external email lookup is provided' do
|
138
|
-
before :each do
|
139
|
-
@old_email_lookup = ENV.delete('GIT_DUET_EMAIL_LOOKUP_COMMAND')
|
140
|
-
ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND'] = @email_lookup_path
|
141
|
-
end
|
142
|
-
|
143
|
-
after :each do
|
144
|
-
ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND'] = @old_email_lookup
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'when setting the author via solo' do
|
148
|
-
before :each do
|
149
|
-
Dir.chdir(@repo_dir)
|
150
|
-
sh('git solo jd -q')
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'sets the author email given by the external email lookup' do
|
154
|
-
sh("git config #{Git::Duet::Config.namespace}.git-author-email").chomp
|
155
|
-
.should == 'jane_doe@lookie.me.local'
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'when setting author and committer via duet' do
|
160
|
-
before :each do
|
161
|
-
Dir.chdir(@repo_dir)
|
162
|
-
sh('git duet jd fb -q')
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'sets the author email given by the external email lookup' do
|
166
|
-
sh("git config #{Git::Duet::Config.namespace}.git-author-email").chomp
|
167
|
-
.should == 'jane_doe@lookie.me.local'
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'sets the committer email given by the external email lookup' do
|
171
|
-
sh(
|
172
|
-
"git config #{Git::Duet::Config.namespace}.git-committer-email"
|
173
|
-
).chomp.should == 'fb9000@dalek.info.local'
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
context 'when a custom email template is provided' do
|
179
|
-
before :each do
|
180
|
-
authors_cfg = YAML.load_file(@git_authors)
|
181
|
-
@name_suffix = rand(9999)
|
182
|
-
authors_cfg['email_template'] =
|
183
|
-
"<%= '' << author.split.first.downcase << " \
|
184
|
-
"author.split.last[0].chr.downcase << " \
|
185
|
-
"'#{@name_suffix}@mompopshop.local' %>"
|
186
|
-
File.open(@git_authors, 'w') do |f|
|
187
|
-
f.puts YAML.dump(authors_cfg)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
after :each do
|
192
|
-
authors_cfg = YAML.load_file(@git_authors)
|
193
|
-
authors_cfg.delete('email_template')
|
194
|
-
File.open(@git_authors, 'w') do |f|
|
195
|
-
f.puts YAML.dump(authors_cfg)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
context 'after running git-solo' do
|
200
|
-
before :each do
|
201
|
-
Dir.chdir(@repo_dir)
|
202
|
-
sh('git solo zp -q')
|
203
|
-
make_an_edit
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'uses the email template to construct the author email' do
|
207
|
-
sh("git duet-commit -q -m 'Testing custom email template for author'")
|
208
|
-
sh("git log -1 --format='%an <%ae>'").chomp
|
209
|
-
.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'uses the email template to construct the committer email' do
|
213
|
-
sh('git duet-commit -q ' \
|
214
|
-
"-m 'Testing custom email template for committer'")
|
215
|
-
sh("git log -1 --format='%cn <%ce>'").chomp
|
216
|
-
.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
context 'after running git-duet' do
|
221
|
-
before :each do
|
222
|
-
Dir.chdir(@repo_dir)
|
223
|
-
sh('git duet zp fb -q')
|
224
|
-
make_an_edit
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'uses the email template to construct the author email' do
|
228
|
-
sh("git duet-commit -q -m 'Testing custom email template for author'")
|
229
|
-
sh("git log -1 --format='%an <%ae>'").chomp
|
230
|
-
.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'uses the email template to construct the committer email' do
|
234
|
-
sh('git duet-commit -q ' \
|
235
|
-
"-m 'Testing custom email template for committer'")
|
236
|
-
sh("git log -1 --format='%cn <%ce>'").chomp
|
237
|
-
.should == "Frances Bar <francesb#{@name_suffix}@mompopshop.local>"
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
context 'when setting author and committer via duet' do
|
243
|
-
before :each do
|
244
|
-
Dir.chdir(@repo_dir)
|
245
|
-
sh('git duet jd fb -q')
|
246
|
-
end
|
247
|
-
|
248
|
-
it 'sets the git user name' do
|
249
|
-
sh('git config user.name').chomp.should == 'Jane Doe'
|
250
|
-
end
|
251
|
-
|
252
|
-
it 'sets the git user email' do
|
253
|
-
sh('git config user.email').chomp.should == 'jane@hamsters.biz.local'
|
254
|
-
end
|
255
|
-
|
256
|
-
it 'caches the git committer name' do
|
257
|
-
sh("git config #{Git::Duet::Config.namespace}.git-committer-name").chomp
|
258
|
-
.should == 'Frances Bar'
|
259
|
-
end
|
260
|
-
|
261
|
-
it 'caches the git committer email' do
|
262
|
-
sh("git config #{Git::Duet::Config.namespace}.git-committer-email").chomp
|
263
|
-
.should == 'f.bar@hamster.info.local'
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
context 'when committing via git-duet-commit' do
|
268
|
-
context 'after running git-duet' do
|
269
|
-
before :each do
|
270
|
-
Dir.chdir(@repo_dir)
|
271
|
-
sh('git duet jd fb -q')
|
272
|
-
make_an_edit
|
273
|
-
end
|
274
|
-
|
275
|
-
it 'lists the alpha of the duet as author in the log' do
|
276
|
-
sh("git duet-commit -q -m 'Testing set of alpha as author'")
|
277
|
-
sh("git log -1 --format='%an <%ae>'").chomp
|
278
|
-
.should == 'Jane Doe <jane@hamsters.biz.local>'
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'lists the omega of the duet as committer in the log' do
|
282
|
-
sh("git duet-commit -q -m 'Testing set of omega as committer'")
|
283
|
-
sh("git log -1 --format='%cn <%ce>'").chomp
|
284
|
-
.should == 'Frances Bar <f.bar@hamster.info.local>'
|
285
|
-
end
|
286
|
-
|
287
|
-
context 'when no author has been set' do
|
288
|
-
before do
|
289
|
-
Dir.chdir(@repo_dir)
|
290
|
-
%w(git-author-email git-author-name).each do |config|
|
291
|
-
sh("git config --unset #{Git::Duet::Config.namespace}.#{config}")
|
292
|
-
end
|
293
|
-
make_an_edit
|
294
|
-
end
|
295
|
-
|
296
|
-
it 'raises an error if committed without the -q option' do
|
297
|
-
sh("git duet-commit -q -m 'Testing commit with no author'")
|
298
|
-
@capture_status.to_i.should_not == 0
|
299
|
-
end
|
300
|
-
|
301
|
-
it 'fails to add a commit' do
|
302
|
-
expect do
|
303
|
-
sh("git duet-commit -q -m 'testing commit with no author'")
|
304
|
-
end.to_not change { sh('git log -1 --format=%H').chomp }
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
context 'with the pre-commit hook in place' do
|
309
|
-
before :each do
|
310
|
-
sh("git commit -m 'Committing before installing the hook'")
|
311
|
-
@latest_sha1 = sh('git log -1 --format=%H').chomp
|
312
|
-
make_an_edit
|
313
|
-
install_hook
|
314
|
-
sh("git config --unset-all #{Git::Duet::Config.namespace}.mtime")
|
315
|
-
ENV['GIT_DUET_QUIET'] = '1'
|
316
|
-
end
|
317
|
-
|
318
|
-
after :each do
|
319
|
-
uninstall_hook
|
320
|
-
ENV.delete('GIT_DUET_QUIET')
|
321
|
-
end
|
322
|
-
|
323
|
-
it 'fires the hook and reject the commit' do
|
324
|
-
sh("git duet-commit -q -m 'Testing hook firing'")
|
325
|
-
sh('git log -1 --format=%H').chomp.should == @latest_sha1
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
context 'after running git-solo' do
|
331
|
-
before :each do
|
332
|
-
Dir.chdir(@repo_dir)
|
333
|
-
sh('git solo jd -q')
|
334
|
-
make_an_edit
|
335
|
-
end
|
336
|
-
|
337
|
-
it 'lists the soloist as author in the log' do
|
338
|
-
sh("git duet-commit -m 'Testing set of soloist as author'")
|
339
|
-
sh("git log -1 --format='%an <%ae>'").chomp
|
340
|
-
.should == 'Jane Doe <jane@hamsters.biz.local>'
|
341
|
-
end
|
342
|
-
|
343
|
-
it 'lists the soloist as committer in the log' do
|
344
|
-
sh("git duet-commit -m 'Testing set of soloist as committer'")
|
345
|
-
sh("git log -1 --format='%cn <%ce>'").chomp
|
346
|
-
.should == 'Jane Doe <jane@hamsters.biz.local>'
|
347
|
-
end
|
348
|
-
|
349
|
-
it 'does not include "Signed-off-by" in the commit message' do
|
350
|
-
sh("git duet-commit -m 'Testing omitting signoff'")
|
351
|
-
sh("grep 'Signed-off-by' .git/COMMIT_EDITMSG").chomp.should == ''
|
352
|
-
end
|
353
|
-
|
354
|
-
context 'with the pre-commit hook in place' do
|
355
|
-
before :each do
|
356
|
-
sh("git commit -m 'Committing before installing the hook'")
|
357
|
-
@latest_sha1 = sh('git log -1 --format=%H').chomp
|
358
|
-
make_an_edit
|
359
|
-
install_hook
|
360
|
-
sh("git config --unset-all #{Git::Duet::Config.namespace}.mtime")
|
361
|
-
ENV['GIT_DUET_QUIET'] = '1'
|
362
|
-
end
|
363
|
-
|
364
|
-
after :each do
|
365
|
-
uninstall_hook
|
366
|
-
ENV.delete('GIT_DUET_QUIET')
|
367
|
-
end
|
368
|
-
|
369
|
-
it 'fires the hook and reject the commit' do
|
370
|
-
sh("git duet-commit -q -m 'Testing hook firing'")
|
371
|
-
sh('git log -1 --format=%H').chomp.should == @latest_sha1
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
end
|