git_reflow 0.3.5 → 0.4.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/.gitignore +2 -0
- data/Gemfile.lock +67 -35
- data/Rakefile +8 -0
- data/git_reflow.gemspec +5 -4
- data/lib/git_reflow/commands/setup.rb +8 -1
- data/lib/git_reflow/commands/start.rb +2 -2
- data/lib/git_reflow/config.rb +23 -0
- data/lib/git_reflow/git_helpers.rb +65 -0
- data/lib/git_reflow/git_server/base.rb +88 -0
- data/lib/git_reflow/git_server/git_hub.rb +184 -0
- data/lib/git_reflow/git_server.rb +52 -0
- data/lib/git_reflow/sandbox.rb +39 -0
- data/lib/git_reflow/version.rb +1 -1
- data/lib/git_reflow.rb +48 -273
- data/spec/fixtures/git/git_config +7 -0
- data/spec/fixtures/issues/comments.json +29 -0
- data/spec/fixtures/pull_requests/comments.json +47 -0
- data/spec/fixtures/pull_requests/pull_request.json +123 -0
- data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -0
- data/spec/fixtures/pull_requests/pull_requests.json +117 -0
- data/spec/fixtures/repositories/statuses.json +31 -0
- data/spec/git_reflow_spec.rb +386 -0
- data/spec/lib/git_reflow/config_spec.rb +18 -0
- data/spec/lib/git_reflow/git_helpers_spec.rb +146 -0
- data/spec/lib/git_reflow/git_server_spec.rb +94 -0
- data/spec/lib/git_server/git_hub_spec.rb +236 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/command_line_helpers.rb +99 -0
- data/spec/support/fixtures.rb +8 -0
- data/spec/support/github_helpers.rb +98 -0
- data/spec/support/rspec_stub_helpers.rb +7 -0
- data/spec/support/web_mocks.rb +39 -0
- metadata +104 -62
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6033d9ac0481348f75d715588d5ae35f451b53e8
|
4
|
+
data.tar.gz: 6865bb6dfdad09ada836eb0e5cb08a2f8bc7b29f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1054c1140b333a61c70030757b5a713b2d23a876c2912d6d18887c4d946e7e8b8e92f4277529bf8075ed9112e6b701ed79a2102fe51759d7a415229b5414d189
|
7
|
+
data.tar.gz: 9720ebbd2a3ee378cc830940de30170b58ed1fe970264f45807fad418f03413d40faf8099ff947bfd9bf7e2f77d436eaa0b6dc554c6d83cc4d0be58e331231bb
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
git_reflow (0.
|
4
|
+
git_reflow (0.4.0)
|
5
5
|
colorize (= 0.6.0)
|
6
|
-
github_api (= 0.
|
7
|
-
gli (= 2.
|
6
|
+
github_api (= 0.12.1)
|
7
|
+
gli (= 2.12.2)
|
8
8
|
highline
|
9
9
|
httpclient
|
10
10
|
json_pure
|
@@ -13,48 +13,78 @@ GEM
|
|
13
13
|
remote: https://rubygems.org/
|
14
14
|
specs:
|
15
15
|
addressable (2.3.5)
|
16
|
+
byebug (3.5.1)
|
17
|
+
columnize (~> 0.8)
|
18
|
+
debugger-linecache (~> 1.2)
|
19
|
+
slop (~> 3.6)
|
20
|
+
coderay (1.1.0)
|
16
21
|
colorize (0.6.0)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
columnize (0.8.9)
|
23
|
+
crack (0.4.2)
|
24
|
+
safe_yaml (~> 1.0.0)
|
25
|
+
debugger-linecache (1.2.0)
|
26
|
+
descendants_tracker (0.0.4)
|
27
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
28
|
+
diff-lcs (1.2.5)
|
29
|
+
faraday (0.9.0)
|
30
|
+
multipart-post (>= 1.2, < 3)
|
31
|
+
github_api (0.12.1)
|
32
|
+
addressable (~> 2.3)
|
33
|
+
descendants_tracker (~> 0.0.4)
|
34
|
+
faraday (~> 0.8, < 0.10)
|
35
|
+
hashie (>= 3.2)
|
36
|
+
multi_json (>= 1.7.5, < 2.0)
|
37
|
+
nokogiri (~> 1.6.3)
|
26
38
|
oauth2
|
27
|
-
gli (2.
|
28
|
-
hashie (
|
29
|
-
highline (1.6.
|
30
|
-
|
31
|
-
httpclient (2.3.4.1)
|
32
|
-
jeweler (1.8.4)
|
33
|
-
bundler (~> 1.0)
|
34
|
-
git (>= 1.2.5)
|
35
|
-
rake
|
36
|
-
rdoc
|
39
|
+
gli (2.12.2)
|
40
|
+
hashie (3.3.1)
|
41
|
+
highline (1.6.21)
|
42
|
+
httpclient (2.4.0)
|
37
43
|
json (1.7.5)
|
38
44
|
json_pure (1.8.1)
|
39
|
-
jwt (0.
|
40
|
-
|
41
|
-
mini_portile (0.
|
42
|
-
multi_json (1.
|
45
|
+
jwt (1.0.0)
|
46
|
+
method_source (0.8.2)
|
47
|
+
mini_portile (0.6.0)
|
48
|
+
multi_json (1.10.1)
|
43
49
|
multi_xml (0.5.5)
|
44
|
-
multipart-post (
|
45
|
-
nokogiri (1.6.
|
46
|
-
mini_portile (
|
47
|
-
oauth2 (0.
|
48
|
-
faraday (
|
49
|
-
|
50
|
-
|
51
|
-
multi_json (~> 1.0)
|
50
|
+
multipart-post (2.0.0)
|
51
|
+
nokogiri (1.6.3.1)
|
52
|
+
mini_portile (= 0.6.0)
|
53
|
+
oauth2 (1.0.0)
|
54
|
+
faraday (>= 0.8, < 0.10)
|
55
|
+
jwt (~> 1.0)
|
56
|
+
multi_json (~> 1.3)
|
52
57
|
multi_xml (~> 0.5)
|
53
58
|
rack (~> 1.2)
|
59
|
+
pry (0.10.1)
|
60
|
+
coderay (~> 1.1.0)
|
61
|
+
method_source (~> 0.8.1)
|
62
|
+
slop (~> 3.4)
|
63
|
+
pry-byebug (2.0.0)
|
64
|
+
byebug (~> 3.4)
|
65
|
+
pry (~> 0.10)
|
54
66
|
rack (1.5.2)
|
55
67
|
rake (0.9.2.2)
|
56
68
|
rdoc (3.12)
|
57
69
|
json (~> 1.4)
|
70
|
+
rspec (3.0.0)
|
71
|
+
rspec-core (~> 3.0.0)
|
72
|
+
rspec-expectations (~> 3.0.0)
|
73
|
+
rspec-mocks (~> 3.0.0)
|
74
|
+
rspec-core (3.0.3)
|
75
|
+
rspec-support (~> 3.0.0)
|
76
|
+
rspec-expectations (3.0.3)
|
77
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
78
|
+
rspec-support (~> 3.0.0)
|
79
|
+
rspec-mocks (3.0.3)
|
80
|
+
rspec-support (~> 3.0.0)
|
81
|
+
rspec-support (3.0.3)
|
82
|
+
safe_yaml (1.0.1)
|
83
|
+
slop (3.6.0)
|
84
|
+
thread_safe (0.3.4)
|
85
|
+
webmock (1.17.4)
|
86
|
+
addressable (>= 2.2.7)
|
87
|
+
crack (>= 0.3.2)
|
58
88
|
|
59
89
|
PLATFORMS
|
60
90
|
ruby
|
@@ -62,6 +92,8 @@ PLATFORMS
|
|
62
92
|
DEPENDENCIES
|
63
93
|
bundler
|
64
94
|
git_reflow!
|
65
|
-
|
95
|
+
pry-byebug
|
66
96
|
rake
|
67
97
|
rdoc
|
98
|
+
rspec (~> 3.0.0)
|
99
|
+
webmock
|
data/Rakefile
CHANGED
data/git_reflow.gemspec
CHANGED
@@ -16,21 +16,22 @@ spec = Gem::Specification.new do |s|
|
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.extra_rdoc_files = ['README.rdoc']
|
18
18
|
s.bindir = 'bin'
|
19
|
-
|
20
19
|
s.require_paths << 'lib'
|
21
20
|
s.rdoc_options << '--title' << 'git_reflow' << '--main' << 'README.rdoc' << '-ri'
|
22
21
|
|
23
22
|
s.add_development_dependency('bundler')
|
23
|
+
s.add_development_dependency('pry-byebug')
|
24
24
|
s.add_development_dependency('rake')
|
25
25
|
s.add_development_dependency('rdoc')
|
26
|
-
s.add_development_dependency('
|
26
|
+
s.add_development_dependency('rspec', '~> 3.0.0')
|
27
|
+
s.add_development_dependency('webmock')
|
27
28
|
|
28
29
|
s.add_dependency('colorize', '0.6.0')
|
29
|
-
s.add_dependency('gli', '2.
|
30
|
+
s.add_dependency('gli', '2.12.2')
|
30
31
|
s.add_dependency('highline')
|
31
32
|
s.add_dependency('httpclient')
|
32
33
|
s.add_dependency('json_pure')
|
33
|
-
s.add_dependency('github_api', '0.
|
34
|
+
s.add_dependency('github_api', '0.12.1')
|
34
35
|
|
35
36
|
s.post_install_message = "You need to setup your GitHub OAuth token\nPlease run 'git-reflow setup'"
|
36
37
|
end
|
@@ -4,6 +4,13 @@ command :setup do |c|
|
|
4
4
|
c.switch [:l, :local], default_value: false, desc: 'setup GitReflow for the current project only'
|
5
5
|
c.switch [:e, :enterprise], default_value: false, desc: 'setup GitReflow with a Github Enterprise account'
|
6
6
|
c.action do |global_options, options, args|
|
7
|
-
|
7
|
+
reflow_options = { project_only: options[:local], enterprise: options[:enterprise] }
|
8
|
+
choose do |menu|
|
9
|
+
menu.header = "Available remote Git Server services:"
|
10
|
+
menu.prompt = "Which service would you like to use for this project? "
|
11
|
+
|
12
|
+
menu.choice('GitHub') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'GitHub', silent: false }) }
|
13
|
+
menu.choice('BitBucket') { say("Coming soon...") }
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
@@ -2,7 +2,7 @@ desc 'Start will create a new feature branch and setup remote tracking'
|
|
2
2
|
long_desc <<LONGTIME
|
3
3
|
Performs the following:\n
|
4
4
|
\t$ git pull origin <current_branch>\n
|
5
|
-
\t$ git push origin
|
5
|
+
\t$ git push origin <current_branch>:refs/heads/[new_feature_branch]\n
|
6
6
|
\t$ git checkout --track -b [new_feature_branch] origin/[new_feature_branch]\n
|
7
7
|
LONGTIME
|
8
8
|
arg_name '[new-feature-branch-name] - name of the new feature branch'
|
@@ -18,7 +18,7 @@ command :start do |c|
|
|
18
18
|
raise "usage: git-reflow start [new-branch-name]"
|
19
19
|
else
|
20
20
|
`git pull origin #{GitReflow.current_branch}`
|
21
|
-
`git push origin
|
21
|
+
`git push origin #{GitReflow.current_branch}:refs/heads/#{args[0]}`
|
22
22
|
`git checkout --track -b #{args[0]} origin/#{args[0]}`
|
23
23
|
end
|
24
24
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module GitReflow
|
2
|
+
module Config
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def get(key)
|
6
|
+
if cached_key_value = instance_variable_get(:"@#{key.tr('.-', '_')}")
|
7
|
+
cached_key_value
|
8
|
+
else
|
9
|
+
new_value = GitReflow::Sandbox.run "git config --get #{key}", loud: false
|
10
|
+
instance_variable_set(:"@#{key.tr('.-', '_')}", new_value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(key, value, options = { local: false })
|
15
|
+
value = value.strip
|
16
|
+
if options.delete(:local)
|
17
|
+
GitReflow::Sandbox.run "git config --replace-all #{key} \"#{value}\"", loud: false
|
18
|
+
else
|
19
|
+
GitReflow::Sandbox.run "git config --global --replace-all #{key} \"#{value}\"", loud: false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'git_reflow/config'
|
2
|
+
require 'git_reflow/sandbox'
|
3
|
+
|
4
|
+
module GitReflow
|
5
|
+
module GitHelpers
|
6
|
+
include Sandbox
|
7
|
+
|
8
|
+
def remote_user
|
9
|
+
return "" unless "#{GitReflow::Config.get('remote.origin.url')}".length > 0
|
10
|
+
GitReflow::Config.get('remote.origin.url')[/[\/:](\w|-|\.)+/i][1..-1]
|
11
|
+
end
|
12
|
+
|
13
|
+
def remote_repo_name
|
14
|
+
return "" unless "#{GitReflow::Config.get('remote.origin.url')}".length > 0
|
15
|
+
GitReflow::Config.get('remote.origin.url')[/\/(\w|-|\.)+$/i][1..-5]
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_branch
|
19
|
+
run("git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'", loud: false).strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_first_commit_message
|
23
|
+
run('git log --pretty=format:"%s" --no-merges -n 1', loud: false).strip
|
24
|
+
end
|
25
|
+
|
26
|
+
def push_current_branch
|
27
|
+
run_command_with_label "git push origin #{current_branch}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch_destination(destination_branch)
|
31
|
+
run_command_with_label "git fetch origin #{destination_branch}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_destination(destination_branch)
|
35
|
+
origin_branch = current_branch
|
36
|
+
run_command_with_label "git checkout #{destination_branch}"
|
37
|
+
run_command_with_label "git pull origin #{destination_branch}"
|
38
|
+
run_command_with_label "git checkout #{origin_branch}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def merge_feature_branch(feature_branch_name, options = {})
|
42
|
+
options[:destination_branch] ||= 'master'
|
43
|
+
|
44
|
+
message = "#{options[:message]}"
|
45
|
+
|
46
|
+
if "#{options[:pull_request_number]}".length > 0
|
47
|
+
message << "\nCloses ##{options[:pull_request_number]}\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
if lgtm_authors = Array(options[:lgtm_authors]) and lgtm_authors.any?
|
51
|
+
message << "\nLGTM given by: @#{lgtm_authors.join(', @')}\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
run_command_with_label "git checkout #{options[:destination_branch]}"
|
55
|
+
run_command_with_label "git merge --squash #{feature_branch_name}"
|
56
|
+
|
57
|
+
append_to_squashed_commit_message(message) if message.length > 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def append_to_squashed_commit_message(message = '')
|
61
|
+
run "echo \"#{message}\" | cat - .git/SQUASH_MSG > ./tmp_squash_msg"
|
62
|
+
run 'mv ./tmp_squash_msg .git/SQUASH_MSG'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'git_reflow/config'
|
2
|
+
|
3
|
+
module GitReflow
|
4
|
+
class GitServer::Base
|
5
|
+
@@connection = nil
|
6
|
+
@@project_only = false
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@@project_only = !!options.delete(:project_only)
|
10
|
+
|
11
|
+
site_url = self.class.site_url
|
12
|
+
api_endpoint = self.class.api_endpoint
|
13
|
+
|
14
|
+
self.class.site_url = site_url
|
15
|
+
self.class.api_endpoint = api_endpoint
|
16
|
+
|
17
|
+
authenticate
|
18
|
+
end
|
19
|
+
|
20
|
+
def authenticate
|
21
|
+
raise "#{self.class.to_s}#authenticate method must be implemented"
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_pull_request(options)
|
25
|
+
raise "#{self.class.to_s}#find_pull_request(options) method must be implemented"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.connection
|
29
|
+
raise "#{self.class.to_s}.connection method must be implemented"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.user
|
33
|
+
raise "#{self.class.to_s}.user method must be implemented"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.oauth_token
|
37
|
+
raise "#{self.class.to_s}.oauth_token method must be implemented"
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.oauth_token=(oauth_token)
|
41
|
+
raise "#{self.class.to_s}.oauth_token= method must be implemented"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.api_endpoint
|
45
|
+
raise "#{self.class.to_s}.api_endpoint method must be implemented"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.api_endpoint=(api_endpoint, options = {local: false})
|
49
|
+
raise "#{self.class.to_s}.api_endpoint= method must be implemented"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.site_url
|
53
|
+
raise "#{self.class.to_s}.site_url method must be implemented"
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.site_url=(site_url, options = {local: false})
|
57
|
+
raise "#{self.class.to_s}.site_url= method must be implemented"
|
58
|
+
end
|
59
|
+
|
60
|
+
def connection
|
61
|
+
@connection ||= self.class.connection
|
62
|
+
end
|
63
|
+
|
64
|
+
def pull_request_comments(pull_request)
|
65
|
+
raise "#{self.class.to_s}#pull_request_comments(pull_request) method must be implemented"
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_pull_request_comments?(pull_request)
|
69
|
+
pull_request_comments(pull_request).count > 0
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_build_status sha
|
73
|
+
raise "#{self.class.to_s}#get_build_status(sha) method must be implemented"
|
74
|
+
end
|
75
|
+
|
76
|
+
def colorized_build_description status
|
77
|
+
raise "#{self.class.to_s}#colorized_build_description(status) method must be implemented"
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_authors_of_open_pull_request_comments(pull_request)
|
81
|
+
raise "#{self.class.to_s}#find_authors_of_open_pull_request_comments(pull_request) method must be implemented"
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_commited_time(commit_sha)
|
85
|
+
raise "#{self.class.to_s}#get_commited_time(commit_sha) method must be implemented"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'github_api'
|
2
|
+
require 'git_reflow/git_helpers'
|
3
|
+
|
4
|
+
module GitReflow
|
5
|
+
module GitServer
|
6
|
+
class GitHub < Base
|
7
|
+
include GitHelpers
|
8
|
+
|
9
|
+
attr_accessor :connection
|
10
|
+
|
11
|
+
@@project_only = false
|
12
|
+
@@using_enterprise = false
|
13
|
+
|
14
|
+
def initialize(config_options = {})
|
15
|
+
@@project_only = !!config_options.delete(:project_only)
|
16
|
+
@@using_enterprise = !!config_options.delete(:enterprise)
|
17
|
+
|
18
|
+
gh_site_url = self.class.site_url
|
19
|
+
gh_api_endpoint = self.class.api_endpoint
|
20
|
+
|
21
|
+
if @@using_enterprise
|
22
|
+
gh_site_url = ask("Please enter your Enterprise site URL (e.g. https://github.company.com):")
|
23
|
+
gh_api_endpoint = ask("Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):")
|
24
|
+
end
|
25
|
+
|
26
|
+
self.class.site_url = gh_site_url
|
27
|
+
self.class.api_endpoint = gh_api_endpoint
|
28
|
+
|
29
|
+
if @@project_only
|
30
|
+
GitReflow::Config.set('reflow.git-server', 'GitHub', local: true)
|
31
|
+
else
|
32
|
+
GitReflow::Config.set('reflow.git-server', 'GitHub')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def authenticate(options = {silent: false})
|
37
|
+
if connection
|
38
|
+
unless options[:silent]
|
39
|
+
puts "Your GitHub account was already setup with: "
|
40
|
+
puts "\tUser Name: #{self.class.user}"
|
41
|
+
puts "\tEndpoint: #{self.class.api_endpoint}"
|
42
|
+
end
|
43
|
+
else
|
44
|
+
begin
|
45
|
+
gh_user = ask("Please enter your GitHub username: ")
|
46
|
+
gh_password = ask("Please enter your GitHub password (we do NOT store this): ") { |q| q.echo = false }
|
47
|
+
|
48
|
+
@connection = ::Github.new do |config|
|
49
|
+
config.basic_auth = "#{gh_user}:#{gh_password}"
|
50
|
+
config.endpoint = GitServer::GitHub.api_endpoint
|
51
|
+
config.site = GitServer::GitHub.site_url
|
52
|
+
config.adapter = :net_http
|
53
|
+
config.ssl = {:verify => false}
|
54
|
+
end
|
55
|
+
|
56
|
+
previous_authorizations = @connection.oauth.all.select {|auth| auth.note == "git-reflow (#{run('hostname', loud: false).strip})" }
|
57
|
+
if previous_authorizations.any?
|
58
|
+
authorization = previous_authorizations.last
|
59
|
+
else
|
60
|
+
authorization = @connection.oauth.create scopes: ['repo'], note: "git-reflow (#{run('hostname', loud: false).strip})"
|
61
|
+
end
|
62
|
+
|
63
|
+
oauth_token = authorization.token
|
64
|
+
|
65
|
+
self.class.oauth_token = oauth_token
|
66
|
+
puts "\nYour GitHub account was successfully setup!"
|
67
|
+
|
68
|
+
rescue StandardError => e
|
69
|
+
puts "\nInvalid username or password: #{e.inspect}"
|
70
|
+
else
|
71
|
+
puts "\nYour GitHub account was successfully setup!"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
@connection
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_pull_request(options = {})
|
79
|
+
pull_request = connection.pull_requests.create(remote_user, remote_repo_name,
|
80
|
+
title: options[:title],
|
81
|
+
body: options[:body],
|
82
|
+
head: "#{remote_user}:#{current_branch}",
|
83
|
+
base: options[:base])
|
84
|
+
end
|
85
|
+
|
86
|
+
def find_pull_request(options = {})
|
87
|
+
connection.pull_requests.all(remote_user, remote_repo_name, base: options[:to], head: "#{remote_user}:#{options[:from]}", :state => 'open').first
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.connection
|
91
|
+
if self.oauth_token.length > 0
|
92
|
+
@connection ||= ::Github.new do |config|
|
93
|
+
config.oauth_token = GitServer::GitHub.oauth_token
|
94
|
+
config.endpoint = GitServer::GitHub.api_endpoint
|
95
|
+
config.site = GitServer::GitHub.site_url
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.user
|
101
|
+
GitReflow::Config.get('github.user')
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.oauth_token
|
105
|
+
GitReflow::Config.get('github.oauth-token')
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.oauth_token=(oauth_token, options = {})
|
109
|
+
GitReflow::Config.set('github.oauth-token', oauth_token, local: @@project_only)
|
110
|
+
oauth_token
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.api_endpoint
|
114
|
+
endpoint = GitReflow::Config.get('github.endpoint')
|
115
|
+
(endpoint.length > 0) ? endpoint : ::Github::Configuration.new.endpoint
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.api_endpoint=(api_endpoint)
|
119
|
+
GitReflow::Config.set("github.endpoint", api_endpoint, local: @@project_only)
|
120
|
+
api_endpoint
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.site_url
|
124
|
+
site_url = GitReflow::Config.get('github.site')
|
125
|
+
(site_url.length > 0) ? site_url : ::Github::Configuration.new.site
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.site_url=(site_url)
|
129
|
+
GitReflow::Config.set("github.site", site_url, local: @@project_only)
|
130
|
+
site_url
|
131
|
+
end
|
132
|
+
|
133
|
+
def connection
|
134
|
+
@connection ||= self.class.connection
|
135
|
+
end
|
136
|
+
|
137
|
+
def pull_request_comments(pull_request)
|
138
|
+
comments = connection.issues.comments.all remote_user, remote_repo_name, number: pull_request.number
|
139
|
+
review_comments = connection.pull_requests.comments.all remote_user, remote_repo_name, number: pull_request.number
|
140
|
+
|
141
|
+
review_comments.to_a + comments.to_a
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_build_status sha
|
145
|
+
connection.repos.statuses.all(remote_user, remote_repo_name, sha).first
|
146
|
+
end
|
147
|
+
|
148
|
+
def colorized_build_description status
|
149
|
+
colorized_statuses = { pending: :yellow, success: :green, error: :red, failure: :red }
|
150
|
+
status.description.colorize( colorized_statuses[status.state.to_sym] )
|
151
|
+
end
|
152
|
+
|
153
|
+
def find_authors_of_open_pull_request_comments(pull_request)
|
154
|
+
# first we'll gather all the authors that have commented on the pull request
|
155
|
+
pull_last_committed_at = get_commited_time(pull_request.head.sha)
|
156
|
+
comment_authors = comment_authors_for_pull_request(pull_request)
|
157
|
+
lgtm_authors = comment_authors_for_pull_request(pull_request, :with => LGTM, :after => pull_last_committed_at)
|
158
|
+
|
159
|
+
comment_authors - lgtm_authors
|
160
|
+
end
|
161
|
+
|
162
|
+
def comment_authors_for_pull_request(pull_request, options = {})
|
163
|
+
all_comments = pull_request_comments(pull_request)
|
164
|
+
comment_authors = []
|
165
|
+
|
166
|
+
all_comments.each do |comment|
|
167
|
+
next if options[:after] and Time.parse(comment.created_at) < options[:after]
|
168
|
+
if (options[:with].nil? or comment[:body] =~ options[:with])
|
169
|
+
comment_authors |= [comment.user.login]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# remove the current user from the list to check
|
174
|
+
comment_authors -= [self.class.user]
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_commited_time(commit_sha)
|
178
|
+
last_commit = connection.repos.commits.find remote_user, remote_repo_name, commit_sha
|
179
|
+
Time.parse last_commit.commit.author[:date]
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GitReflow
|
2
|
+
module GitServer
|
3
|
+
autoload :Base, 'git_reflow/git_server/base'
|
4
|
+
autoload :GitHub, 'git_reflow/git_server/git_hub'
|
5
|
+
|
6
|
+
extend self
|
7
|
+
|
8
|
+
class ConnectionError < StandardError; end
|
9
|
+
|
10
|
+
def connect(options = nil)
|
11
|
+
options ||= { provider: 'GitHub' }
|
12
|
+
begin
|
13
|
+
provider_name = options[:provider]
|
14
|
+
provider = provider_class_for(options.delete(:provider)).new(options)
|
15
|
+
provider.authenticate(options.keep_if {|key, value| key == :silent })
|
16
|
+
provider
|
17
|
+
rescue ConnectionError => e
|
18
|
+
puts "Error connecting to #{provider_name}: #{e.message}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def connection
|
23
|
+
return nil unless current_provider
|
24
|
+
current_provider.connection
|
25
|
+
end
|
26
|
+
|
27
|
+
def current_provider
|
28
|
+
if (provider = GitReflow::Config.get('reflow.git-server')) and provider.length > 0
|
29
|
+
begin
|
30
|
+
provider_class_for(provider)
|
31
|
+
rescue ConnectionError => e
|
32
|
+
puts e.message
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
else
|
36
|
+
puts "[notice] Reflow hasn't been setup yet. Run 'git reflow setup' to continue"
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def can_connect_to?(provider)
|
42
|
+
GitReflow::GitServer.const_defined?(provider)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def provider_class_for(provider)
|
48
|
+
raise ConnectionError, "GitServer not setup for \"#{provider}\"" unless self.can_connect_to?(provider)
|
49
|
+
GitReflow::GitServer.const_get(provider)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module GitReflow
|
2
|
+
module Sandbox
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def run(command, options = {})
|
6
|
+
options = { loud: true }.merge(options)
|
7
|
+
|
8
|
+
if options[:with_system] == true
|
9
|
+
system(command)
|
10
|
+
elsif options[:loud] == true
|
11
|
+
puts `#{command}`
|
12
|
+
else
|
13
|
+
`#{command}`
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_command_with_label(command, options = {})
|
18
|
+
label_color = options.delete(:color) || :green
|
19
|
+
puts command.colorize(label_color)
|
20
|
+
run(command, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# WARNING: this currently only supports OS X and UBUNTU
|
24
|
+
def ask_to_open_in_browser(url)
|
25
|
+
if RUBY_PLATFORM =~ /darwin|linux/i
|
26
|
+
open_in_browser = ask "Would you like to open it in your browser? "
|
27
|
+
if open_in_browser =~ /^y/i
|
28
|
+
if RUBY_PLATFORM =~ /darwin/i
|
29
|
+
# OS X
|
30
|
+
run "open #{url}"
|
31
|
+
else
|
32
|
+
# Ubuntu
|
33
|
+
run "xdg-open #{url}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/git_reflow/version.rb
CHANGED