gist 3.0.2 → 4.0.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.
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/Gemfile +3 -0
- data/LICENSE.MIT +7 -0
- data/README.md +149 -0
- data/Rakefile +13 -45
- data/bin/gist +156 -19
- data/gist.gemspec +21 -0
- data/lib/gist.rb +290 -232
- data/spec/clipboard_spec.rb +40 -0
- data/spec/ghe_spec.rb +80 -0
- data/spec/gist_spec.rb +23 -0
- data/spec/proxy_spec.rb +21 -0
- data/spec/shorten_spec.rb +11 -0
- data/spec/spec_helper.rb +15 -0
- metadata +124 -58
- data/LICENSE +0 -18
- data/README.markdown +0 -121
- data/lib/gist/cacert.pem +0 -116
- data/lib/gist/manpage.rb +0 -90
- data/lib/gist/standalone.rb +0 -55
- data/lib/gist/version.rb +0 -3
- data/man/gist.1 +0 -146
- data/man/gist.1.html +0 -209
- data/man/gist.1.ron +0 -117
data/lib/gist.rb
CHANGED
|
@@ -1,301 +1,359 @@
|
|
|
1
|
-
require 'open-uri'
|
|
2
1
|
require 'net/https'
|
|
3
|
-
require '
|
|
4
|
-
|
|
5
|
-
require 'rubygems'
|
|
2
|
+
require 'cgi'
|
|
6
3
|
require 'json'
|
|
7
|
-
require '
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
require 'gist/version' unless defined?(Gist::Version)
|
|
11
|
-
|
|
12
|
-
# You can use this class from other scripts with the greatest of
|
|
13
|
-
# ease.
|
|
14
|
-
#
|
|
15
|
-
# >> Gist.read(gist_id)
|
|
16
|
-
# Returns the body of gist_id as a string.
|
|
17
|
-
#
|
|
18
|
-
# >> Gist.write(content)
|
|
19
|
-
# Creates a gist from the string `content`. Returns the URL of the
|
|
20
|
-
# new gist.
|
|
21
|
-
#
|
|
22
|
-
# >> Gist.copy(string)
|
|
23
|
-
# Copies string to the clipboard.
|
|
24
|
-
#
|
|
25
|
-
# >> Gist.browse(url)
|
|
26
|
-
# Opens URL in your default browser.
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
# It just gists.
|
|
27
7
|
module Gist
|
|
28
8
|
extend self
|
|
29
9
|
|
|
30
|
-
|
|
31
|
-
CREATE_URL = 'https://api.github.com/gists'
|
|
32
|
-
|
|
33
|
-
if ENV['HTTPS_PROXY']
|
|
34
|
-
PROXY = URI(ENV['HTTPS_PROXY'])
|
|
35
|
-
elsif ENV['HTTP_PROXY']
|
|
36
|
-
PROXY = URI(ENV['HTTP_PROXY'])
|
|
37
|
-
else
|
|
38
|
-
PROXY = nil
|
|
39
|
-
end
|
|
40
|
-
PROXY_HOST = PROXY ? PROXY.host : nil
|
|
41
|
-
PROXY_PORT = PROXY ? PROXY.port : nil
|
|
42
|
-
|
|
43
|
-
# Parses command line arguments and does what needs to be done.
|
|
44
|
-
def execute(*args)
|
|
45
|
-
private_gist = defaults["private"]
|
|
46
|
-
gist_filename = nil
|
|
47
|
-
gist_extension = defaults["extension"]
|
|
48
|
-
browse_enabled = defaults["browse"]
|
|
49
|
-
description = nil
|
|
50
|
-
|
|
51
|
-
opts = OptionParser.new do |opts|
|
|
52
|
-
opts.banner = "Usage: gist [options] [filename or stdin] [filename] ...\n" +
|
|
53
|
-
"Filename '-' forces gist to read from stdin."
|
|
54
|
-
|
|
55
|
-
opts.on('-p', '--[no-]private', 'Make the gist private') do |priv|
|
|
56
|
-
private_gist = priv
|
|
57
|
-
end
|
|
10
|
+
VERSION = '4.0.0'
|
|
58
11
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
12
|
+
# A list of clipboard commands with copy and paste support.
|
|
13
|
+
CLIPBOARD_COMMANDS = {
|
|
14
|
+
'xclip' => 'xclip -o',
|
|
15
|
+
'xsel' => 'xsel -o',
|
|
16
|
+
'pbcopy' => 'pbpaste',
|
|
17
|
+
'putclip' => 'getclip'
|
|
18
|
+
}
|
|
63
19
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
end
|
|
20
|
+
GITHUB_API_URL = URI("https://api.github.com/")
|
|
21
|
+
GIT_IO_URL = URI("http://git.io")
|
|
67
22
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
23
|
+
GITHUB_BASE_PATH = ""
|
|
24
|
+
GHE_BASE_PATH = "/api/v3"
|
|
71
25
|
|
|
72
|
-
|
|
73
|
-
Gist::Manpage.display("gist")
|
|
74
|
-
end
|
|
26
|
+
URL_ENV_NAME = "GITHUB_URL"
|
|
75
27
|
|
|
76
|
-
|
|
77
|
-
puts Gist::Version
|
|
78
|
-
exit
|
|
79
|
-
end
|
|
28
|
+
USER_AGENT = "gist/#{VERSION} (Net::HTTP, #{RUBY_DESCRIPTION})"
|
|
80
29
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
30
|
+
# Exception tag for errors raised while gisting.
|
|
31
|
+
module Error;
|
|
32
|
+
def self.exception(*args)
|
|
33
|
+
RuntimeError.new(*args).extend(self)
|
|
85
34
|
end
|
|
35
|
+
end
|
|
36
|
+
class ClipboardError < RuntimeError; include Error end
|
|
86
37
|
|
|
87
|
-
|
|
38
|
+
# Upload a gist to https://gist.github.com
|
|
39
|
+
#
|
|
40
|
+
# @param [String] content the code you'd like to gist
|
|
41
|
+
# @param [Hash] options more detailed options, see
|
|
42
|
+
# the documentation for {multi_gist}
|
|
43
|
+
#
|
|
44
|
+
# @see http://developer.github.com/v3/gists/
|
|
45
|
+
def gist(content, options = {})
|
|
46
|
+
filename = options[:filename] || "a.rb"
|
|
47
|
+
multi_gist({filename => content}, options)
|
|
48
|
+
end
|
|
88
49
|
|
|
89
|
-
|
|
50
|
+
# Upload a gist to https://gist.github.com
|
|
51
|
+
#
|
|
52
|
+
# @param [Hash] files the code you'd like to gist: filename => content
|
|
53
|
+
# @param [Hash] options more detailed options
|
|
54
|
+
#
|
|
55
|
+
# @option options [String] :description the description
|
|
56
|
+
# @option options [Boolean] :public (false) is this gist public
|
|
57
|
+
# @option options [Boolean] :anonymous (false) is this gist anonymous
|
|
58
|
+
# @option options [String] :access_token (`File.read("~/.gist")`) The OAuth2 access token.
|
|
59
|
+
# @option options [String] :update the URL or id of a gist to update
|
|
60
|
+
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
|
|
61
|
+
# @option options [Boolean] :open (false) Open the resulting URL in a browser.
|
|
62
|
+
# @option options [Symbol] :output (:all) The type of return value you'd like:
|
|
63
|
+
# :html_url gives a String containing the url to the gist in a browser
|
|
64
|
+
# :short_url gives a String contianing a git.io url that redirects to html_url
|
|
65
|
+
# :javascript gives a String containing a script tag suitable for embedding the gist
|
|
66
|
+
# :all gives a Hash containing the parsed json response from the server
|
|
67
|
+
#
|
|
68
|
+
# @return [String, Hash] the return value as configured by options[:output]
|
|
69
|
+
# @raise [Gist::Error] if something went wrong
|
|
70
|
+
#
|
|
71
|
+
# @see http://developer.github.com/v3/gists/
|
|
72
|
+
def multi_gist(files, options={})
|
|
73
|
+
json = {}
|
|
90
74
|
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
json[:description] = options[:description] if options[:description]
|
|
76
|
+
json[:public] = !!options[:public]
|
|
77
|
+
json[:files] = {}
|
|
78
|
+
|
|
79
|
+
files.each_pair do |(name, content)|
|
|
80
|
+
raise "Cannot gist empty files" if content.to_s.strip == ""
|
|
81
|
+
json[:files][File.basename(name)] = {:content => content}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
existing_gist = options[:update].to_s.split("/").last
|
|
85
|
+
if options[:anonymous]
|
|
86
|
+
access_token = nil
|
|
87
|
+
else
|
|
88
|
+
access_token = (options[:access_token] || File.read(auth_token_file) rescue nil)
|
|
89
|
+
end
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
exit
|
|
98
|
-
end
|
|
91
|
+
url = "#{base_path}/gists"
|
|
92
|
+
url << "/" << CGI.escape(existing_gist) if existing_gist.to_s != ''
|
|
93
|
+
url << "?access_token=" << CGI.escape(access_token) if access_token.to_s != ''
|
|
99
94
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
95
|
+
request = Net::HTTP::Post.new(url)
|
|
96
|
+
request.body = JSON.dump(json)
|
|
97
|
+
request.content_type = 'application/json'
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
:input => File.read(file),
|
|
106
|
-
:filename => file,
|
|
107
|
-
:extension => (File.extname(file) if file.include?('.'))
|
|
108
|
-
})
|
|
109
|
-
end
|
|
99
|
+
retried = false
|
|
110
100
|
|
|
101
|
+
begin
|
|
102
|
+
response = http(api_url, request)
|
|
103
|
+
if Net::HTTPSuccess === response
|
|
104
|
+
on_success(response.body, options)
|
|
111
105
|
else
|
|
112
|
-
#
|
|
113
|
-
input = $stdin.read
|
|
114
|
-
files = [{:input => input, :extension => gist_extension}]
|
|
106
|
+
raise "Got #{response.class} from gist: #{response.body}"
|
|
115
107
|
end
|
|
116
|
-
|
|
117
|
-
url = write(files, private_gist, description)
|
|
118
|
-
browse(url) if browse_enabled
|
|
119
|
-
puts copy(url)
|
|
120
108
|
rescue => e
|
|
121
|
-
|
|
122
|
-
|
|
109
|
+
raise if retried
|
|
110
|
+
retried = true
|
|
111
|
+
retry
|
|
123
112
|
end
|
|
124
|
-
end
|
|
125
113
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
rescue => e
|
|
115
|
+
raise e.extend Error
|
|
116
|
+
end
|
|
129
117
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
118
|
+
# Convert long github urls into short git.io ones
|
|
119
|
+
#
|
|
120
|
+
# @param [String] url
|
|
121
|
+
# @return [String] shortened url, or long url if shortening fails
|
|
122
|
+
def shorten(url)
|
|
123
|
+
request = Net::HTTP::Post.new("/")
|
|
124
|
+
request.set_form_data(:url => url)
|
|
125
|
+
response = http(GIT_IO_URL, request)
|
|
126
|
+
case response.code
|
|
127
|
+
when "201"
|
|
128
|
+
response['Location']
|
|
133
129
|
else
|
|
134
|
-
|
|
130
|
+
url
|
|
135
131
|
end
|
|
132
|
+
end
|
|
136
133
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
134
|
+
# Log the user into gist.
|
|
135
|
+
#
|
|
136
|
+
# This method asks the user for a username and password, and tries to obtain
|
|
137
|
+
# and OAuth2 access token, which is then stored in ~/.gist
|
|
138
|
+
#
|
|
139
|
+
# @raise [Gist::Error] if something went wrong
|
|
140
|
+
# @see http://developer.github.com/v3/oauth/
|
|
141
|
+
def login!
|
|
142
|
+
puts "Obtaining OAuth2 access_token from github."
|
|
143
|
+
print "GitHub username: "
|
|
144
|
+
username = $stdin.gets.strip
|
|
145
|
+
print "GitHub password: "
|
|
146
|
+
password = begin
|
|
147
|
+
`stty -echo` rescue nil
|
|
148
|
+
$stdin.gets.strip
|
|
149
|
+
ensure
|
|
150
|
+
`stty echo` rescue nil
|
|
147
151
|
end
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
puts ""
|
|
153
|
+
|
|
154
|
+
request = Net::HTTP::Post.new("#{base_path}/authorizations")
|
|
155
|
+
request.body = JSON.dump({
|
|
156
|
+
:scopes => [:gist],
|
|
157
|
+
:note => "The gist gem",
|
|
158
|
+
:note_url => "https://github.com/ConradIrwin/gist"
|
|
159
|
+
})
|
|
160
|
+
request.content_type = 'application/json'
|
|
161
|
+
request.basic_auth(username, password)
|
|
162
|
+
|
|
163
|
+
response = http(api_url, request)
|
|
164
|
+
|
|
165
|
+
if Net::HTTPCreated === response
|
|
166
|
+
File.open(auth_token_file, 'w') do |f|
|
|
167
|
+
f.write JSON.parse(response.body)['token']
|
|
168
|
+
end
|
|
169
|
+
puts "Success! #{ENV[URL_ENV_NAME] || "https://github.com/"}settings/applications"
|
|
153
170
|
else
|
|
154
|
-
|
|
155
|
-
exit(false)
|
|
171
|
+
raise "Got #{response.class} from gist: #{response.body}"
|
|
156
172
|
end
|
|
173
|
+
rescue => e
|
|
174
|
+
raise e.extend Error
|
|
157
175
|
end
|
|
158
176
|
|
|
159
|
-
#
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
177
|
+
# Return HTTP connection
|
|
178
|
+
#
|
|
179
|
+
# @param [URI::HTTP] The URI to which to connect
|
|
180
|
+
# @return [Net::HTTP]
|
|
181
|
+
def http_connection(uri)
|
|
182
|
+
env = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
|
183
|
+
connection = if env
|
|
184
|
+
proxy = URI(env)
|
|
185
|
+
Net::HTTP::Proxy(proxy.host, proxy.port).new(uri.host, uri.port)
|
|
186
|
+
else
|
|
187
|
+
Net::HTTP.new(uri.host, uri.port)
|
|
188
|
+
end
|
|
189
|
+
if uri.scheme == "https"
|
|
190
|
+
connection.use_ssl = true
|
|
191
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
192
|
+
end
|
|
193
|
+
connection.open_timeout = 10
|
|
194
|
+
connection.read_timeout = 10
|
|
195
|
+
connection
|
|
163
196
|
end
|
|
164
197
|
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
198
|
+
# Run an HTTP operation
|
|
199
|
+
#
|
|
200
|
+
# @param [URI::HTTP] The URI to which to connect
|
|
201
|
+
# @param [Net::HTTPRequest] The request to make
|
|
202
|
+
# @return [Net::HTTPResponse]
|
|
203
|
+
def http(url, request)
|
|
204
|
+
request['User-Agent'] = USER_AGENT
|
|
205
|
+
|
|
206
|
+
http_connection(url).start do |http|
|
|
207
|
+
http.request request
|
|
175
208
|
end
|
|
209
|
+
rescue Timeout::Error
|
|
210
|
+
raise "Could not connect to #{api_url}"
|
|
176
211
|
end
|
|
177
212
|
|
|
178
|
-
#
|
|
213
|
+
# Called after an HTTP response to gist to perform post-processing.
|
|
214
|
+
#
|
|
215
|
+
# @param [String] body the text body from the github api
|
|
216
|
+
# @param [Hash] options more detailed options, see
|
|
217
|
+
# the documentation for {multi_gist}
|
|
218
|
+
def on_success(body, options={})
|
|
219
|
+
json = JSON.parse(body)
|
|
220
|
+
|
|
221
|
+
output = case options[:output]
|
|
222
|
+
when :javascript
|
|
223
|
+
%Q{<script src="#{json['html_url']}.js"></script>}
|
|
224
|
+
when :html_url
|
|
225
|
+
json['html_url']
|
|
226
|
+
when :short_url
|
|
227
|
+
shorten(json['html_url'])
|
|
228
|
+
else
|
|
229
|
+
json
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
Gist.copy(output.to_s) if options[:copy]
|
|
233
|
+
Gist.open(json['html_url']) if options[:open]
|
|
234
|
+
|
|
235
|
+
output
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Copy a string to the clipboard.
|
|
239
|
+
#
|
|
240
|
+
# @param [String] content
|
|
241
|
+
# @raise [Gist::Error] if no clipboard integration could be found
|
|
242
|
+
#
|
|
179
243
|
def copy(content)
|
|
180
|
-
|
|
181
|
-
when system("type pbcopy > /dev/null 2>&1")
|
|
182
|
-
:pbcopy
|
|
183
|
-
when system("type xclip > /dev/null 2>&1")
|
|
184
|
-
:xclip
|
|
185
|
-
when system("type putclip > /dev/null 2>&1")
|
|
186
|
-
:putclip
|
|
187
|
-
end
|
|
244
|
+
IO.popen(clipboard_command(:copy), 'r+') { |clip| clip.print content }
|
|
188
245
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
end
|
|
246
|
+
unless paste == content
|
|
247
|
+
message = 'Copying to clipboard failed.'
|
|
192
248
|
|
|
193
|
-
|
|
194
|
-
|
|
249
|
+
if ENV["TMUX"] && clipboard_command(:copy) == 'pbcopy'
|
|
250
|
+
message << "\nIf you're running tmux on a mac, try http://robots.thoughtbot.com/post/19398560514/how-to-copy-and-paste-with-tmux-on-mac-os-x"
|
|
251
|
+
end
|
|
195
252
|
|
|
196
|
-
|
|
197
|
-
# Give an array of file information and private boolean, returns
|
|
198
|
-
# an appropriate payload for POSTing to gist.github.com
|
|
199
|
-
def data(files, private_gist, description)
|
|
200
|
-
i = 0
|
|
201
|
-
file_data = {}
|
|
202
|
-
files.each do |file|
|
|
203
|
-
i = i + 1
|
|
204
|
-
filename = file[:filename] ? file[:filename] : "gistfile#{i}"
|
|
205
|
-
file_data[filename] = {:content => file[:input]}
|
|
253
|
+
raise Error, message
|
|
206
254
|
end
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
data.merge!({ 'description' => description }) unless description.nil?
|
|
210
|
-
data.merge!({ 'public' => !private_gist })
|
|
211
|
-
data
|
|
255
|
+
rescue Error => e
|
|
256
|
+
raise ClipboardError, e.message + "\nAttempted to copy: #{content}"
|
|
212
257
|
end
|
|
213
258
|
|
|
214
|
-
#
|
|
215
|
-
# http://github.com/guides/local-github-config
|
|
259
|
+
# Get a string from the clipboard.
|
|
216
260
|
#
|
|
217
|
-
#
|
|
218
|
-
#
|
|
219
|
-
def
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
token = config("github.token")
|
|
224
|
-
if password.to_s.empty? && !token.to_s.empty?
|
|
225
|
-
abort "Please set GITHUB_PASSWORD or github.password instead of using a token."
|
|
226
|
-
end
|
|
261
|
+
# @param [String] content
|
|
262
|
+
# @raise [Gist::Error] if no clipboard integration could be found
|
|
263
|
+
def paste
|
|
264
|
+
`#{clipboard_command(:paste)}`
|
|
265
|
+
end
|
|
227
266
|
|
|
228
|
-
|
|
267
|
+
# Find command from PATH environment.
|
|
268
|
+
#
|
|
269
|
+
# @param [String] cmd command name to find
|
|
270
|
+
# @param [String] options PATH environment variable
|
|
271
|
+
# @return [String] the command found
|
|
272
|
+
def which(cmd, path=ENV['PATH'])
|
|
273
|
+
if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin|cygwin/
|
|
274
|
+
path.split(File::PATH_SEPARATOR).each {|dir|
|
|
275
|
+
f = File.join(dir, cmd+".exe")
|
|
276
|
+
return f if File.executable?(f) && !File.directory?(f)
|
|
277
|
+
}
|
|
229
278
|
nil
|
|
230
279
|
else
|
|
231
|
-
|
|
280
|
+
return system("which #{cmd} > /dev/null 2>&1")
|
|
232
281
|
end
|
|
233
282
|
end
|
|
234
283
|
|
|
235
|
-
#
|
|
236
|
-
# git-config(1) for more information.
|
|
237
|
-
#
|
|
238
|
-
# Settings applicable to gist.rb are:
|
|
284
|
+
# Get the command to use for the clipboard action.
|
|
239
285
|
#
|
|
240
|
-
#
|
|
241
|
-
#
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
286
|
+
# @param [Symbol] action either :copy or :paste
|
|
287
|
+
# @return [String] the command to run
|
|
288
|
+
# @raise [Gist::ClipboardError] if no clipboard integration could be found
|
|
289
|
+
def clipboard_command(action)
|
|
290
|
+
command = CLIPBOARD_COMMANDS.keys.detect do |cmd|
|
|
291
|
+
which cmd
|
|
292
|
+
end
|
|
293
|
+
raise ClipboardError, <<-EOT unless command
|
|
294
|
+
Could not find copy command, tried:
|
|
295
|
+
#{CLIPBOARD_COMMANDS.values.join(' || ')}
|
|
296
|
+
EOT
|
|
297
|
+
action == :copy ? command : CLIPBOARD_COMMANDS[command]
|
|
250
298
|
end
|
|
251
299
|
|
|
252
|
-
#
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
#
|
|
300
|
+
# Open a URL in a browser.
|
|
301
|
+
#
|
|
302
|
+
# @param [String] url
|
|
303
|
+
# @raise [RuntimeError] if no browser integration could be found
|
|
256
304
|
#
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
305
|
+
# This method was heavily inspired by defunkt's Gist#open,
|
|
306
|
+
# @see https://github.com/defunkt/gist/blob/bca9b29/lib/gist.rb#L157
|
|
307
|
+
def open(url)
|
|
308
|
+
command = if ENV['BROWSER']
|
|
309
|
+
ENV['BROWSER']
|
|
310
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
|
311
|
+
'open'
|
|
312
|
+
elsif RUBY_PLATFORM =~ /linux/
|
|
313
|
+
%w(
|
|
314
|
+
sensible-browser
|
|
315
|
+
firefox
|
|
316
|
+
firefox-bin
|
|
317
|
+
).detect do |cmd|
|
|
318
|
+
which cmd
|
|
319
|
+
end
|
|
320
|
+
elsif ENV['OS'] == 'Windows_NT' || RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw|wince/i
|
|
321
|
+
'start ""'
|
|
322
|
+
else
|
|
323
|
+
raise "Could not work out how to use a browser."
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
`#{command} #{url}`
|
|
327
|
+
end
|
|
261
328
|
|
|
262
|
-
|
|
329
|
+
# Get the API base path
|
|
330
|
+
def base_path
|
|
331
|
+
ENV.key?(URL_ENV_NAME) ? GHE_BASE_PATH : GITHUB_BASE_PATH
|
|
263
332
|
end
|
|
264
333
|
|
|
265
|
-
#
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
command = str[1, str.length]
|
|
270
|
-
value = `#{command}`
|
|
271
|
-
else
|
|
272
|
-
value = str
|
|
273
|
-
end
|
|
334
|
+
# Get the API URL
|
|
335
|
+
def api_url
|
|
336
|
+
ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_API_URL
|
|
337
|
+
end
|
|
274
338
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
when "true", "1", "yes", "on"
|
|
279
|
-
true
|
|
339
|
+
def auth_token_file
|
|
340
|
+
if ENV.key?(URL_ENV_NAME)
|
|
341
|
+
File.expand_path "~/.gist.#{ENV[URL_ENV_NAME].gsub(/[^a-z.]/, '')}"
|
|
280
342
|
else
|
|
281
|
-
|
|
343
|
+
File.expand_path "~/.gist"
|
|
282
344
|
end
|
|
283
345
|
end
|
|
284
346
|
|
|
285
|
-
def
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
].find{|l| File.exist?(l) }
|
|
347
|
+
def legacy_private_gister?
|
|
348
|
+
return unless which('git')
|
|
349
|
+
`git config --global gist.private` =~ /\Ayes|1|true|on\z/i
|
|
350
|
+
end
|
|
290
351
|
|
|
291
|
-
|
|
292
|
-
|
|
352
|
+
def should_be_public?(options={})
|
|
353
|
+
if options.key? :private
|
|
354
|
+
!options[:private]
|
|
293
355
|
else
|
|
294
|
-
|
|
295
|
-
f.write(DATA.read.split("__CACERT__").last)
|
|
296
|
-
end
|
|
297
|
-
"/tmp/gist_cacert.pem"
|
|
356
|
+
!Gist.legacy_private_gister?
|
|
298
357
|
end
|
|
299
358
|
end
|
|
300
|
-
|
|
301
359
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
describe '...' do
|
|
2
|
+
before do
|
|
3
|
+
@saved_path = ENV['PATH']
|
|
4
|
+
@bobo_url = 'http://example.com'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
after do
|
|
8
|
+
ENV['PATH'] = @saved_path
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ask_for_copy
|
|
12
|
+
Gist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :html_url)
|
|
13
|
+
end
|
|
14
|
+
def gist_but_dont_ask_for_copy
|
|
15
|
+
Gist.on_success({'html_url' => 'http://example.com/'}.to_json, :output => :html_url)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should try to copy the url when the clipboard option is passed' do
|
|
19
|
+
Gist.should_receive(:copy).with(@bobo_url)
|
|
20
|
+
ask_for_copy
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should try to copy the embed url when the clipboard-js option is passed' do
|
|
24
|
+
js_link = %Q{<script src="#{@bobo_url}.js"></script>}
|
|
25
|
+
Gist.should_receive(:copy).with(js_link)
|
|
26
|
+
Gist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :javascript)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should not copy when not asked to" do
|
|
30
|
+
Gist.should_not_receive(:copy).with(@bobo_url)
|
|
31
|
+
gist_but_dont_ask_for_copy
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should raise an error if no copying mechanisms are available" do
|
|
35
|
+
ENV['PATH'] = ''
|
|
36
|
+
lambda{
|
|
37
|
+
ask_for_copy
|
|
38
|
+
}.should raise_error(/Could not find copy command.*http/m)
|
|
39
|
+
end
|
|
40
|
+
end
|