git_reflow 0.8.6 → 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +348 -348
  4. data/Gemfile.lock +13 -15
  5. data/LICENSE +20 -20
  6. data/README.rdoc +461 -461
  7. data/Rakefile +8 -8
  8. data/bin/console +7 -7
  9. data/bin/setup +6 -6
  10. data/circle.yml +5 -5
  11. data/exe/git-reflow +36 -36
  12. data/git_reflow.gemspec +1 -1
  13. data/lib/git_reflow/commands/deliver.rb +10 -10
  14. data/lib/git_reflow/commands/refresh.rb +20 -20
  15. data/lib/git_reflow/commands/review.rb +13 -13
  16. data/lib/git_reflow/commands/setup.rb +11 -11
  17. data/lib/git_reflow/commands/stage.rb +9 -9
  18. data/lib/git_reflow/commands/start.rb +22 -22
  19. data/lib/git_reflow/commands/status.rb +7 -7
  20. data/lib/git_reflow/config.rb +9 -9
  21. data/lib/git_reflow/git_server/base.rb +68 -68
  22. data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
  23. data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
  24. data/lib/git_reflow/git_server/git_hub/pull_request.rb +4 -1
  25. data/lib/git_reflow/git_server/pull_request.rb +11 -2
  26. data/lib/git_reflow/git_server.rb +63 -63
  27. data/lib/git_reflow/logger.rb +49 -0
  28. data/lib/git_reflow/merge_error.rb +9 -9
  29. data/lib/git_reflow/os_detector.rb +23 -23
  30. data/lib/git_reflow/rspec/command_line_helpers.rb +12 -8
  31. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  32. data/lib/git_reflow/rspec.rb +2 -2
  33. data/lib/git_reflow/sandbox.rb +11 -6
  34. data/lib/git_reflow/version.rb +1 -1
  35. data/lib/git_reflow/workflow.rb +59 -59
  36. data/lib/git_reflow/workflows/core.rb +238 -238
  37. data/lib/git_reflow/workflows/flat_merge.rb +10 -10
  38. data/lib/git_reflow.rb +11 -0
  39. data/spec/fixtures/awesome_workflow.rb +7 -0
  40. data/spec/fixtures/git/git_config +7 -0
  41. data/spec/fixtures/issues/comment.json.erb +27 -0
  42. data/spec/fixtures/issues/comments.json +29 -0
  43. data/spec/fixtures/issues/comments.json.erb +15 -0
  44. data/spec/fixtures/pull_requests/comment.json.erb +45 -0
  45. data/spec/fixtures/pull_requests/comments.json +47 -0
  46. data/spec/fixtures/pull_requests/comments.json.erb +15 -0
  47. data/spec/fixtures/pull_requests/commits.json +29 -0
  48. data/spec/fixtures/pull_requests/external_pull_request.json +145 -0
  49. data/spec/fixtures/pull_requests/pull_request.json +142 -0
  50. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -0
  51. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -0
  52. data/spec/fixtures/pull_requests/pull_requests.json +136 -0
  53. data/spec/fixtures/repositories/commit.json +53 -0
  54. data/spec/fixtures/repositories/commit.json.erb +53 -0
  55. data/spec/fixtures/repositories/commits.json.erb +13 -0
  56. data/spec/fixtures/repositories/statuses.json +31 -0
  57. data/spec/fixtures/workflow_with_super.rb +8 -0
  58. data/spec/lib/git_reflow/config_spec.rb +74 -0
  59. data/spec/lib/git_reflow/git_helpers_spec.rb +182 -0
  60. data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -0
  61. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +587 -0
  62. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +221 -0
  63. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +524 -0
  64. data/spec/lib/git_reflow/git_server_spec.rb +101 -0
  65. data/spec/lib/git_reflow/logger_spec.rb +18 -0
  66. data/spec/lib/git_reflow/sandbox_spec.rb +15 -0
  67. data/spec/lib/git_reflow/workflow_spec.rb +59 -0
  68. data/spec/lib/git_reflow/workflows/core_spec.rb +665 -0
  69. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +59 -0
  70. data/spec/lib/git_reflow_spec.rb +75 -0
  71. data/spec/spec_helper.rb +38 -0
  72. data/spec/support/fake_github.rb +128 -0
  73. data/spec/support/fixtures.rb +54 -0
  74. data/spec/support/github_helpers.rb +109 -0
  75. data/spec/support/mock_pull_request.rb +17 -0
  76. data/spec/support/web_mocks.rb +39 -0
  77. metadata +83 -6
@@ -0,0 +1,136 @@
1
+ [
2
+ {
3
+ "url": "https://api.github.com/reenhanced/repo/pulls/1",
4
+ "html_url": "https://github.com/reenhanced/repo/pulls/1",
5
+ "diff_url": "https://github.com/reenhanced/repo/pulls/1.diff",
6
+ "patch_url": "https://github.com/reenhanced/repo/pulls/1.patch",
7
+ "issue_url": "https://github.com/reenhanced/repo/issue/1",
8
+ "number": 1,
9
+ "state": "open",
10
+ "title": "new-feature",
11
+ "body": "Please pull these awesome changes",
12
+ "created_at": "2011-01-26T19:01:12Z",
13
+ "updated_at": "2011-01-26T19:01:12Z",
14
+ "closed_at": "2011-01-26T19:01:12Z",
15
+ "merged_at": "2011-01-26T19:01:12Z",
16
+ "user": {
17
+ "login": "reenhanced",
18
+ "id": 1,
19
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
20
+ "gravatar_id": "",
21
+ "url": "https://api.github.com/users/reenhanced",
22
+ "html_url": "https://github.com/reenhanced",
23
+ "followers_url": "https://api.github.com/users/reenhanced/followers",
24
+ "following_url": "https://api.github.com/users/reenhanced/following{/other_user}",
25
+ "gists_url": "https://api.github.com/users/reenhanced/gists{/gist_id}",
26
+ "starred_url": "https://api.github.com/users/reenhanced/starred{/owner}{/repo}",
27
+ "subscriptions_url": "https://api.github.com/users/reenhanced/subscriptions",
28
+ "organizations_url": "https://api.github.com/users/reenhanced/orgs",
29
+ "repos_url": "https://api.github.com/users/reenhanced/repos",
30
+ "events_url": "https://api.github.com/users/reenhanced/events{/privacy}",
31
+ "received_events_url": "https://api.github.com/users/reenhanced/received_events",
32
+ "type": "User",
33
+ "site_admin": false
34
+ },
35
+ "head": {
36
+ "label": "new-feature",
37
+ "ref": "new-feature",
38
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
39
+ "user": {
40
+ "login": "reenhanced",
41
+ "id": 1,
42
+ "avatar_url": "https://github.com/images/error/reenhanced_happy.gif",
43
+ "gravatar_id": "somehexcode",
44
+ "url": "https://api.github.com/users/reenhanced"
45
+ },
46
+ "repo": {
47
+ "url": "https://api.github.com/repos/reenhanced/repo",
48
+ "html_url": "https://github.com/reenhanced/repo",
49
+ "clone_url": "https://github.com/reenhanced/repo.git",
50
+ "git_url": "git://github.com/reenhanced/repo.git",
51
+ "ssh_url": "git@github.com:reenhanced/repo.git",
52
+ "svn_url": "https://svn.github.com/reenhanced/repo",
53
+ "mirror_url": "git://git.example.com/reenhanced/repo",
54
+ "id": 1296269,
55
+ "owner": {
56
+ "login": "reenhanced",
57
+ "id": 1,
58
+ "avatar_url": "https://github.com/images/error/reenhanced_happy.gif",
59
+ "gravatar_id": "somehexcode",
60
+ "url": "https://api.github.com/users/reenhanced"
61
+ },
62
+ "name": "repo",
63
+ "description": "This your first repo!",
64
+ "homepage": "https://github.com",
65
+ "language": null,
66
+ "private": false,
67
+ "fork": false,
68
+ "forks": 9,
69
+ "watchers": 80,
70
+ "size": 108,
71
+ "master_branch": "master",
72
+ "open_issues": 0,
73
+ "pushed_at": "2011-01-26T19:06:43Z",
74
+ "created_at": "2011-01-26T19:01:12Z",
75
+ "updated_at": "2011-01-26T19:14:43Z"
76
+ }
77
+ },
78
+ "base": {
79
+ "label": "master",
80
+ "ref": "master",
81
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
82
+ "user": {
83
+ "login": "reenhanced",
84
+ "id": 1,
85
+ "avatar_url": "https://github.com/images/error/reenhanced_happy.gif",
86
+ "gravatar_id": "somehexcode",
87
+ "url": "https://api.github.com/users/reenhanced"
88
+ },
89
+ "repo": {
90
+ "url": "https://api.github.com/repos/reenhanced/repo",
91
+ "html_url": "https://github.com/reenhanced/repo",
92
+ "clone_url": "https://github.com/reenhanced/repo.git",
93
+ "git_url": "git://github.com/reenhanced/repo.git",
94
+ "ssh_url": "git@github.com:reenhanced/repo.git",
95
+ "svn_url": "https://svn.github.com/reenhanced/repo",
96
+ "mirror_url": "git://git.example.com/reenhanced/repo",
97
+ "id": 1296269,
98
+ "owner": {
99
+ "login": "reenhanced",
100
+ "id": 1,
101
+ "avatar_url": "https://github.com/images/error/reenhanced_happy.gif",
102
+ "gravatar_id": "somehexcode",
103
+ "url": "https://api.github.com/users/reenhanced"
104
+ },
105
+ "name": "repo",
106
+ "description": "This your first repo!",
107
+ "homepage": "https://github.com",
108
+ "language": null,
109
+ "private": false,
110
+ "fork": false,
111
+ "forks": 9,
112
+ "watchers": 80,
113
+ "size": 108,
114
+ "master_branch": "master",
115
+ "open_issues": 0,
116
+ "pushed_at": "2011-01-26T19:06:43Z",
117
+ "created_at": "2011-01-26T19:01:12Z",
118
+ "updated_at": "2011-01-26T19:14:43Z"
119
+ }
120
+ },
121
+ "_links": {
122
+ "self": {
123
+ "href": "https://api.github.com/reenhanced/repo/pulls/1"
124
+ },
125
+ "html": {
126
+ "href": "https://github.com/reenhanced/repo/pull/1"
127
+ },
128
+ "comments": {
129
+ "href": "https://api.github.com/reenhanced/repo/issues/1/comments"
130
+ },
131
+ "review_comments": {
132
+ "href": "https://api.github.com/reenhanced/repo/pulls/1/comments"
133
+ }
134
+ }
135
+ }
136
+ ]
@@ -0,0 +1,53 @@
1
+ {
2
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
3
+ "commit": {
4
+ "url": "https://api.github.com/repos/reenhanced/repo/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
5
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
6
+ "author": {
7
+ "name": "Monalisa Octocat",
8
+ "email": "support@github.com",
9
+ "date": "2011-04-14T16:00:49Z"
10
+ },
11
+ "committer": {
12
+ "name": "Monalisa Octocat",
13
+ "email": "support@github.com",
14
+ "date": "2011-04-14T16:00:49Z"
15
+ },
16
+ "message": "Fix all the bugs",
17
+ "tree": {
18
+ "url": "https://api.github.com/repos/reenhanced/repo/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
19
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
20
+ }
21
+ },
22
+ "author": {
23
+ "login": "reenhanced",
24
+ "id": 1,
25
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
26
+ "url": "https://api.github.com/users/reenhanced"
27
+ },
28
+ "committer": {
29
+ "login": "reenhanced",
30
+ "id": 1,
31
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
32
+ "url": "https://api.github.com/users/reenhanced"
33
+ },
34
+ "parents": [
35
+ {
36
+ "url": "https://api.github.com/repos/reenhanced/repo/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
37
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
38
+ }
39
+ ],
40
+ "stats": {
41
+ "additions": 104,
42
+ "deletions": 4,
43
+ "total": 108
44
+ },
45
+ "files": [
46
+ {
47
+ "filename": "file1.txt",
48
+ "additions": 10,
49
+ "deletions": 2,
50
+ "total": 12
51
+ }
52
+ ]
53
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
3
+ "commit": {
4
+ "url": "https://api.github.com/repos/<%= repo_owner %>/<%= repo_name %>/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
5
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
6
+ "author": {
7
+ "name": "Monalisa Octocat",
8
+ "email": "support@github.com",
9
+ "date": "<%= created_at || "2011-04-14T16:00:49Z" %>"
10
+ },
11
+ "committer": {
12
+ "name": "Monalisa Octocat",
13
+ "email": "support@github.com",
14
+ "date": "<%= created_at || "2011-04-14T16:00:49Z" %>"
15
+ },
16
+ "message": "Fix all the bugs",
17
+ "tree": {
18
+ "url": "https://api.github.com/repos/<%= repo_owner %>/<%= repo_name %>/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
19
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
20
+ }
21
+ },
22
+ "author": {
23
+ "login": "<%= author %>",
24
+ "id": 1,
25
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
26
+ "url": "https://api.github.com/users/<%= author %>"
27
+ },
28
+ "committer": {
29
+ "login": "<%= author %>",
30
+ "id": 1,
31
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
32
+ "url": "https://api.github.com/users/<%= author %>"
33
+ },
34
+ "parents": [
35
+ {
36
+ "url": "https://api.github.com/repos/<%= repo_owner %>/<%= repo_name %>/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
37
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
38
+ }
39
+ ],
40
+ "stats": {
41
+ "additions": 104,
42
+ "deletions": 4,
43
+ "total": 108
44
+ },
45
+ "files": [
46
+ {
47
+ "filename": "file1.txt",
48
+ "additions": 10,
49
+ "deletions": 2,
50
+ "total": 12
51
+ }
52
+ ]
53
+ }
@@ -0,0 +1,13 @@
1
+ [
2
+ <% commits_json = [] %>
3
+ <% commits.each_with_index do |commit, index| %>
4
+ <% commits_json << Fixture.new('repositories/commit.json.erb',
5
+ id: index,
6
+ author: commit[:author],
7
+ repo_owner: repo_owner,
8
+ repo_name: repo_name,
9
+ created_at: commit[:created_at] || Chronic.parse("October 21, 2015 07:28:00")
10
+ ).to_s %>
11
+ <% end %>
12
+ <%= commits_json.join(", ") %>
13
+ ]
@@ -0,0 +1,31 @@
1
+ [
2
+ {
3
+ "created_at": "2012-07-20T01:19:13Z",
4
+ "updated_at": "2012-07-20T01:19:13Z",
5
+ "state": "success",
6
+ "target_url": "https://ci.example.com/1000/output",
7
+ "description": "Build has completed successfully",
8
+ "id": 1,
9
+ "url": "https://api.github.com/repos/reenhanced/example/statuses/1",
10
+ "context": "continuous-integration/jenkins",
11
+ "creator": {
12
+ "login": "reenhanced",
13
+ "id": 1,
14
+ "avatar_url": "https://github.com/images/error/octocat_happy.gif",
15
+ "gravatar_id": "somehexcode",
16
+ "url": "https://api.github.com/users/reenhanced",
17
+ "html_url": "https://github.com/reenhanced",
18
+ "followers_url": "https://api.github.com/users/reenhanced/followers",
19
+ "following_url": "https://api.github.com/users/reenhanced/following{/other_user}",
20
+ "gists_url": "https://api.github.com/users/reenhanced/gists{/gist_id}",
21
+ "starred_url": "https://api.github.com/users/reenhanced/starred{/owner}{/repo}",
22
+ "subscriptions_url": "https://api.github.com/users/reenhanced/subscriptions",
23
+ "organizations_url": "https://api.github.com/users/reenhanced/orgs",
24
+ "repos_url": "https://api.github.com/users/reenhanced/repos",
25
+ "events_url": "https://api.github.com/users/reenhanced/events{/privacy}",
26
+ "received_events_url": "https://api.github.com/users/reenhanced/received_events",
27
+ "type": "User",
28
+ "site_admin": false
29
+ }
30
+ }
31
+ ]
@@ -0,0 +1,8 @@
1
+ class WorkflowWithSuper < GitReflow::Workflows::Core
2
+ def self.start(**args)
3
+ GitReflow.say "Super."
4
+ super(feature_branch: args[:feature_branch], base: args[:base])
5
+ end
6
+ end
7
+
8
+ WorkflowWithSuper
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::Config do
4
+ describe ".get(key)" do
5
+ subject { GitReflow::Config.get('chucknorris.roundhouse') }
6
+ it { expect{ subject }.to have_run_command_silently 'git config --get chucknorris.roundhouse', blocking: false }
7
+
8
+ context "and getting all values" do
9
+ subject { GitReflow::Config.get('chucknorris.roundhouse-kick', all: true) }
10
+ it { expect{ subject }.to have_run_command_silently 'git config --get-all chucknorris.roundhouse-kick', blocking: false }
11
+
12
+ context "and checking locally only" do
13
+ subject { GitReflow::Config.get('chucknorris.jump', local: true) }
14
+ it { expect{ subject }.to have_run_command_silently 'git config --local --get chucknorris.jump', blocking: false }
15
+ end
16
+ end
17
+
18
+ context "and checking for updates" do
19
+ before { GitReflow::Config.get('chucknorris.roundhouse') }
20
+ subject { GitReflow::Config.get('chucknorris.roundhouse') }
21
+ it { expect{ subject }.to_not have_run_command_silently 'git config --get chucknorris.roundhouse-kick', blocking: false }
22
+ end
23
+
24
+ context "and checking locally only" do
25
+ subject { GitReflow::Config.get('chucknorris.smash', local: true) }
26
+ it { expect{ subject }.to have_run_command_silently 'git config --local --get chucknorris.smash', blocking: false }
27
+ end
28
+ end
29
+
30
+ describe ".set(key)" do
31
+ subject { GitReflow::Config.set('chucknorris.roundhouse', 'to the face') }
32
+ it { expect{ subject }.to have_run_command_silently "git config -f #{ENV['HOME']}/.gitconfig.reflow --replace-all chucknorris.roundhouse \"to the face\"", blocking: false }
33
+
34
+ context "for current project only" do
35
+ subject { GitReflow::Config.set('chucknorris.roundhouse', 'to the face', local: true) }
36
+ it { expect{ subject }.to have_run_command_silently 'git config --replace-all chucknorris.roundhouse "to the face"', blocking: false }
37
+ end
38
+ end
39
+
40
+ describe ".unset(key)" do
41
+ subject { GitReflow::Config.unset('chucknorris.roundhouse') }
42
+ it { expect{ subject }.to have_run_command_silently "git config -f #{ENV['HOME']}/.gitconfig.reflow --unset-all chucknorris.roundhouse ", blocking: false }
43
+
44
+ context "for multi-value keys" do
45
+ subject { GitReflow::Config.unset('chucknorris.roundhouse', value: 'to the face') }
46
+ it { expect{ subject }.to have_run_command_silently "git config -f #{ENV['HOME']}/.gitconfig.reflow --unset-all chucknorris.roundhouse \"to the face\"", blocking: false }
47
+ end
48
+
49
+ context "for current project only" do
50
+ subject { GitReflow::Config.unset('chucknorris.roundhouse', local: true) }
51
+ it { expect{ subject }.to have_run_command_silently 'git config --unset-all chucknorris.roundhouse ', blocking: false }
52
+
53
+ context "for multi-value keys" do
54
+ subject { GitReflow::Config.unset('chucknorris.roundhouse', value: 'to the face', local: true) }
55
+ it { expect{ subject }.to have_run_command_silently 'git config --unset-all chucknorris.roundhouse "to the face"', blocking: false }
56
+ end
57
+ end
58
+ end
59
+
60
+ describe ".add(key)" do
61
+ subject { GitReflow::Config.add('chucknorris.roundhouse', 'to the face') }
62
+ it { expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --add chucknorris.roundhouse \"to the face\"", blocking: false }
63
+
64
+ context "for current project only" do
65
+ subject { GitReflow::Config.add('chucknorris.roundhouse', 'to the face', local: true) }
66
+ it { expect{ subject }.to have_run_command_silently 'git config --add chucknorris.roundhouse "to the face"', blocking: false }
67
+ end
68
+
69
+ context "globally" do
70
+ subject { GitReflow::Config.add('chucknorris.roundhouse', 'to the face', global: true) }
71
+ it { expect{ subject }.to have_run_command_silently 'git config --global --add chucknorris.roundhouse "to the face"', blocking: false }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::GitHelpers do
4
+ let(:origin_url) { 'git@github.com:reenhanced.spectacular/this-is-the.shit.git' }
5
+
6
+ before do
7
+ stub_with_fallback(GitReflow::Config, :get).with('remote.origin.url').and_return(origin_url)
8
+
9
+ module Gitacular
10
+ include GitReflow::GitHelpers
11
+ extend self
12
+ end
13
+
14
+ stub_run_for Gitacular
15
+ end
16
+
17
+ describe ".git_root_dir" do
18
+ subject { Gitacular.git_root_dir }
19
+ it { expect{ subject }.to have_run_command_silently "git rev-parse --show-toplevel" }
20
+ end
21
+
22
+ describe '.git_editor_command' do
23
+ subject { Gitacular.git_editor_command }
24
+ before { ENV['EDITOR'] = 'vim' }
25
+
26
+ it 'defaults to GitReflow config' do
27
+ allow(GitReflow::Config).to receive(:get).with('core.editor').and_return 'nano'
28
+
29
+ expect(subject).to eq 'nano'
30
+ end
31
+
32
+ it 'falls back to the environment variable $EDITOR' do
33
+ allow(GitReflow::Config).to receive(:get).with('core.editor').and_return ''
34
+
35
+ expect(subject).to eq 'vim'
36
+ end
37
+ end
38
+
39
+ describe ".remote_user" do
40
+ subject { Gitacular.remote_user }
41
+
42
+ it { is_expected.to eq('reenhanced.spectacular') }
43
+
44
+ context "remote origin url isn't set" do
45
+ let(:origin_url) { nil }
46
+ it { is_expected.to eq('') }
47
+ end
48
+
49
+ context "remote origin uses HTTP" do
50
+ let(:origin_url) { 'https://github.com/reenhanced.spectacular/this-is-the.shit.git' }
51
+ it { is_expected.to eq('reenhanced.spectacular') }
52
+ end
53
+ end
54
+
55
+ describe ".remote_repo_name" do
56
+ subject { Gitacular.remote_repo_name }
57
+
58
+ it { is_expected.to eq('this-is-the.shit') }
59
+
60
+ context "remote origin url isn't set" do
61
+ let(:origin_url) { nil }
62
+ it { is_expected.to eq('') }
63
+ end
64
+
65
+ context "remote origin uses HTTP" do
66
+ let(:origin_url) { 'https://github.com/reenhanced.spectacular/this-is-the.shit.git' }
67
+ it { is_expected.to eq('this-is-the.shit') }
68
+ end
69
+ end
70
+
71
+ describe ".current_branch" do
72
+ subject { Gitacular.current_branch }
73
+ it { expect{ subject }.to have_run_command_silently "git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'" }
74
+ end
75
+
76
+ describe ".pull_request_template" do
77
+ subject { Gitacular.pull_request_template }
78
+
79
+ context "template file exists" do
80
+ let(:root_dir) { "/some_repo" }
81
+ let(:template_content) { "Template content" }
82
+
83
+ before do
84
+ allow(Gitacular).to receive(:git_root_dir).and_return(root_dir)
85
+ allow(File).to receive(:exist?).with("#{root_dir}/.github/PULL_REQUEST_TEMPLATE.md").and_return(true)
86
+ allow(File).to receive(:read).with("#{root_dir}/.github/PULL_REQUEST_TEMPLATE.md").and_return(template_content)
87
+ end
88
+ it { is_expected.to eq template_content }
89
+ end
90
+
91
+ context "template file does not exist" do
92
+ before do
93
+ allow(File).to receive(:exist?).and_return(false)
94
+ end
95
+
96
+ it { is_expected.to be_nil }
97
+ end
98
+ end
99
+
100
+ describe ".get_first_commit_message" do
101
+ subject { Gitacular.get_first_commit_message }
102
+ it { expect{ subject }.to have_run_command_silently 'git log --pretty=format:"%s" --no-merges -n 1' }
103
+ end
104
+
105
+ describe ".push_current_branch" do
106
+ subject { Gitacular.push_current_branch }
107
+ before { allow(Gitacular).to receive(:current_branch).and_return('bingo') }
108
+ it { expect{ subject }.to have_run_command "git push origin bingo" }
109
+ end
110
+
111
+ describe ".fetch_destination(destination_branch)" do
112
+ subject { Gitacular.fetch_destination('new-feature') }
113
+ it { expect{ subject }.to have_run_command "git fetch origin new-feature" }
114
+ end
115
+
116
+ describe ".update_destination(destination_branch)" do
117
+ let(:current_branch) { 'bananas' }
118
+ let(:destination_branch) { 'monkey-business' }
119
+
120
+ before { allow(Gitacular).to receive(:current_branch).and_return(current_branch) }
121
+ subject { Gitacular.update_destination(destination_branch) }
122
+
123
+ it "updates the destination branch with the latest code from the remote repo" do
124
+ expect { subject }.to have_run_commands_in_order [
125
+ "git checkout #{destination_branch}",
126
+ "git pull origin #{destination_branch}",
127
+ "git checkout #{current_branch}"
128
+ ]
129
+ end
130
+ end
131
+
132
+ describe ".update_current_branch" do
133
+ subject { Gitacular.update_current_branch }
134
+ before { allow(Gitacular).to receive(:current_branch).and_return('new-feature') }
135
+
136
+ it "updates the remote changes and pushes any local changes" do
137
+ expect { subject }.to have_run_commands_in_order [
138
+ "git pull origin new-feature",
139
+ "git push origin new-feature"
140
+ ]
141
+ end
142
+ end
143
+
144
+ describe ".update_feature_branch" do
145
+ options = {base: "base", remote: "remote"}
146
+ subject { Gitacular.update_feature_branch(options) }
147
+ before { allow(Gitacular).to receive(:current_branch).and_return('feature') }
148
+
149
+ it "calls the correct methods" do
150
+ expect { subject }.to have_run_commands_in_order [
151
+ "git checkout base",
152
+ "git pull remote base",
153
+ "git checkout feature",
154
+ "git pull origin feature",
155
+ "git merge base"
156
+ ]
157
+ end
158
+ end
159
+
160
+ describe ".append_to_squashed_commit_message(message)" do
161
+ let(:original_squash_message) { "Oooooo, SQUASH IT" }
162
+ let(:message) { "do do the voodoo that you do" }
163
+ let(:root_dir) { '/home/gitreflow' }
164
+ let(:squash_path) { "#{root_dir}/.git/SQUASH_MSG" }
165
+ let(:tmp_squash_path) { "#{root_dir}/.git/tmp_squash_msg" }
166
+ before { allow(Gitacular).to receive(:git_root_dir).and_return(root_dir) }
167
+ subject { Gitacular.append_to_squashed_commit_message(message) }
168
+
169
+ it "appends the message to git's SQUASH_MSG temp file" do
170
+ tmp_file = double('file')
171
+ allow(File).to receive(:open).with(tmp_squash_path, "w").and_yield(tmp_file)
172
+ allow(File).to receive(:exists?).with(squash_path).and_return(true)
173
+ allow(File).to receive(:foreach).with(squash_path).and_yield(original_squash_message)
174
+ expect(tmp_file).to receive(:puts).with(message)
175
+ expect(tmp_file).to receive(:puts).with(original_squash_message)
176
+
177
+ expect { subject }.to have_run_commands_in_order [
178
+ "mv #{tmp_squash_path} #{squash_path}"
179
+ ]
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::GitServer::BitBucket do
4
+ let(:user) { 'reenhanced' }
5
+ let(:password) { 'shazam' }
6
+ let(:repo) { 'repo' }
7
+ let(:api_key) { 'a1b2c3d4e5f6g7h8i9j0' }
8
+ let(:hostname) { 'hostname.local' }
9
+ let(:api_endpoint) { 'https://bitbucket.org/api/1.0' }
10
+ let(:site) { 'https://bitbucket.org' }
11
+ let(:remote_url) { "git@bitbucket.org:#{user}/#{repo}.git" }
12
+
13
+ before do
14
+ allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
15
+ values = {
16
+ "Please enter your BitBucket username: " => user
17
+ }
18
+ return_value = values[question]
19
+ question = ""
20
+ return_value
21
+ end
22
+ end
23
+
24
+ describe '#initialize(options)' do
25
+ subject { GitReflow::GitServer::BitBucket.new({}) }
26
+
27
+ it 'sets the reflow git server provider to BitBucket in the git config' do
28
+ expect(GitReflow::Config).to receive(:set).once.with('reflow.git-server', 'BitBucket', local: false)
29
+ subject
30
+ end
31
+
32
+ context 'storing git config settings only for this project' do
33
+ subject { GitReflow::GitServer::BitBucket.new(project_only: true) }
34
+
35
+ it 'sets the enterprise site and api as the site and api endpoints for the BitBucket provider in the git config' do
36
+ expect(GitReflow::Config).to receive(:set).once.with('reflow.git-server', 'BitBucket', local: true)
37
+ subject
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ describe '#authenticate' do
44
+ let(:bitbucket) { GitReflow::GitServer::BitBucket.new( { }) }
45
+ let!(:bitbucket_api) { BitBucket.new }
46
+ subject { bitbucket.authenticate }
47
+
48
+ context 'already authenticated' do
49
+ it "notifies the user of successful setup" do
50
+ allow(GitReflow::Config).to receive(:set).with('reflow.git-server', 'BitBucket', local: false)
51
+ allow(GitReflow::Config).to receive(:get).with('remote.origin.url').and_return(remote_url)
52
+ allow(GitReflow::Config).to receive(:get).with('bitbucket.user', local: false).and_return(user)
53
+ allow(GitReflow::Config).to receive(:get).with('bitbucket.api-key', reload: true, local: false).and_return(api_key)
54
+ allow(GitReflow::Config).to receive(:get).with('reflow.local-projects', all: true).and_return('')
55
+ expect { subject }.to have_said "\nYour BitBucket account was already setup with:"
56
+ expect { subject }.to have_said "\tUser Name: #{user}"
57
+ end
58
+ end
59
+
60
+ context 'not yet authenticated' do
61
+ context 'with valid BitBucket credentials' do
62
+ before do
63
+ allow(GitReflow::Config).to receive(:get).and_return('')
64
+ allow(GitReflow::Config).to receive(:set)
65
+ allow(GitReflow::Config).to receive(:set).with('bitbucket.api-key', reload: true).and_return(api_key)
66
+ allow(GitReflow::Config).to receive(:get).with('bitbucket.api-key', reload: true).and_return('')
67
+ allow(GitReflow::Config).to receive(:get).with('remote.origin.url').and_return(remote_url)
68
+ allow(GitReflow::Config).to receive(:get).with('reflow.local-projects').and_return('')
69
+ allow(bitbucket).to receive(:connection).and_return double(repos: double(all: []))
70
+ end
71
+
72
+ it "prompts me to setup an API key" do
73
+ expect { subject }.to have_said "\nIn order to connect your BitBucket account,"
74
+ expect { subject }.to have_said "you'll need to generate an API key for your team"
75
+ expect { subject }.to have_said "Visit https://bitbucket.org/account/user/reenhanced/api-key/, to generate it\n"
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ end