git-process 1.1.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG.md +14 -1
  2. data/LICENSE +193 -22
  3. data/README.md +212 -71
  4. data/man/git-process.1 +371 -0
  5. metadata +52 -140
  6. data/Gemfile +0 -20
  7. data/Gemfile.lock +0 -53
  8. data/Rakefile +0 -16
  9. data/bin/git-new-fb +0 -58
  10. data/bin/git-pull-request +0 -107
  11. data/bin/git-sync +0 -73
  12. data/bin/git-to-master +0 -133
  13. data/git-process.gemspec +0 -25
  14. data/lib/git-process/abstract_error_builder.rb +0 -53
  15. data/lib/git-process/changed_file_helper.rb +0 -115
  16. data/lib/git-process/git_abstract_merge_error_builder.rb +0 -146
  17. data/lib/git-process/git_branch.rb +0 -105
  18. data/lib/git-process/git_branches.rb +0 -73
  19. data/lib/git-process/git_config.rb +0 -153
  20. data/lib/git-process/git_lib.rb +0 -512
  21. data/lib/git-process/git_logger.rb +0 -84
  22. data/lib/git-process/git_merge_error.rb +0 -28
  23. data/lib/git-process/git_process.rb +0 -172
  24. data/lib/git-process/git_process_error.rb +0 -18
  25. data/lib/git-process/git_process_options.rb +0 -99
  26. data/lib/git-process/git_rebase_error.rb +0 -30
  27. data/lib/git-process/git_remote.rb +0 -256
  28. data/lib/git-process/git_status.rb +0 -108
  29. data/lib/git-process/github_configuration.rb +0 -298
  30. data/lib/git-process/github_pull_request.rb +0 -151
  31. data/lib/git-process/new_fb.rb +0 -50
  32. data/lib/git-process/parked_changes_error.rb +0 -41
  33. data/lib/git-process/pull_request.rb +0 -134
  34. data/lib/git-process/pull_request_error.rb +0 -25
  35. data/lib/git-process/rebase_to_master.rb +0 -148
  36. data/lib/git-process/sync.rb +0 -136
  37. data/lib/git-process/uncommitted_changes_error.rb +0 -23
  38. data/lib/git-process/version.rb +0 -22
  39. data/spec/FileHelpers.rb +0 -19
  40. data/spec/GitRepoHelper.rb +0 -123
  41. data/spec/changed_file_helper_spec.rb +0 -127
  42. data/spec/git_abstract_merge_error_builder_spec.rb +0 -126
  43. data/spec/git_branch_spec.rb +0 -123
  44. data/spec/git_config_spec.rb +0 -45
  45. data/spec/git_lib_spec.rb +0 -176
  46. data/spec/git_logger_spec.rb +0 -66
  47. data/spec/git_process_spec.rb +0 -208
  48. data/spec/git_remote_spec.rb +0 -227
  49. data/spec/git_status_spec.rb +0 -122
  50. data/spec/github_configuration_spec.rb +0 -152
  51. data/spec/github_pull_request_spec.rb +0 -96
  52. data/spec/github_test_helper.rb +0 -49
  53. data/spec/new_fb_spec.rb +0 -130
  54. data/spec/pull_request_helper.rb +0 -94
  55. data/spec/pull_request_spec.rb +0 -128
  56. data/spec/rebase_to_master_spec.rb +0 -429
  57. data/spec/spec_helper.rb +0 -21
  58. data/spec/sync_spec.rb +0 -304
@@ -1,108 +0,0 @@
1
- # Licensed under the Apache License, Version 2.0 (the "License");
2
- # you may not use this file except in compliance with the License.
3
- # You may obtain a copy of the License at
4
- #
5
- # http://www.apache.org/licenses/LICENSE-2.0
6
- #
7
- # Unless required by applicable law or agreed to in writing, software
8
- # distributed under the License is distributed on an "AS IS" BASIS,
9
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
- # See the License for the specific language governing permissions and
11
- # limitations under the License.
12
-
13
- module GitProc
14
-
15
- #
16
- # The status of the Git repository.
17
- #
18
- # @!attribute [r] unmerged
19
- # @return [Enumerable] a sorted list of unmerged files
20
- # @!attribute [r] modified
21
- # @return [Enumerable] a sorted list of modified files
22
- # @!attribute [r] deleted
23
- # @return [Enumerable] a sorted list of deleted files
24
- # @!attribute [r] added
25
- # @return [Enumerable] a sorted list of files that have been added
26
- # @!attribute [r] unknown
27
- # @return [Enumerable] a sorted list of unknown files
28
- class GitStatus
29
- attr_reader :unmerged, :modified, :deleted, :added, :unknown
30
-
31
-
32
- def initialize(lib)
33
- unmerged = []
34
- modified = []
35
- deleted = []
36
- added = []
37
- unknown = []
38
-
39
- stats = lib.porcelain_status.split("\n")
40
-
41
- stats.each do |s|
42
- stat = s[0..1]
43
- file = s[3..-1]
44
- #puts "stat #{stat} - #{file}"
45
- f = unquote(file)
46
- case stat
47
- when 'U ', ' U'
48
- unmerged << f
49
- when 'UU'
50
- unmerged << f
51
- modified << f
52
- when 'M ', ' M', 'MM'
53
- modified << f
54
- when 'MD'
55
- modified << f
56
- deleted << f
57
- when 'D ', ' D', 'DD'
58
- deleted << f
59
- when 'DU', 'UD'
60
- deleted << f
61
- unmerged << f
62
- when 'A ', ' A'
63
- added << f
64
- when 'AD'
65
- added << f
66
- deleted << f
67
- when 'AA', 'AU', 'UA'
68
- added << f
69
- unmerged << f
70
- when 'AM', 'MA'
71
- added << f
72
- modified << f
73
- when '??', '!!'
74
- unknown << f
75
- when 'R '
76
- old_file, new_file = file.split(' -> ')
77
- deleted << unquote(old_file)
78
- added << unquote(new_file)
79
- when 'C '
80
- old_file, new_file = file.split(' -> ')
81
- added << unquote(old_file)
82
- added << unquote(new_file)
83
- else
84
- raise "Do not know what to do with status #{stat} - #{file}"
85
- end
86
- end
87
-
88
- @unmerged = unmerged.sort.uniq.freeze
89
- @modified = modified.sort.uniq.freeze
90
- @deleted = deleted.sort.uniq.freeze
91
- @added = added.sort.uniq.freeze
92
- @unknown = unknown.sort.uniq.freeze
93
- end
94
-
95
-
96
- def unquote(file)
97
- file.match(/^"?(.*?)"?$/)[1]
98
- end
99
-
100
-
101
- # @return [Boolean] are there any changes in the index or working directory?
102
- def clean?
103
- @unmerged.empty? and @modified.empty? and @deleted.empty? and @added.empty? and @unknown.empty?
104
- end
105
-
106
- end
107
-
108
- end
@@ -1,298 +0,0 @@
1
- # Licensed under the Apache License, Version 2.0 (the "License");
2
- # you may not use this file except in compliance with the License.
3
- # You may obtain a copy of the License at
4
- #
5
- # http://www.apache.org/licenses/LICENSE-2.0
6
- #
7
- # Unless required by applicable law or agreed to in writing, software
8
- # distributed under the License is distributed on an "AS IS" BASIS,
9
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
- # See the License for the specific language governing permissions and
11
- # limitations under the License.
12
-
13
- require 'git-process/git_lib'
14
- require 'highline/import'
15
- require 'octokit'
16
- require 'uri'
17
-
18
-
19
- #
20
- # Provides methods related to GitHub configuration
21
- #
22
- module GitHubService
23
-
24
- class Configuration
25
-
26
- attr_reader :git_config
27
-
28
-
29
- #
30
- # @param [GitProc::GitConfig] git_config
31
- # @param [Hash] opts
32
- # @option opts [String] :remote_name (#remote_name) The "remote" name to use (e.g., 'origin')
33
- # @option opts [String] :user the username to authenticate with
34
- # @option opts [String] :password (#password) the password to authenticate with
35
- #
36
- # @return [String] the OAuth token
37
- #
38
- def initialize(git_config, opts = {})
39
- @git_config = git_config
40
- @user = opts[:user]
41
- @password = opts[:password]
42
- @remote_name = opts[:remote_name]
43
- end
44
-
45
-
46
- # @return [String]
47
- def remote_name
48
- unless @remote_name
49
- @remote_name = gitlib.remote.name
50
- raise NoRemoteRepository.new('No remote repository is defined') unless @remote_name
51
- end
52
- @remote_name
53
- end
54
-
55
-
56
- # @return [String]
57
- def user
58
- @user ||= Configuration.ask_for_user(gitlib)
59
- end
60
-
61
-
62
- # @return [String]
63
- def password
64
- @password ||= Configuration.ask_for_password
65
- end
66
-
67
-
68
- # @return [Octokit::Client]
69
- def client
70
- create_client
71
- end
72
-
73
-
74
- # @return [GitProc::GitLib]
75
- def gitlib
76
- @git_config.gitlib
77
- end
78
-
79
-
80
- # @return [Octokit::Client]
81
- def create_client(opts = {})
82
- logger.debug { "Creating GitHub client for user #{user} using token '#{auth_token}'" }
83
-
84
- base_url = opts[:base_url] || base_github_api_url_for_remote
85
-
86
- configure_octokit(:base_url => base_url)
87
-
88
- Octokit::Client.new(:login => user, :oauth_token => auth_token)
89
- end
90
-
91
-
92
- #
93
- # Configures Octokit to use the appropriate URLs for GitHub server.
94
- #
95
- # @param [Hash] opts the options to create a message with
96
- # @option opts [String] :base_url The base URL to use for the GitHub server
97
- #
98
- # @return [void]
99
- #
100
- def configure_octokit(opts = {})
101
- base_url = opts[:base_url] || base_github_api_url_for_remote
102
- Octokit.configure do |c|
103
- c.api_endpoint = api_endpoint(base_url)
104
- c.web_endpoint = web_endpoint(base_url)
105
- c.faraday_config do |f|
106
- #f.response :logger
107
- end
108
- end
109
- end
110
-
111
-
112
- #
113
- # Determines the URL used for using the GitHub REST interface based
114
- # on a "base" URL.
115
- #
116
- # If the "base_url" is not provided, then it assumes that this object
117
- # has a "remote_name" property that it can ask.
118
- #
119
- # @param [String] base_url the base GitHub URL
120
- # @return [String] the GitHub REST API URL
121
- #
122
- def api_endpoint(base_url = nil)
123
- base_url ||= base_github_api_url_for_remote
124
- if /github.com/ !~ base_url
125
- "#{base_url}/api/v3"
126
- else
127
- Octokit::Configuration::DEFAULT_API_ENDPOINT
128
- end
129
- end
130
-
131
-
132
- #
133
- # Determines the URL used for using the GitHub web interface based
134
- # on a "base" URL.
135
- #
136
- # If the "base_url" is not provided, then it assumes that this object
137
- # has a "remote_name" property that it can ask.
138
- #
139
- # @param [String] base_url the base GitHub URL
140
- # @return [String] the GitHub web URL
141
- #
142
- def web_endpoint(base_url = nil)
143
- base_url ||= base_github_api_url_for_remote
144
- if /github.com/ !~ base_url
145
- base_url
146
- else
147
- Octokit::Configuration::DEFAULT_WEB_ENDPOINT
148
- end
149
- end
150
-
151
-
152
- #
153
- # Determines the base URL for GitHub API calls.
154
- #
155
- # @return [String] the base GitHub API URL
156
- #
157
- def base_github_api_url_for_remote
158
- url = gitlib.remote.expanded_url(remote_name)
159
- Configuration.url_to_base_github_api_url(url)
160
- end
161
-
162
-
163
- #
164
- # Translate any "git known" URL to the HTTP(S) URL needed for
165
- # GitHub API calls.
166
- #
167
- # @param url [String] the URL to translate
168
- # @return [String] the base GitHub API URL
169
- #
170
- def self.url_to_base_github_api_url(url)
171
- uri = URI.parse(url)
172
- host = uri.host
173
-
174
- if /github.com$/ =~ host
175
- 'https://api.github.com'
176
- else
177
- scheme = uri.scheme
178
- scheme = 'https' unless scheme.start_with?('http')
179
- host = 'unknown-host' unless host
180
- "#{scheme}://#{host}"
181
- end
182
- end
183
-
184
-
185
- #
186
- # Create a GitHub client using username and password specifically.
187
- # Meant to be used to get an OAuth token for "regular" client calls.
188
- #
189
- # @param [Hash] opts the options to create a message with
190
- # @option opts [String] :base_url The base URL to use for the GitHub server
191
- # @option opts [String] :remote_name (#remote_name) The "remote" name to use (e.g., 'origin')
192
- # @option opts [String] :user the username to authenticate with
193
- # @option opts [String] :password (#password) the password to authenticate with
194
- #
195
- def create_pw_client(opts = {})
196
- usr = opts[:user] || user()
197
- pw = opts[:password] || password()
198
-
199
- logger.debug { "Creating GitHub client for user #{usr} using BasicAuth w/ password" }
200
-
201
- configure_octokit(opts)
202
-
203
- Octokit::Client.new(:login => usr, :password => pw)
204
- end
205
-
206
-
207
- #
208
- # Returns to OAuth token. If it's in .git/config, returns that.
209
- # Otherwise it connects to GitHub to get the authorization token.
210
- #
211
- # @param [Hash] opts
212
- # @option opts [String] :base_url The base URL to use for the GitHub server
213
- # @option opts [String] :remote_name (#remote_name) The "remote" name to use (e.g., 'origin')
214
- # @option opts [String] :user the username to authenticate with
215
- # @option opts [String] :password (#password) the password to authenticate with
216
- #
217
- # @return [String]
218
- #
219
- def auth_token(opts = {})
220
- get_config_auth_token() || create_authorization(opts)
221
- end
222
-
223
-
224
- #
225
- # Connects to GitHub to get an OAuth token.
226
- #
227
- # @param [Hash] opts
228
- # @option opts [String] :base_url The base URL to use for the GitHub server
229
- # @option opts [String] :remote_name (#remote_name) The "remote" name to use (e.g., 'origin')
230
- # @option opts [String] :user the username to authenticate with
231
- # @option opts [String] :password (#password) the password to authenticate with
232
- #
233
- # @return [String] the OAuth token
234
- #
235
- def create_authorization(opts = {})
236
- username = opts[:user] || self.user
237
- remote = opts[:remote_name] || self.remote_name
238
- logger.info("Authorizing #{username} to work with #{remote}.")
239
-
240
- auth = create_pw_client(opts).create_authorization(
241
- :scopes => %w(repo user gist),
242
- :note => 'Git-Process',
243
- :note_url => 'http://jdigger.github.com/git-process')
244
-
245
- config_auth_token = auth['token']
246
-
247
- # remember it for next time
248
- gitlib.config['gitProcess.github.authToken'] = config_auth_token
249
-
250
- config_auth_token
251
- end
252
-
253
-
254
- # @return [String]
255
- def get_config_auth_token
256
- c_auth_token = gitlib.config['gitProcess.github.authToken']
257
- (c_auth_token.nil? or c_auth_token.empty?) ? nil : c_auth_token
258
- end
259
-
260
-
261
- def logger
262
- gitlib.logger
263
- end
264
-
265
-
266
- private
267
-
268
-
269
- def self.ask_for_user(gitlib)
270
- user = gitlib.config['github.user']
271
- if user.nil? or user.empty?
272
- user = ask("Your <%= color('GitHub', [:bold, :blue]) %> username: ") do |q|
273
- q.validate = /^\w\w+$/
274
- end
275
- gitlib.config['github.user'] = user
276
- end
277
- user
278
- end
279
-
280
-
281
- def self.ask_for_password
282
- ask("Your <%= color('GitHub', [:bold, :blue]) %> password: ") do |q|
283
- q.validate = /^\S\S+$/
284
- q.echo = 'x'
285
- end
286
- end
287
-
288
- end
289
-
290
-
291
- class Error < ::StandardError
292
- end
293
-
294
-
295
- class NoRemoteRepository < Error
296
- end
297
-
298
- end
@@ -1,151 +0,0 @@
1
- # Licensed under the Apache License, Version 2.0 (the "License");
2
- # you may not use this file except in compliance with the License.
3
- # You may obtain a copy of the License at
4
- #
5
- # http://www.apache.org/licenses/LICENSE-2.0
6
- #
7
- # Unless required by applicable law or agreed to in writing, software
8
- # distributed under the License is distributed on an "AS IS" BASIS,
9
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
- # See the License for the specific language governing permissions and
11
- # limitations under the License.
12
-
13
- require 'git-process/github_configuration'
14
- require 'octokit'
15
- require 'octokit/repository'
16
-
17
-
18
- module GitHub
19
-
20
- class PullRequest
21
- attr_reader :gitlib, :repo, :remote_name, :client, :configuration
22
-
23
-
24
- def initialize(lib, remote_name, repo, opts = {})
25
- @gitlib = lib
26
- @repo = repo
27
- @remote_name = remote_name
28
- @configuration = GitHubService::Configuration.new(gitlib.config, :user => opts[:user], :password => opts[:password])
29
- end
30
-
31
-
32
- def client
33
- @client ||= @configuration.create_client
34
- end
35
-
36
-
37
- def pull_requests(state = 'open', opts = {})
38
- @pull_requests ||= client.pull_requests(repo, state, opts)
39
- end
40
-
41
-
42
- def create(base, head, title, body)
43
- logger.info { "Creating a pull request asking for '#{head}' to be merged into '#{base}' on #{repo}." }
44
- begin
45
- client.create_pull_request(repo, base, head, title, body)
46
- rescue Octokit::UnprocessableEntity => exp
47
- pull = pull_requests.find { |p| p[:head][:ref] == head and p[:base][:ref] == base }
48
- if pull
49
- logger.warn { "Pull request already exists. See #{pull[:html_url]}" }
50
- else
51
- logger.warn { "UnprocessableEntity: #{exp}" }
52
- end
53
- pull
54
- end
55
- end
56
-
57
-
58
- def logger
59
- @gitlib.logger
60
- end
61
-
62
-
63
- def pull_request(pr_number)
64
- client.pull_request(repo, pr_number)
65
- end
66
-
67
-
68
- #
69
- # Find the pull request (PR) that matches the 'head' and 'base'.
70
- #
71
- # @param [String] base what the PR is merging into
72
- # @param [String] head the branch of the PR
73
- #
74
- # @return [Hash]
75
- # @raise [NotFoundError] if the pull request does not exist
76
- #
77
- def get_pull_request(base, head)
78
- find_pull_request(base, head, true)
79
- end
80
-
81
-
82
- #
83
- # Find the pull request (PR) that matches the 'head' and 'base'.
84
- #
85
- # @param [String] base what the PR is merging into
86
- # @param [String] head the branch of the PR
87
- # @param [boolean] error_if_missing should this error-out if the PR is not found?
88
- #
89
- # @return [Hash, nil]
90
- # @raise [NotFoundError] if the pull request does not exist and 'error_if_missing' is true
91
- #
92
- def find_pull_request(base, head, error_if_missing = false)
93
- logger.info { "Looking for a pull request asking for '#{head}' to be merged into '#{base}' on #{repo}." }
94
-
95
- json = pull_requests
96
- pr = json.find { |p| p[:head][:ref] == head and p[:base][:ref] == base }
97
-
98
- raise NotFoundError.new(base, head, repo, json) if error_if_missing && pr.nil?
99
-
100
- pr
101
- end
102
-
103
-
104
- def close(*args)
105
- pull_number = if args.size == 2
106
- get_pull_request(args[0], args[1])[:number]
107
- elsif args.size == 1
108
- args[0]
109
- else
110
- raise ArgumentError.new('close(..) needs 1 or 2 arguments')
111
- end
112
-
113
- logger.info { "Closing a pull request \##{pull_number} on #{repo}." }
114
-
115
- client.patch("repos/#{Octokit::Repository.new(repo)}/pulls/#{pull_number}", {:state => 'closed'})
116
- end
117
-
118
-
119
- class NotFoundError < StandardError
120
- attr_reader :base, :head, :repo
121
-
122
-
123
- def initialize(base, head, repo, pull_requests_json)
124
- @base = base
125
- @head = head
126
- @repo = repo
127
-
128
- @pull_requests = pull_requests_json.map do |p|
129
- {:head => p[:head][:ref], :base => p[:base][:ref]}
130
- end
131
-
132
- msg = "Could not find a pull request for '#{head}' to be merged with '#{base}' on #{repo}."
133
- msg += "\n\nExisting Pull Requests:"
134
- msg = pull_requests.inject(msg) { |a, v| "#{a}\n #{v[:head]} -> #{v[:base]}" }
135
-
136
- super(msg)
137
- end
138
-
139
-
140
- def pull_requests
141
- @pull_requests
142
- end
143
-
144
- end
145
-
146
- private
147
-
148
-
149
- end
150
-
151
- end