jiragit 0.5.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 +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
|