gist 4.6.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +43 -10
- data/Rakefile +1 -3
- data/bin/gist +19 -12
- data/gist.gemspec +1 -1
- data/lib/gist.rb +115 -38
- data/spec/ghe_spec.rb +12 -5
- data/spec/rawify_spec.rb +10 -1
- data/spec/shorten_spec.rb +11 -2
- data/spec/spec_helper.rb +1 -1
- metadata +3 -8
- data/.gitignore +0 -8
- data/build/gist +0 -2357
- data/build/gist.1 +0 -258
- data/vendor/netrc.rb +0 -286
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 78e3d009d0e3e3a535d20e8d7e0582705c6ea61308958c3f59a4d4a2e365fa3c
|
4
|
+
data.tar.gz: 23df778298090151ce7e2b8f3dbb8f97786bc7d576f218be1aeb454123090e91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
@@ -79,12 +84,29 @@ To read a gist and print it to STDOUT
|
|
79
84
|
|
80
85
|
## Login
|
81
86
|
|
82
|
-
|
83
|
-
|
84
|
-
an
|
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.
|
85
95
|
|
86
96
|
gist --login
|
87
|
-
|
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.
|
88
110
|
GitHub username: ConradIrwin
|
89
111
|
GitHub password:
|
90
112
|
2-factor auth code:
|
@@ -94,9 +116,21 @@ This token is stored in `~/.gist` and used for all future gisting. If you need t
|
|
94
116
|
you can revoke it from https://github.com/settings/tokens, or just delete the
|
95
117
|
file.
|
96
118
|
|
97
|
-
|
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`).
|
128
|
+
|
129
|
+
For example, one way to create this file would be to run:
|
130
|
+
|
131
|
+
(umask 0077 && echo MY_SECRET_TOKEN > ~/.gist)
|
98
132
|
|
99
|
-
|
133
|
+
The `umask` ensures that the file is only accessible from your user account.
|
100
134
|
|
101
135
|
### GitHub Enterprise
|
102
136
|
|
@@ -106,10 +140,10 @@ you need to export the `GITHUB_URL` environment variable (usually done in your `
|
|
106
140
|
export GITHUB_URL=http://github.internal.example.com/
|
107
141
|
|
108
142
|
Once you've done this and restarted your terminal (or run `source ~/.bashrc`), gist will
|
109
|
-
automatically use
|
143
|
+
automatically use GitHub Enterprise instead of the public github.com
|
110
144
|
|
111
145
|
Your token for GitHub Enterprise will be stored in `.gist.<protocol>.<server.name>[.<port>]` (e.g.
|
112
|
-
|
146
|
+
`~/.gist.http.github.internal.example.com` for the GITHUB_URL example above) instead of `~/.gist`.
|
113
147
|
|
114
148
|
If you have multiple servers or use Enterprise and public GitHub often, you can work around this by creating scripts
|
115
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
|
@@ -137,11 +171,10 @@ If you need more advanced features you can also pass:
|
|
137
171
|
* `:public` if you want your gist to have a guessable url.
|
138
172
|
* `:description` to add a description to your gist.
|
139
173
|
* `:update` to update an existing gist (can be a URL or an id).
|
140
|
-
* `:anonymous` to submit an anonymous gist (default is false).
|
141
174
|
* `:copy` to copy the resulting URL to the clipboard (default is false).
|
142
175
|
* `:open` to open the resulting URL in a browser (default is false).
|
143
176
|
|
144
|
-
NOTE: The access_token must have the
|
177
|
+
NOTE: The access_token must have the `gist` scope and may also require the `user:email` scope.
|
145
178
|
|
146
179
|
If you want to upload multiple files in the same gist, you can:
|
147
180
|
|
data/Rakefile
CHANGED
@@ -23,9 +23,7 @@ task :standalone do
|
|
23
23
|
f.puts "#!/usr/bin/env ruby"
|
24
24
|
f.puts "# This is generated from https://github.com/defunkt/gist using 'rake standalone'"
|
25
25
|
f.puts "# any changes will be overwritten."
|
26
|
-
f.puts File.read("lib/gist.rb")
|
27
|
-
.split("require 'json'\n").join(File.read("vendor/json.rb"))
|
28
|
-
.split("require 'netrc'\n").join(File.read("vendor/netrc.rb"))
|
26
|
+
f.puts File.read("lib/gist.rb").split("require 'json'\n").join(File.read("vendor/json.rb"))
|
29
27
|
|
30
28
|
f.puts File.read("bin/gist").gsub(/^require.*gist.*\n/, '');
|
31
29
|
end
|
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
|
-
|
28
|
-
|
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
|
-
|
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
|
@@ -140,6 +140,12 @@ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-R] [-d DESC] [-a] [-u URL] [-P]
|
|
140
140
|
end.parse!
|
141
141
|
|
142
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
|
+
|
143
149
|
options[:output] = if options[:embed] && options[:shorten]
|
144
150
|
raise Gist::Error, "--embed does not make sense with --shorten"
|
145
151
|
elsif options[:embed]
|
@@ -195,7 +201,8 @@ begin
|
|
195
201
|
end
|
196
202
|
end
|
197
203
|
|
198
|
-
|
204
|
+
output = Gist.multi_gist(files, options)
|
205
|
+
puts output if output
|
199
206
|
end
|
200
207
|
|
201
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
@@ -8,17 +8,11 @@ rescue LoadError
|
|
8
8
|
require File.join File.dirname(File.dirname(__FILE__)), 'vendor', 'json.rb'
|
9
9
|
end
|
10
10
|
|
11
|
-
begin
|
12
|
-
require 'netrc'
|
13
|
-
rescue LoadError
|
14
|
-
require File.join File.dirname(File.dirname(__FILE__)), 'vendor', 'netrc.rb'
|
15
|
-
end
|
16
|
-
|
17
11
|
# It just gists.
|
18
12
|
module Gist
|
19
13
|
extend self
|
20
14
|
|
21
|
-
VERSION = '
|
15
|
+
VERSION = '6.0.0'
|
22
16
|
|
23
17
|
# A list of clipboard commands with copy and paste support.
|
24
18
|
CLIPBOARD_COMMANDS = {
|
@@ -29,12 +23,16 @@ module Gist
|
|
29
23
|
}
|
30
24
|
|
31
25
|
GITHUB_API_URL = URI("https://api.github.com/")
|
26
|
+
GITHUB_URL = URI("https://github.com/")
|
32
27
|
GIT_IO_URL = URI("https://git.io")
|
33
28
|
|
34
29
|
GITHUB_BASE_PATH = ""
|
35
30
|
GHE_BASE_PATH = "/api/v3"
|
36
31
|
|
32
|
+
GITHUB_CLIENT_ID = '4f7ec0d4eab38e74384e'
|
33
|
+
|
37
34
|
URL_ENV_NAME = "GITHUB_URL"
|
35
|
+
CLIENT_ID_ENV_NAME = "GIST_CLIENT_ID"
|
38
36
|
|
39
37
|
USER_AGENT = "gist/#{VERSION} (Net::HTTP, #{RUBY_DESCRIPTION})"
|
40
38
|
|
@@ -50,7 +48,7 @@ module Gist
|
|
50
48
|
module AuthTokenFile
|
51
49
|
def self.filename
|
52
50
|
if ENV.key?(URL_ENV_NAME)
|
53
|
-
File.expand_path "~/.gist.#{ENV[URL_ENV_NAME].gsub(/:/, '.').gsub(/[^a-z0-9
|
51
|
+
File.expand_path "~/.gist.#{ENV[URL_ENV_NAME].gsub(/:/, '.').gsub(/[^a-z0-9.-]/, '')}"
|
54
52
|
else
|
55
53
|
File.expand_path "~/.gist"
|
56
54
|
end
|
@@ -71,7 +69,7 @@ module Gist
|
|
71
69
|
#
|
72
70
|
# @return [String] string value of access token or `nil`, if not found
|
73
71
|
def auth_token
|
74
|
-
@token ||= AuthTokenFile.read rescue nil
|
72
|
+
@token ||= AuthTokenFile.read rescue nil
|
75
73
|
end
|
76
74
|
|
77
75
|
# Upload a gist to https://gist.github.com
|
@@ -82,10 +80,14 @@ module Gist
|
|
82
80
|
#
|
83
81
|
# @see http://developer.github.com/v3/gists/
|
84
82
|
def gist(content, options = {})
|
85
|
-
filename = options[:filename] ||
|
83
|
+
filename = options[:filename] || default_filename
|
86
84
|
multi_gist({filename => content}, options)
|
87
85
|
end
|
88
86
|
|
87
|
+
def default_filename
|
88
|
+
"gistfile1.txt"
|
89
|
+
end
|
90
|
+
|
89
91
|
# Upload a gist to https://gist.github.com
|
90
92
|
#
|
91
93
|
# @param [Hash] files the code you'd like to gist: filename => content
|
@@ -98,6 +100,7 @@ module Gist
|
|
98
100
|
# @option options [String] :update the URL or id of a gist to update
|
99
101
|
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
|
100
102
|
# @option options [Boolean] :open (false) Open the resulting URL in a browser.
|
103
|
+
# @option options [Boolean] :skip_empty (false) Skip gisting empty files.
|
101
104
|
# @option options [Symbol] :output (:all) The type of return value you'd like:
|
102
105
|
# :html_url gives a String containing the url to the gist in a browser
|
103
106
|
# :short_url gives a String contianing a git.io url that redirects to html_url
|
@@ -109,6 +112,13 @@ module Gist
|
|
109
112
|
#
|
110
113
|
# @see http://developer.github.com/v3/gists/
|
111
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
|
+
|
112
122
|
json = {}
|
113
123
|
|
114
124
|
json[:description] = options[:description] if options[:description]
|
@@ -116,22 +126,23 @@ module Gist
|
|
116
126
|
json[:files] = {}
|
117
127
|
|
118
128
|
files.each_pair do |(name, content)|
|
119
|
-
|
120
|
-
|
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
|
121
135
|
end
|
122
136
|
|
137
|
+
return if json[:files].empty? && options[:skip_empty]
|
138
|
+
|
123
139
|
existing_gist = options[:update].to_s.split("/").last
|
124
|
-
if options[:anonymous]
|
125
|
-
access_token = nil
|
126
|
-
else
|
127
|
-
access_token = (options[:access_token] || auth_token())
|
128
|
-
end
|
129
140
|
|
130
141
|
url = "#{base_path}/gists"
|
131
142
|
url << "/" << CGI.escape(existing_gist) if existing_gist.to_s != ''
|
132
|
-
url << "?access_token=" << CGI.escape(access_token) if access_token.to_s != ''
|
133
143
|
|
134
144
|
request = Net::HTTP::Post.new(url)
|
145
|
+
request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
|
135
146
|
request.body = JSON.dump(json)
|
136
147
|
request.content_type = 'application/json'
|
137
148
|
|
@@ -167,9 +178,10 @@ module Gist
|
|
167
178
|
if user == ""
|
168
179
|
access_token = auth_token()
|
169
180
|
if access_token.to_s != ''
|
170
|
-
url << "/gists
|
181
|
+
url << "/gists"
|
171
182
|
|
172
183
|
request = Net::HTTP::Get.new(url)
|
184
|
+
request['Authorization'] = "token #{access_token}"
|
173
185
|
response = http(api_url, request)
|
174
186
|
|
175
187
|
pretty_gist(response)
|
@@ -192,24 +204,21 @@ module Gist
|
|
192
204
|
url = "#{base_path}"
|
193
205
|
|
194
206
|
if user == ""
|
195
|
-
|
196
|
-
if access_token.to_s != ''
|
197
|
-
url << "/gists?per_page=100&access_token=" << CGI.escape(access_token)
|
198
|
-
get_gist_pages(url)
|
199
|
-
else
|
200
|
-
raise Error, "Not authenticated. Use 'gist --login' to login or 'gist -l username' to view public gists."
|
201
|
-
end
|
202
|
-
|
207
|
+
url << "/gists?per_page=100"
|
203
208
|
else
|
204
209
|
url << "/users/#{user}/gists?per_page=100"
|
205
|
-
get_gist_pages(url)
|
206
210
|
end
|
207
211
|
|
212
|
+
get_gist_pages(url, auth_token())
|
208
213
|
end
|
209
214
|
|
210
215
|
def read_gist(id, file_name=nil)
|
211
216
|
url = "#{base_path}/gists/#{id}"
|
217
|
+
|
218
|
+
access_token = auth_token()
|
219
|
+
|
212
220
|
request = Net::HTTP::Get.new(url)
|
221
|
+
request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
|
213
222
|
response = http(api_url, request)
|
214
223
|
|
215
224
|
if response.code == '200'
|
@@ -235,9 +244,8 @@ module Gist
|
|
235
244
|
|
236
245
|
access_token = auth_token()
|
237
246
|
if access_token.to_s != ''
|
238
|
-
url << "?access_token=" << CGI.escape(access_token)
|
239
|
-
|
240
247
|
request = Net::HTTP::Delete.new(url)
|
248
|
+
request["Authorization"] = "token #{access_token}"
|
241
249
|
response = http(api_url, request)
|
242
250
|
else
|
243
251
|
raise Error, "Not authenticated. Use 'gist --login' to login."
|
@@ -250,9 +258,10 @@ module Gist
|
|
250
258
|
end
|
251
259
|
end
|
252
260
|
|
253
|
-
def get_gist_pages(url)
|
261
|
+
def get_gist_pages(url, access_token = "")
|
254
262
|
|
255
263
|
request = Net::HTTP::Get.new(url)
|
264
|
+
request['Authorization'] = "token #{access_token}" if access_token.to_s != ''
|
256
265
|
response = http(api_url, request)
|
257
266
|
pretty_gist(response)
|
258
267
|
|
@@ -260,7 +269,7 @@ module Gist
|
|
260
269
|
|
261
270
|
if link_header
|
262
271
|
links = Hash[ link_header.gsub(/(<|>|")/, "").split(',').map { |link| link.split('; rel=') } ].invert
|
263
|
-
get_gist_pages(links['next']) if links['next']
|
272
|
+
get_gist_pages(links['next'], access_token) if links['next']
|
264
273
|
end
|
265
274
|
|
266
275
|
end
|
@@ -324,16 +333,72 @@ module Gist
|
|
324
333
|
|
325
334
|
# Log the user into gist.
|
326
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
|
+
#
|
327
395
|
# This method asks the user for a username and password, and tries to obtain
|
328
396
|
# and OAuth2 access token, which is then stored in ~/.gist
|
329
397
|
#
|
330
398
|
# @raise [Gist::Error] if something went wrong
|
331
|
-
# @param [Hash] credentials login details
|
332
|
-
# @option credentials [String] :username
|
333
|
-
# @option credentials [String] :password
|
334
399
|
# @see http://developer.github.com/v3/oauth/
|
335
|
-
def
|
336
|
-
puts "Obtaining OAuth2 access_token from
|
400
|
+
def access_token_login!(credentials={})
|
401
|
+
puts "Obtaining OAuth2 access_token from GitHub."
|
337
402
|
loop do
|
338
403
|
print "GitHub username: "
|
339
404
|
username = credentials[:username] || $stdin.gets.strip
|
@@ -389,7 +454,11 @@ module Gist
|
|
389
454
|
env = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
390
455
|
connection = if env
|
391
456
|
proxy = URI(env)
|
392
|
-
|
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
|
393
462
|
else
|
394
463
|
Net::HTTP.new(uri.host, uri.port)
|
395
464
|
end
|
@@ -543,11 +612,19 @@ Could not find copy command, tried:
|
|
543
612
|
ENV.key?(URL_ENV_NAME) ? GHE_BASE_PATH : GITHUB_BASE_PATH
|
544
613
|
end
|
545
614
|
|
615
|
+
def login_url
|
616
|
+
ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_URL
|
617
|
+
end
|
618
|
+
|
546
619
|
# Get the API URL
|
547
620
|
def api_url
|
548
621
|
ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_API_URL
|
549
622
|
end
|
550
623
|
|
624
|
+
def client_id
|
625
|
+
ENV.key?(CLIENT_ID_ENV_NAME) ? URI(ENV[CLIENT_ID_ENV_NAME]) : GITHUB_CLIENT_ID
|
626
|
+
end
|
627
|
+
|
551
628
|
def legacy_private_gister?
|
552
629
|
return unless which('git')
|
553
630
|
`git config --global gist.private` =~ /\Ayes|1|true|on\z/i
|