git-duet 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|