Files
textmate/bin/upload
Allan Odgaard 720f9eac98 Expect more than just {?name} in GitHub’s URI template
Currently GitHub supports both name and label parameters.
2015-10-03 17:33:21 +07:00

118 lines
4.0 KiB
Ruby
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby -w
# == Synopsis
#
# upload [-k «keyfile»] [-d «destination»] [-m «json»] «file»
#
# == Usage
#
# --help:
# show help.
#
# --keyfile/-k:
# Keyfile used for signing.
#
# --destination/-d:
# Which GitHub «user»/«repository» we should upload to.
#
# --merge/-m:
# JSON that should be placed in the result dictionary.
#
# --description/-s:
# Optional description.
#
require 'getoptlong'
require "rubygems"
require "net/netrc"
require "json"
require 'base64'
require 'openssl'
require 'digest/sha1'
def sign_file(path, keyfile, password)
# %x{openssl dgst -dss1 -sign '#{keyfile}' -passin 'pass:#{password}' '#{path}'|openssl enc -base64}.chomp
key = OpenSSL::PKey::DSA.new(File.read(keyfile), password) or abort "*** error reading keyfile: #{keyfile}."
digest = Digest::SHA1.digest(File.read(path))
signature = key.syssign(digest)
Base64.encode64(signature).gsub("\n", '')
end
def create_release(path, repository, tag, description, content_type)
name = tag.sub(/^v(.*?)-(.*?)\.(.*)$/, 'TextMate \1 (\2 \3)')
basename = File::basename(path)
payload = { 'name' => name, 'tag_name' => tag, 'draft' => false, 'prerelease' => true }
payload['body'] = description unless description.nil?
open("|curl -snd '#{payload.to_json}' https://api.github.com/repos/#{repository}/releases") do |response|
github = JSON.parse(response.read)
if github.include?('errors')
err = github['errors'].first
if err['code'] == 'already_exists' && err['field'] == 'tag_name'
open("|curl -sn https://api.github.com/repos/#{repository}/releases") do |io|
github = JSON.parse(io.read)
github = github.find { |e| e['tag_name'] == tag }
STDERR << "Upload to existing release: #{github['html_url']}\n"
end
else
abort "GitHub error: #{github['errors'].inspect} for #{repository}" if github.include?('errors')
end
end
if url = github['upload_url']
url.sub!(/\{\?.*?\}/, '')
upload_url = "|curl -nH'Content-Type: #{content_type}' --data-binary @'#{path}' '#{url}?name=#{basename}'"
open(upload_url) do |io|
res = JSON.parse(io.read)
return "https://github.com/#{repository}/releases/download/#{tag}/#{basename}" if res.include?('url')
STDERR << "Unexpected response (asset): #{res.inspect}\n"
end
else
STDERR << "Unexpected response (release): #{github.inspect}\n"
end
open("|curl -snX DELETE #{github['url']}") { |io| STDERR << "Removing release: #{github['url']}\n" }
end
abort
end
if __FILE__ == $PROGRAM_NAME
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--keyfile', '-k', GetoptLong::REQUIRED_ARGUMENT ],
[ '--destination', '-d', GetoptLong::REQUIRED_ARGUMENT ],
[ '--tag', '-t', GetoptLong::REQUIRED_ARGUMENT ],
[ '--merge', '-m', GetoptLong::REQUIRED_ARGUMENT ],
[ '--description', '-s', GetoptLong::REQUIRED_ARGUMENT ]
)
keyfile = nil
destination = 'textmate/textmate'
tag = nil
base_info = { }
description = nil
netinfo = Net::Netrc.locate("sign.textmate.org") or abort "*** missing passphrase in ~/.netrc."
opts.each do |opt, arg|
case opt
when '--help' then RDoc::usage
when '--keyfile' then keyfile = arg
when '--destination' then destination = arg
when '--tag' then tag = arg
when '--merge' then base_info = JSON.parse(arg)
when '--description' then description = arg
end
end
abort 'No signing key provided' if keyfile.nil?
abort "No tag specified" if tag.nil?
if path = ARGV.shift
signature = sign_file(path, keyfile, netinfo.password)
info = base_info.merge({
'url' => create_release(path, destination, tag, description, 'application/x-bzip2'),
'signature' => signature,
'signee' => netinfo.login
})
STDOUT << info.to_json
end
end