jiragit 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +112 -0
- data/Rakefile +18 -0
- data/bin/jiragit +5 -0
- data/hooks/commit-msg +90 -0
- data/hooks/post-checkout +107 -0
- data/hooks/post-commit +51 -0
- data/hooks/prepare-commit-msg +144 -0
- data/lib/jiragit.rb +10 -0
- data/lib/jiragit/cli.rb +249 -0
- data/lib/jiragit/configuration.rb +51 -0
- data/lib/jiragit/git/branch.rb +29 -0
- data/lib/jiragit/git/commit_response.rb +23 -0
- data/lib/jiragit/git/repository.rb +222 -0
- data/lib/jiragit/jira_store.rb +48 -0
- data/lib/jiragit/logger.rb +32 -0
- data/lib/jiragit/tag.rb +30 -0
- data/lib/jiragit/vault.rb +113 -0
- data/lib/jiragit/version.rb +3 -0
- data/spec/branch_spec.rb +105 -0
- data/spec/cli_context.rb +13 -0
- data/spec/cli_spec.rb +149 -0
- data/spec/commit_message_spec.rb +82 -0
- data/spec/commit_spec.rb +81 -0
- data/spec/configuration_spec.rb +32 -0
- data/spec/git_editor.rb +40 -0
- data/spec/git_editor_spec.rb +59 -0
- data/spec/jira_store_spec.rb +57 -0
- data/spec/logger_spec.rb +37 -0
- data/spec/merge_spec.rb +85 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tag_spec.rb +35 -0
- data/spec/test_repository_context.rb +17 -0
- data/spec/test_support.rb +81 -0
- data/spec/vault_spec.rb +100 -0
- metadata +124 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require 'expect'
|
3
|
+
|
4
|
+
describe "Commit message" do
|
5
|
+
|
6
|
+
include_context "Test Repository"
|
7
|
+
|
8
|
+
context "when making a commit" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@repo.make_a_command_line_commit
|
12
|
+
checkout_a_new_branch('new_branch', 'PA-12345')
|
13
|
+
@repo.create('a_file', 'The brown fox jumped over the fence')
|
14
|
+
@repo.add('a_file')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "must be properly formatted" do
|
18
|
+
message = <<-COMMIT
|
19
|
+
Capitalized, short (50 chars or less) summary
|
20
|
+
|
21
|
+
More detailed explanatory text, if necessary. Wrap it to about 72
|
22
|
+
characters or so. In some contexts, the first line is treated as the
|
23
|
+
subject of an email and the rest of the text as the body. The blank
|
24
|
+
line separating the summary from the body is critical (unless you omit
|
25
|
+
the body entirely); tools like rebase can get confused if you run the
|
26
|
+
two together.
|
27
|
+
COMMIT
|
28
|
+
|
29
|
+
@repo.commit(message) do |output, input|
|
30
|
+
output.expect("Commit rejected", 5) do |message|
|
31
|
+
expect(message).to be nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "must contain a title" do
|
37
|
+
message = ""
|
38
|
+
@repo.commit(message) do |output, input|
|
39
|
+
output.expect("The title of the commit message must be present", 5) do |message|
|
40
|
+
expect(message).to_not be nil
|
41
|
+
end
|
42
|
+
output.expect("Edit commit message? [yes]> ")
|
43
|
+
input.puts("no")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "the title must not be too long" do
|
48
|
+
message = "a"*51
|
49
|
+
@repo.commit(message) do |output, input|
|
50
|
+
output.expect("The title of the commit message must be no longer than 50 characters", 5) do |message|
|
51
|
+
expect(message).to_not be nil
|
52
|
+
end
|
53
|
+
output.expect("Edit commit message? [yes]> ")
|
54
|
+
input.puts("no")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "the body must be seperated by at least one new line from the title" do
|
59
|
+
message = "Line 1\nLine 2"
|
60
|
+
@repo.commit(message) do |output, input|
|
61
|
+
output.expect("The commit title and body must be separated by a single blank line", 5) do |message|
|
62
|
+
expect(message).to_not be nil
|
63
|
+
end
|
64
|
+
output.expect("Edit commit message? [yes]> ")
|
65
|
+
input.puts("no")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "the lines in the body must not be too long" do
|
70
|
+
message = "a"*20 + "\n\n" +"b"*73
|
71
|
+
@repo.commit(message) do |output, input|
|
72
|
+
output.expect("Lines in the body of the commit message must be no longer than 72 characters", 5) do |message|
|
73
|
+
expect(message).to_not be nil
|
74
|
+
end
|
75
|
+
output.expect("Edit commit message? [yes]> ")
|
76
|
+
input.puts("no")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/spec/commit_spec.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require 'expect'
|
3
|
+
|
4
|
+
describe "Repository Commit Behaviors" do
|
5
|
+
|
6
|
+
include_context "Test Repository"
|
7
|
+
|
8
|
+
context "when making a commit" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@repo.make_a_command_line_commit
|
12
|
+
checkout_a_new_branch('new_branch', 'PA-12345')
|
13
|
+
end
|
14
|
+
|
15
|
+
context "via editor" do
|
16
|
+
|
17
|
+
before do
|
18
|
+
@commit = @repo.make_a_commit
|
19
|
+
end
|
20
|
+
|
21
|
+
it "adds the related jira to the body of the commit message" do
|
22
|
+
@repo.log_for_one_commit(@commit.sha) do |output, input|
|
23
|
+
output.expect("PA-12345", 5) do |message|
|
24
|
+
expect(message).to_not be nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "contains the commit message on the first line" do
|
30
|
+
@repo.oneline_log_for_one_commit(@commit.sha) do |output, input|
|
31
|
+
output.expect("Short (50 chars or less) summary", 5) do |message|
|
32
|
+
expect(message).to_not be nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "relates the jira and the commit" do
|
38
|
+
assert_relation({jira: 'PA-12345'}, {commit: @repo.current_commit})
|
39
|
+
end
|
40
|
+
|
41
|
+
it "relates the branch and the commit" do
|
42
|
+
assert_relation({branch: 'new_branch'}, {commit: @repo.current_commit})
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "via command line" do
|
48
|
+
|
49
|
+
before do
|
50
|
+
@commit = @repo.make_a_command_line_commit
|
51
|
+
end
|
52
|
+
|
53
|
+
it "adds the related jira to the body of the commit message" do
|
54
|
+
@repo.log_for_one_commit(@commit.sha) do |output, input|
|
55
|
+
output.expect("PA-12345", 5) do |message|
|
56
|
+
expect(message).to_not be nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "contains the commit message on the first line" do
|
62
|
+
@repo.oneline_log_for_one_commit(@commit.sha) do |output, input|
|
63
|
+
output.expect("command line specified commit message", 5) do |message|
|
64
|
+
expect(message).to_not be nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "relates the jira and the commit" do
|
70
|
+
assert_relation({jira: 'PA-12345'}, {commit: @repo.current_commit})
|
71
|
+
end
|
72
|
+
|
73
|
+
it "relates the branch and the commit" do
|
74
|
+
assert_relation({branch: 'new_branch'}, {commit: @repo.current_commit})
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module Jiragit
|
4
|
+
|
5
|
+
describe Configuration do
|
6
|
+
|
7
|
+
let!(:config) { described_class.new('.testconfig') }
|
8
|
+
|
9
|
+
cleanup = ->(x) { File.delete('.testconfig') if File.exist?('.testconfig') }
|
10
|
+
before &cleanup
|
11
|
+
after &cleanup
|
12
|
+
|
13
|
+
it "should create a config file" do
|
14
|
+
config[:a] = 5
|
15
|
+
expect(File.exists?('.testconfig')).to be true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set keys" do
|
19
|
+
config[:a] = 5
|
20
|
+
expect(config[:a]).to eq(5)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should load keys" do
|
24
|
+
config[:a] = 5
|
25
|
+
|
26
|
+
new_config = described_class.new('.testconfig')
|
27
|
+
expect(new_config[:a]).to eq(5)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/git_editor.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This is a test double for entering a commit message via an editor
|
4
|
+
# It always enters the same commit message
|
5
|
+
|
6
|
+
def commit_message
|
7
|
+
File.read(ARGV[0])
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_commit_message(message)
|
11
|
+
File.write(ARGV[0], message)
|
12
|
+
end
|
13
|
+
|
14
|
+
def prepend_to_commit_message(line)
|
15
|
+
write_commit_message(line+commit_message)
|
16
|
+
end
|
17
|
+
|
18
|
+
def commit_body
|
19
|
+
if File.exist?('.git_commit_body')
|
20
|
+
File.read('.git_commit_body')
|
21
|
+
else
|
22
|
+
predefined_commit_body
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def predefined_commit_body
|
27
|
+
<<-BODY
|
28
|
+
Short (50 chars or less) summary of changes
|
29
|
+
|
30
|
+
More detailed explanatory text, if necessary. Wrap it to about 72
|
31
|
+
characters or so. In some contexts, the first line is treated as the
|
32
|
+
subject of an email and the rest of the text as the body. The blank
|
33
|
+
line separating the summary from the body is critical (unless you omit
|
34
|
+
the body entirely); tools like rebase can get confused if you run the
|
35
|
+
two together.
|
36
|
+
|
37
|
+
BODY
|
38
|
+
end
|
39
|
+
|
40
|
+
prepend_to_commit_message(commit_body)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
describe "Git Editor Double" do
|
2
|
+
|
3
|
+
context "when making a commit via an editor" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@commit_message_filename = '.git_commit_message'
|
7
|
+
@commit_body_filename = '.git_commit_body'
|
8
|
+
delete_commit_message
|
9
|
+
delete_commit_body
|
10
|
+
write_commit_message("#This is the git commit message prepared by git")
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
delete_commit_message
|
15
|
+
delete_commit_body
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should add a predefined body to the commit message" do
|
19
|
+
run_git_editor
|
20
|
+
expect(commit_message).to match(/summary of changes/)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should add a user defined body to the commit message" do
|
24
|
+
write_commit_body('this is a test body')
|
25
|
+
run_git_editor
|
26
|
+
expect(commit_message).to match(/this is a test body/)
|
27
|
+
end
|
28
|
+
|
29
|
+
def commit_message
|
30
|
+
File.read(@commit_message_filename)
|
31
|
+
end
|
32
|
+
|
33
|
+
def commit_body
|
34
|
+
File.read(@commit_body_filename)
|
35
|
+
end
|
36
|
+
|
37
|
+
def write_commit_message(message)
|
38
|
+
File.write(@commit_message_filename, message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_commit_message
|
42
|
+
File.delete(@commit_message_filename) if File.exist?(@commit_message_filename)
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_commit_body(body)
|
46
|
+
File.write(@commit_body_filename, body)
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_commit_body
|
50
|
+
File.delete(@commit_body_filename) if File.exists?(@commit_body_filename)
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_git_editor
|
54
|
+
`./spec/git_editor.rb #{@commit_message_filename}`
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module Jiragit
|
4
|
+
|
5
|
+
describe JiraStore do
|
6
|
+
|
7
|
+
subject {
|
8
|
+
File.delete('.testjirastore') if File.exists?('.testjirastore')
|
9
|
+
described_class.new('.testjirastore')
|
10
|
+
}
|
11
|
+
|
12
|
+
after do
|
13
|
+
File.delete('.testjirastore') if File.exists?('.testjirastore')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should initialize using the default location" do
|
17
|
+
expect(described_class.new).to be_a JiraStore
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should initialize using a custom location" do
|
21
|
+
expect(subject).to be_a JiraStore
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should relate a branch to a jira" do
|
25
|
+
subject.relate(jira: "PA-12345", branch: "my-feature-branch")
|
26
|
+
branch = subject.relations(jira: "PA-12345").first
|
27
|
+
expect(branch.label).to eq "my-feature-branch"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should automatically save changes" do
|
31
|
+
subject.relate(jira: "PA-12345", branch: "my-feature-branch")
|
32
|
+
store = described_class.new('.testjirastore')
|
33
|
+
branch = store.relations(jira: "PA-12345").first
|
34
|
+
expect(branch.label).to eq "my-feature-branch"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should relate multiple branches to a jira" do
|
38
|
+
subject.relate(jira: "PA-12345", branch: "my-feature-branch")
|
39
|
+
subject.relate(jira: "PA-12345", branch: "my-second-feature-branch")
|
40
|
+
branch = subject.relations(jira: "PA-12345")
|
41
|
+
expect(branch.size).to eq 2
|
42
|
+
expect(branch.to_a.first.label).to eq "my-feature-branch"
|
43
|
+
expect(branch.to_a.last.label).to eq "my-second-feature-branch"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should relate a branch and a commit to a jira" do
|
47
|
+
subject.relate(jira: "PA-12345", branch: "my-feature-branch")
|
48
|
+
subject.relate(jira: "PA-12345", commit: "3d0ff811d2e4e71ede49d3db7fac71f1f988627e")
|
49
|
+
relations = subject.relations(jira: "PA-12345")
|
50
|
+
expect(relations.size).to eq 2
|
51
|
+
expect(relations.map(&:label)).to include "my-feature-branch"
|
52
|
+
expect(relations.map(&:label)).to include "3d0ff811d2e4e71ede49d3db7fac71f1f988627e"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module Jiragit
|
4
|
+
|
5
|
+
describe Logger do
|
6
|
+
|
7
|
+
subject { Logger.new("test_log") }
|
8
|
+
|
9
|
+
after do
|
10
|
+
File.delete('test_log') if File.exists?('test_log')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialize" do
|
14
|
+
expect(subject).to be_a Logger
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create a log file" do
|
18
|
+
subject.info "Test"
|
19
|
+
expect(File.exists?('test_log')).to be true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should contain log entries" do
|
23
|
+
subject.info "Test"
|
24
|
+
contents = `cat test_log`
|
25
|
+
expect(contents).to match(/Test/)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should contain hooks names" do
|
29
|
+
subject.hook = "post-checkout"
|
30
|
+
subject.info "Test"
|
31
|
+
contents = `cat test_log`
|
32
|
+
expect(contents).to match(/post-checkout/)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/spec/merge_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require 'expect'
|
3
|
+
|
4
|
+
describe "Repository Merge Behaviors" do
|
5
|
+
|
6
|
+
include_context "Test Repository"
|
7
|
+
|
8
|
+
context "when merging a feature branch" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@repo.create('a_file', 'The quick fox jumped over the fence')
|
12
|
+
@repo.add('a_file')
|
13
|
+
@repo.commit('initial commit')
|
14
|
+
checkout_a_new_branch('feature_branch', 'PA-12345')
|
15
|
+
@repo.create('a_file', 'The brown fox jumped over the fence')
|
16
|
+
@repo.add('a_file')
|
17
|
+
@repo.commit('feature commit')
|
18
|
+
checkout_a_new_branch('another_feature_branch', 'PA-54321')
|
19
|
+
@repo.create('c_file', 'The frog went for a swim')
|
20
|
+
@repo.add('c_file')
|
21
|
+
@repo.commit('another feature commit')
|
22
|
+
checkout_an_existing_branch('master')
|
23
|
+
@repo.create('b_file', 'The cow walked to the lake')
|
24
|
+
@repo.add('b_file')
|
25
|
+
@repo.commit('hotpatch commit')
|
26
|
+
checkout_an_existing_branch('feature_branch')
|
27
|
+
@repo.create('d_file', 'The crow flew for a while')
|
28
|
+
@repo.add('d_file')
|
29
|
+
@repo.commit('feature commit number two')
|
30
|
+
end
|
31
|
+
|
32
|
+
context "into the master branch without conflicts" do
|
33
|
+
|
34
|
+
it "should not relate the jira" do
|
35
|
+
checkout_an_existing_branch('master')
|
36
|
+
@repo.merge('feature_branch')
|
37
|
+
assert_no_relation({jira: 'PA-12345'}, {branch: 'master'})
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should add the jira to the merge commit message" do
|
41
|
+
checkout_an_existing_branch('master')
|
42
|
+
@repo.merge('feature_branch')
|
43
|
+
@repo.log_for_one_commit('HEAD') do |output, input|
|
44
|
+
output.expect("PA-12345", 5) do |message|
|
45
|
+
expect(message).to_not be nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "into the feature branch without conflicts" do
|
53
|
+
|
54
|
+
it "should relate the jiras" do
|
55
|
+
checkout_an_existing_branch('feature_branch')
|
56
|
+
@repo.merge('another_feature_branch')
|
57
|
+
assert_relation({jira: 'PA-12345'}, {branch: 'feature_branch'})
|
58
|
+
assert_no_relation({jira: 'PA-54321'}, {branch: 'feature_branch'})
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should add the current branch jira to the merge commit message" do
|
62
|
+
checkout_an_existing_branch('feature_branch')
|
63
|
+
@repo.merge('another_feature_branch')
|
64
|
+
@repo.log_for_one_commit('HEAD') do |output, input|
|
65
|
+
output.expect("PA-12345", 5) do |message|
|
66
|
+
expect(message).to_not be nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should add the merge branch jira to the merge commit message" do
|
72
|
+
checkout_an_existing_branch('feature_branch')
|
73
|
+
@repo.merge('another_feature_branch')
|
74
|
+
@repo.log_for_one_commit('HEAD') do |output, input|
|
75
|
+
output.expect("PA-54321", 5) do |message|
|
76
|
+
expect(message).to_not be nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|