gist 4.5.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 687ff483f835c421449de703f4b33a8ec8341ed7
4
- data.tar.gz: f5f46207b5e3cf3aa7d05253eb7f0f946e5429b3
2
+ SHA256:
3
+ metadata.gz: 78e3d009d0e3e3a535d20e8d7e0582705c6ea61308958c3f59a4d4a2e365fa3c
4
+ data.tar.gz: 23df778298090151ce7e2b8f3dbb8f97786bc7d576f218be1aeb454123090e91
5
5
  SHA512:
6
- metadata.gz: 903fd99ebdfc68873b338965fc03cc2f7bb1aa08acf22d6f16c8c12aeb736df1fec1d798419f1a734b2b26177869514f4c7125610419d66347f3e8338a1afdcc
7
- data.tar.gz: 8261a612326028a57aad653ba0889f004c20d6183658f4068736fdfa6f30466cac978912fe96e443b20a1ca99b8e9aeb3e9693913234650934006a9c0e2012f5
6
+ metadata.gz: 70506cc45562b725085e2f10d5627a3ac4c700fa6e599e39a6625629fbd2c63903b2d42a4a95d9642f0ac01893bd8de27d72acb7e4622eaa44ab4ea96b08840c
7
+ data.tar.gz: b3476f46cb844603a169e3a67fae3bb37e5399494ddec6c78178f4bb664a90cda642c5be780ea007d12e96cc96312f695b86827872bc4947603c092a4e3d6774
data/README.md CHANGED
@@ -21,6 +21,11 @@ upload content to https://gist.github.com/.
21
21
 
22
22
  brew install gist
23
23
 
24
+ ‌For FreeBSD, gist lives in ports
25
+
26
+ pkg install gist
27
+
28
+
24
29
  ## Command
25
30
 
26
31
  ‌To upload the contents of `a.rb` just:
@@ -70,30 +75,88 @@ upload content to https://gist.github.com/.
70
75
  gist -l : all gists for authed user
71
76
  gist -l defunkt : list defunkt's public gists
72
77
 
78
+ To read a gist and print it to STDOUT
79
+
80
+ gist -r GIST_ID
81
+ gist -r 374130
82
+
73
83
  ‌See `gist --help` for more detail.
74
84
 
75
85
  ## Login
76
86
 
77
- If you want to associate your gists with your GitHub account, you need to login
78
- with gist. It doesn't store your username and password, it just uses them to get
79
- an OAuth2 token (with the "gist" permission).
87
+ Before you use `gist` for the first time you will need to log in. There are two supported login flows:
88
+
89
+ 1. The Github device-code Oauth flow. This is the default for authenticating to github.com, and can be enabled for Github Enterprise by creating an Oauth app, and exporting the environment variable `GIST_CLIENT_ID` with the client id of the Oauth app.
90
+ 2. The (deprecated) username and password token exchange flow. This is the default for GitHub Enterprise, and can be used to log into github.com by exporting the environment variable `GIST_USE_USERNAME_AND_PASSWORD`.
91
+
92
+ ### The device-code flow
93
+
94
+ This flow allows you to obtain a token by logging into GitHub in the browser and typing a verification code. This is the preferred mechanism.
80
95
 
81
96
  gist --login
82
- Obtaining OAuth2 access_token from github.
97
+ Requesting login parameters...
98
+ Please sign in at https://github.com/login/device
99
+ and enter code: XXXX-XXXX
100
+ Success! https://github.com/settings/connections/applications/4f7ec0d4eab38e74384e
101
+
102
+ The returned access_token is stored in `~/.gist` and used for all future gisting. If you need to you can revoke access from https://github.com/settings/connections/applications/4f7ec0d4eab38e74384e.
103
+
104
+ ### The username-password flow
105
+
106
+ This flow asks for your GitHub username and password (and 2FA code), and exchanges them for a token with the "gist" permission (your username and password are not stored). This mechanism is deprecated by GitHub, but may still work with GitHub Enterprise.
107
+
108
+ gist --login
109
+ Obtaining OAuth2 access_token from GitHub.
83
110
  GitHub username: ConradIrwin
84
111
  GitHub password:
85
112
  2-factor auth code:
86
- Success! https://github.com/settings/applications
113
+ Success! https://github.com/settings/tokens
87
114
 
88
115
  This token is stored in `~/.gist` and used for all future gisting. If you need to
89
- you can revoke it from https://github.com/settings/applications, or just delete the
90
- file. If you need to store tokens for both github.com and a Github Enterprise instance
91
- you can save your Github Enterprise token in `~/.gist.github.example.com` where
92
- "github.example.com" is the URL for your Github Enterprise instance.
116
+ you can revoke it from https://github.com/settings/tokens, or just delete the
117
+ file.
118
+
119
+ #### Password-less login
120
+
121
+ If you have a complicated authorization requirement you can manually create a
122
+ token file by pasting a GitHub token with `gist` scope (and maybe the `user:email`
123
+ for GitHub Enterprise) into a file called `~/.gist`. You can create one from
124
+ https://github.com/settings/tokens
125
+
126
+ This file should contain only the token (~40 hex characters), and to make it
127
+ easier to edit, can optionally have a final newline (`\n` or `\r\n`).
93
128
 
94
- ‌After you've done this, you can still upload gists anonymously with `-a`.
129
+ For example, one way to create this file would be to run:
95
130
 
96
- gist -a a.rb
131
+ (umask 0077 && echo MY_SECRET_TOKEN > ~/.gist)
132
+
133
+ The `umask` ensures that the file is only accessible from your user account.
134
+
135
+ ### GitHub Enterprise
136
+
137
+ If you'd like `gist` to use your locally installed [GitHub Enterprise](https://enterprise.github.com/),
138
+ you need to export the `GITHUB_URL` environment variable (usually done in your `~/.bashrc`).
139
+
140
+ export GITHUB_URL=http://github.internal.example.com/
141
+
142
+ Once you've done this and restarted your terminal (or run `source ~/.bashrc`), gist will
143
+ automatically use GitHub Enterprise instead of the public github.com
144
+
145
+ Your token for GitHub Enterprise will be stored in `.gist.<protocol>.<server.name>[.<port>]` (e.g.
146
+ `~/.gist.http.github.internal.example.com` for the GITHUB_URL example above) instead of `~/.gist`.
147
+
148
+ If you have multiple servers or use Enterprise and public GitHub often, you can work around this by creating scripts
149
+ that set the env var and then run `gist`. Keep in mind that to use the public GitHub you must unset the env var. Just
150
+ setting it to the public URL will not work. Use `unset GITHUB_URL`
151
+
152
+ ### Token file format
153
+
154
+ If you cannot use passwords, as most Enterprise installations do, you can generate the token via the web interface
155
+ and then simply save the string in the correct file. Avoid line breaks or you might see:
156
+ ```
157
+ $ gist -l
158
+ Error: Bad credentials
159
+ ```
97
160
 
98
161
  # Library
99
162
 
@@ -108,11 +171,10 @@ If you need more advanced features you can also pass:
108
171
  * `:public` if you want your gist to have a guessable url.
109
172
  * `:description` to add a description to your gist.
110
173
  * `:update` to update an existing gist (can be a URL or an id).
111
- * `:anonymous` to submit an anonymous gist (default is false).
112
174
  * `:copy` to copy the resulting URL to the clipboard (default is false).
113
175
  * `:open` to open the resulting URL in a browser (default is false).
114
176
 
115
- NOTE: The access_token must have the "gist" scope.
177
+ NOTE: The access_token must have the `gist` scope and may also require the `user:email` scope.
116
178
 
117
179
  ‌If you want to upload multiple files in the same gist, you can:
118
180
 
@@ -126,16 +188,6 @@ NOTE: The access_token must have the "gist" scope.
126
188
  ‌This will take them through the process of obtaining an OAuth2 token, and storing it
127
189
  in `~/.gist`, where it can later be read by `Gist.gist`
128
190
 
129
- ## GitHub enterprise
130
-
131
- ‌If you'd like `gist` to use your locally installed [GitHub Enterprise](https://enterprise.github.com/),
132
- you need to export the `GITHUB_URL` environment variable in your `~/.bashrc`.
133
-
134
- export GITHUB_URL=http://github.internal.example.com/
135
-
136
- ‌Once you've done this and restarted your terminal (or run `source ~/.bashrc`), gist will
137
- automatically use github enterprise instead of the public github.com
138
-
139
191
  ## Configuration
140
192
 
141
193
  ‌If you'd like `-o` or `-c` to be the default when you use the gist executable, add an
data/bin/gist CHANGED
@@ -24,16 +24,12 @@ specified STDIN will be read. The default filename for STDIN is "a.rb", and all
24
24
  filenames can be overridden by repeating the "-f" flag. The most useful reason
25
25
  to do this is to change the syntax highlighting.
26
26
 
27
- If you'd like your gists to be associated with your GitHub account, so that you
28
- can edit them and find them in future, first use `gist --login` to obtain an
29
- Oauth2 access token. This is stored and used by gist in the future.
27
+ All gists must to be associated with a GitHub account, so you will need to login with
28
+ `gist --login` to obtain an OAuth2 access token. This is stored and used by gist in the future.
30
29
 
31
30
  Private gists do not have guessable URLs and can be created with "-p", you can
32
31
  also set the description at the top of the gist by passing "-d".
33
32
 
34
- Anonymous gists are not associated with your GitHub account, they can be created
35
- with "-a" even after you have used "gist --login".
36
-
37
33
  If you would like to shorten the resulting gist URL, use the -s flag. This will
38
34
  use GitHub's URL shortener, git.io. You can also use -R to get the link to the
39
35
  raw gist.
@@ -47,7 +43,11 @@ Instead of creating a new gist, you can update an existing one by passing its ID
47
43
  or URL with "-u". For this to work, you must be logged in, and have created the
48
44
  original gist with the same GitHub account.
49
45
 
50
- Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P] [-f NAME|-t EXT]* FILE*
46
+ If you want to skip empty files, use the --skip-empty flag. If all files are
47
+ empty no gist will be created.
48
+
49
+ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-u URL]
50
+ [--skip-empty] [-P] [-f NAME|-t EXT]* FILE*
51
51
  #{executable_name} --login
52
52
  #{executable_name} [-l|-r]
53
53
 
@@ -88,10 +88,6 @@ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P]
88
88
  options[:update] = update
89
89
  end
90
90
 
91
- opts.on("-a", "--anonymous", "Create an anonymous gist.") do
92
- options[:anonymous] = true
93
- end
94
-
95
91
  opts.on("-c", "--copy", "Copy the resulting URL to the clipboard") do
96
92
  options[:copy] = true
97
93
  end
@@ -107,6 +103,10 @@ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P]
107
103
 
108
104
  opts.on("--no-open")
109
105
 
106
+ opts.on("--skip-empty", "Skip gisting empty files") do
107
+ options[:skip_empty] = true
108
+ end
109
+
110
110
  opts.on("-P", "--paste", "Paste from the clipboard to gist") do
111
111
  options[:paste] = true
112
112
  end
@@ -123,6 +123,10 @@ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P]
123
123
  options[:read] = id
124
124
  end
125
125
 
126
+ opts.on("--delete [ URL | ID ]", "Delete a gist") do |id|
127
+ options[:delete] = id
128
+ end
129
+
126
130
  opts.on_tail("-h","--help", "Show this message.") do
127
131
  puts opts
128
132
  exit
@@ -136,6 +140,12 @@ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P]
136
140
  end.parse!
137
141
 
138
142
  begin
143
+ if Gist.auth_token.nil?
144
+ puts 'Please log in with `gist --login`. ' \
145
+ '(GitHub now requires credentials to gist https://bit.ly/2GBBxKw)'
146
+ exit(1)
147
+ end
148
+
139
149
  options[:output] = if options[:embed] && options[:shorten]
140
150
  raise Gist::Error, "--embed does not make sense with --shorten"
141
151
  elsif options[:embed]
@@ -167,6 +177,11 @@ begin
167
177
  exit
168
178
  end
169
179
 
180
+ if options.key? :delete
181
+ Gist.delete_gist(options[:delete])
182
+ exit
183
+ end
184
+
170
185
  if options[:paste]
171
186
  puts Gist.gist(Gist.paste, options)
172
187
  else
@@ -186,7 +201,8 @@ begin
186
201
  end
187
202
  end
188
203
 
189
- puts Gist.multi_gist(files, options)
204
+ output = Gist.multi_gist(files, options)
205
+ puts output if output
190
206
  end
191
207
 
192
208
  rescue Gist::Error => e
data/gist.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.email = ['conrad.irwin@gmail.com', 'rkingist@sharpsaw.org']
10
10
  s.authors = ['Conrad Irwin', '☈king']
11
11
  s.license = 'MIT'
12
- s.files = `git ls-files`.split("\n")
12
+ s.files = `git ls-files`.split("\n") - Dir.glob("build/*") - [".gitignore"]
13
13
  s.require_paths = ["lib"]
14
14
 
15
15
  s.executables << 'gist'
data/lib/gist.rb CHANGED
@@ -12,23 +12,27 @@ end
12
12
  module Gist
13
13
  extend self
14
14
 
15
- VERSION = '4.5.0'
15
+ VERSION = '6.0.0'
16
16
 
17
17
  # A list of clipboard commands with copy and paste support.
18
18
  CLIPBOARD_COMMANDS = {
19
+ 'pbcopy' => 'pbpaste',
19
20
  'xclip' => 'xclip -o',
20
21
  'xsel -i' => 'xsel -o',
21
- 'pbcopy' => 'pbpaste',
22
- 'putclip' => 'getclip'
22
+ 'putclip' => 'getclip',
23
23
  }
24
24
 
25
25
  GITHUB_API_URL = URI("https://api.github.com/")
26
- GIT_IO_URL = URI("http://git.io")
26
+ GITHUB_URL = URI("https://github.com/")
27
+ GIT_IO_URL = URI("https://git.io")
27
28
 
28
29
  GITHUB_BASE_PATH = ""
29
30
  GHE_BASE_PATH = "/api/v3"
30
31
 
32
+ GITHUB_CLIENT_ID = '4f7ec0d4eab38e74384e'
33
+
31
34
  URL_ENV_NAME = "GITHUB_URL"
35
+ CLIENT_ID_ENV_NAME = "GIST_CLIENT_ID"
32
36
 
33
37
  USER_AGENT = "gist/#{VERSION} (Net::HTTP, #{RUBY_DESCRIPTION})"
34
38
 
@@ -44,7 +48,7 @@ module Gist
44
48
  module AuthTokenFile
45
49
  def self.filename
46
50
  if ENV.key?(URL_ENV_NAME)
47
- File.expand_path "~/.gist.#{ENV[URL_ENV_NAME].gsub(/[^a-z.]/, '')}"
51
+ File.expand_path "~/.gist.#{ENV[URL_ENV_NAME].gsub(/:/, '.').gsub(/[^a-z0-9.-]/, '')}"
48
52
  else
49
53
  File.expand_path "~/.gist"
50
54
  end
@@ -76,10 +80,14 @@ module Gist
76
80
  #
77
81
  # @see http://developer.github.com/v3/gists/
78
82
  def gist(content, options = {})
79
- filename = options[:filename] || "a.rb"
83
+ filename = options[:filename] || default_filename
80
84
  multi_gist({filename => content}, options)
81
85
  end
82
86
 
87
+ def default_filename
88
+ "gistfile1.txt"
89
+ end
90
+
83
91
  # Upload a gist to https://gist.github.com
84
92
  #
85
93
  # @param [Hash] files the code you'd like to gist: filename => content
@@ -92,6 +100,7 @@ module Gist
92
100
  # @option options [String] :update the URL or id of a gist to update
93
101
  # @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
94
102
  # @option options [Boolean] :open (false) Open the resulting URL in a browser.
103
+ # @option options [Boolean] :skip_empty (false) Skip gisting empty files.
95
104
  # @option options [Symbol] :output (:all) The type of return value you'd like:
96
105
  # :html_url gives a String containing the url to the gist in a browser
97
106
  # :short_url gives a String contianing a git.io url that redirects to html_url
@@ -103,6 +112,13 @@ module Gist
103
112
  #
104
113
  # @see http://developer.github.com/v3/gists/
105
114
  def multi_gist(files, options={})
115
+ if options[:anonymous]
116
+ raise 'Anonymous gists are no longer supported. Please log in with `gist --login`. ' \
117
+ '(GitHub now requires credentials to gist https://bit.ly/2GBBxKw)'
118
+ else
119
+ access_token = (options[:access_token] || auth_token())
120
+ end
121
+
106
122
  json = {}
107
123
 
108
124
  json[:description] = options[:description] if options[:description]
@@ -110,22 +126,23 @@ module Gist
110
126
  json[:files] = {}
111
127
 
112
128
  files.each_pair do |(name, content)|
113
- raise "Cannot gist empty files" if content.to_s.strip == ""
114
- json[:files][File.basename(name)] = {:content => content}
129
+ if content.to_s.strip == ""
130
+ raise "Cannot gist empty files" unless options[:skip_empty]
131
+ else
132
+ name = name == "-" ? default_filename : File.basename(name)
133
+ json[:files][name] = {:content => content}
134
+ end
115
135
  end
116
136
 
137
+ return if json[:files].empty? && options[:skip_empty]
138
+
117
139
  existing_gist = options[:update].to_s.split("/").last
118
- if options[:anonymous]
119
- access_token = nil
120
- else
121
- access_token = (options[:access_token] || auth_token())
122
- end
123
140
 
124
141
  url = "#{base_path}/gists"
125
142
  url << "/" << CGI.escape(existing_gist) if existing_gist.to_s != ''
126
- url << "?access_token=" << CGI.escape(access_token) if access_token.to_s != ''
127
143
 
128
144
  request = Net::HTTP::Post.new(url)
145
+ request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
129
146
  request.body = JSON.dump(json)
130
147
  request.content_type = 'application/json'
131
148
 
@@ -161,9 +178,10 @@ module Gist
161
178
  if user == ""
162
179
  access_token = auth_token()
163
180
  if access_token.to_s != ''
164
- url << "/gists?access_token=" << CGI.escape(access_token)
181
+ url << "/gists"
165
182
 
166
183
  request = Net::HTTP::Get.new(url)
184
+ request['Authorization'] = "token #{access_token}"
167
185
  response = http(api_url, request)
168
186
 
169
187
  pretty_gist(response)
@@ -186,24 +204,21 @@ module Gist
186
204
  url = "#{base_path}"
187
205
 
188
206
  if user == ""
189
- access_token = auth_token()
190
- if access_token.to_s != ''
191
- url << "/gists?per_page=100&access_token=" << CGI.escape(access_token)
192
- get_gist_pages(url)
193
- else
194
- raise Error, "Not authenticated. Use 'gist --login' to login or 'gist -l username' to view public gists."
195
- end
196
-
207
+ url << "/gists?per_page=100"
197
208
  else
198
209
  url << "/users/#{user}/gists?per_page=100"
199
- get_gist_pages(url)
200
210
  end
201
211
 
212
+ get_gist_pages(url, auth_token())
202
213
  end
203
214
 
204
215
  def read_gist(id, file_name=nil)
205
216
  url = "#{base_path}/gists/#{id}"
217
+
218
+ access_token = auth_token()
219
+
206
220
  request = Net::HTTP::Get.new(url)
221
+ request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
207
222
  response = http(api_url, request)
208
223
 
209
224
  if response.code == '200'
@@ -223,9 +238,30 @@ module Gist
223
238
  end
224
239
  end
225
240
 
226
- def get_gist_pages(url)
241
+ def delete_gist(id)
242
+ id = id.split("/").last
243
+ url = "#{base_path}/gists/#{id}"
244
+
245
+ access_token = auth_token()
246
+ if access_token.to_s != ''
247
+ request = Net::HTTP::Delete.new(url)
248
+ request["Authorization"] = "token #{access_token}"
249
+ response = http(api_url, request)
250
+ else
251
+ raise Error, "Not authenticated. Use 'gist --login' to login."
252
+ end
253
+
254
+ if response.code == '204'
255
+ puts "Deleted!"
256
+ else
257
+ raise Error, "Gist with id of #{id} does not exist."
258
+ end
259
+ end
260
+
261
+ def get_gist_pages(url, access_token = "")
227
262
 
228
263
  request = Net::HTTP::Get.new(url)
264
+ request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
229
265
  response = http(api_url, request)
230
266
  pretty_gist(response)
231
267
 
@@ -233,7 +269,7 @@ module Gist
233
269
 
234
270
  if link_header
235
271
  links = Hash[ link_header.gsub(/(<|>|")/, "").split(',').map { |link| link.split('; rel=') } ].invert
236
- get_gist_pages(links['next']) if links['next']
272
+ get_gist_pages(links['next'], access_token) if links['next']
237
273
  end
238
274
 
239
275
  end
@@ -263,10 +299,12 @@ module Gist
263
299
  # @param [String] url
264
300
  # @return [String] shortened url, or long url if shortening fails
265
301
  def shorten(url)
266
- request = Net::HTTP::Post.new("/")
302
+ request = Net::HTTP::Post.new("/create")
267
303
  request.set_form_data(:url => url)
268
304
  response = http(GIT_IO_URL, request)
269
305
  case response.code
306
+ when "200"
307
+ URI.join(GIT_IO_URL, response.body).to_s
270
308
  when "201"
271
309
  response['Location']
272
310
  else
@@ -295,16 +333,72 @@ module Gist
295
333
 
296
334
  # Log the user into gist.
297
335
  #
336
+ def login!(credentials={})
337
+ if (login_url == GITHUB_URL || ENV.key?(CLIENT_ID_ENV_NAME)) && credentials.empty? && !ENV.key?('GIST_USE_USERNAME_AND_PASSWORD')
338
+ device_flow_login!
339
+ else
340
+ access_token_login!(credentials)
341
+ end
342
+ end
343
+
344
+ def device_flow_login!
345
+ puts "Requesting login parameters..."
346
+ request = Net::HTTP::Post.new("/login/device/code")
347
+ request.body = JSON.dump({
348
+ :scope => 'gist',
349
+ :client_id => client_id,
350
+ })
351
+ request.content_type = 'application/json'
352
+ request['accept'] = "application/json"
353
+ response = http(login_url, request)
354
+
355
+ if response.code != '200'
356
+ raise Error, "HTTP #{response.code}: #{response.body}"
357
+ end
358
+
359
+ body = JSON.parse(response.body)
360
+
361
+ puts "Please sign in at #{body['verification_uri']}"
362
+ puts " and enter code: #{body['user_code']}"
363
+ device_code = body['device_code']
364
+ interval = body['interval']
365
+
366
+ loop do
367
+ sleep(interval.to_i)
368
+ request = Net::HTTP::Post.new("/login/oauth/access_token")
369
+ request.body = JSON.dump({
370
+ :client_id => client_id,
371
+ :grant_type => 'urn:ietf:params:oauth:grant-type:device_code',
372
+ :device_code => device_code
373
+ })
374
+ request.content_type = 'application/json'
375
+ request['Accept'] = 'application/json'
376
+ response = http(login_url, request)
377
+ if response.code != '200'
378
+ raise Error, "HTTP #{response.code}: #{response.body}"
379
+ end
380
+ body = JSON.parse(response.body)
381
+ break unless body['error'] == 'authorization_pending'
382
+ end
383
+
384
+ if body['error']
385
+ raise Error, body['error_description']
386
+ end
387
+
388
+ AuthTokenFile.write JSON.parse(response.body)['access_token']
389
+
390
+ puts "Success! #{ENV[URL_ENV_NAME] || "https://github.com/"}settings/connections/applications/#{client_id}"
391
+ end
392
+
393
+ # Logs the user into gist.
394
+ #
298
395
  # This method asks the user for a username and password, and tries to obtain
299
396
  # and OAuth2 access token, which is then stored in ~/.gist
300
397
  #
301
398
  # @raise [Gist::Error] if something went wrong
302
- # @param [Hash] credentials login details
303
- # @option credentials [String] :username
304
- # @option credentials [String] :password
305
399
  # @see http://developer.github.com/v3/oauth/
306
- def login!(credentials={})
307
- puts "Obtaining OAuth2 access_token from github."
400
+ def access_token_login!(credentials={})
401
+ puts "Obtaining OAuth2 access_token from GitHub."
308
402
  loop do
309
403
  print "GitHub username: "
310
404
  username = credentials[:username] || $stdin.gets.strip
@@ -339,7 +433,7 @@ module Gist
339
433
 
340
434
  if Net::HTTPCreated === response
341
435
  AuthTokenFile.write JSON.parse(response.body)['token']
342
- puts "Success! #{ENV[URL_ENV_NAME] || "https://github.com/"}settings/applications"
436
+ puts "Success! #{ENV[URL_ENV_NAME] || "https://github.com/"}settings/tokens"
343
437
  return
344
438
  elsif Net::HTTPUnauthorized === response
345
439
  puts "Error: #{JSON.parse(response.body)['message']}"
@@ -360,7 +454,11 @@ module Gist
360
454
  env = ENV['http_proxy'] || ENV['HTTP_PROXY']
361
455
  connection = if env
362
456
  proxy = URI(env)
363
- Net::HTTP::Proxy(proxy.host, proxy.port).new(uri.host, uri.port)
457
+ if proxy.user
458
+ Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password).new(uri.host, uri.port)
459
+ else
460
+ Net::HTTP::Proxy(proxy.host, proxy.port).new(uri.host, uri.port)
461
+ end
364
462
  else
365
463
  Net::HTTP.new(uri.host, uri.port)
366
464
  end
@@ -514,11 +612,19 @@ Could not find copy command, tried:
514
612
  ENV.key?(URL_ENV_NAME) ? GHE_BASE_PATH : GITHUB_BASE_PATH
515
613
  end
516
614
 
615
+ def login_url
616
+ ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_URL
617
+ end
618
+
517
619
  # Get the API URL
518
620
  def api_url
519
621
  ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_API_URL
520
622
  end
521
623
 
624
+ def client_id
625
+ ENV.key?(CLIENT_ID_ENV_NAME) ? URI(ENV[CLIENT_ID_ENV_NAME]) : GITHUB_CLIENT_ID
626
+ end
627
+
522
628
  def legacy_private_gister?
523
629
  return unless which('git')
524
630
  `git config --global gist.private` =~ /\Ayes|1|true|on\z/i