blob: ad5df46d52733e162da37d2fe851d301d5851bba [file] [log] [blame]
# require
require 'rubygems'
#### INLINE: fixed version of https://github.com/github/upload ####
require 'tempfile'
require 'nokogiri'
require 'httpclient'
require 'stringio'
require 'json'
require 'faster_xml_simple'
module Net
module GitHub
class Upload
VERSION = '0.0.5'
def initialize params=nil
@login = params[:login]
@token = params[:token]
if @login.empty? or @token.empty?
raise "login or token is empty"
end
end
def upload info
unless info[:repos]
raise "required repository name"
end
info[:repos] = @login + '/' + info[:repos] unless info[:repos].include? '/'
if info[:file]
file = info[:file]
unless File.exist?(file) && File.readable?(file)
raise "file does not exsits or readable"
end
info[:name] ||= File.basename(file)
end
unless info[:file] || info[:data]
raise "required file or data parameter to upload"
end
unless info[:name]
raise "required name parameter for filename with data parameter"
end
if info[:replace]
list_files(info[:repos]).each { |obj|
next unless obj[:name] == info[:name]
delete info[:repos], obj[:id]
}
elsif list_files(info[:repos]).any?{|obj| obj[:name] == info[:name]}
raise "file '#{info[:name]}' is already uploaded. please try different name"
end
info[:content_type] ||= 'application/octet-stream'
stat = HTTPClient.post("https://github.com/#{info[:repos]}/downloads", {
"file_size" => info[:file] ? File.stat(info[:file]).size : info[:data].size,
"content_type" => info[:content_type],
"file_name" => info[:name],
"description" => info[:description] || '',
"login" => @login,
"token" => @token
})
unless stat.code == 200
raise "Failed to post file info"
end
upload_info = JSON.parse(stat.content)
if info[:file]
f = File.open(info[:file], 'rb')
else
f = Tempfile.open('net-github-upload')
f << info[:data]
f.flush
end
stat = HTTPClient.post("http://github.s3.amazonaws.com/", [
['Filename', info[:name]],
['policy', upload_info['policy']],
['success_action_status', 201],
['key', upload_info['path']],
['AWSAccessKeyId', upload_info['accesskeyid']],
['Content-Type', upload_info['content_type'] || 'application/octet-stream'],
['signature', upload_info['signature']],
['acl', upload_info['acl']],
['file', f]
])
f.close
if stat.code == 201
return FasterXmlSimple.xml_in(stat.content)['PostResponse']['Location']
else
raise 'Failed to upload' + extract_error_message(stat)
end
end
def replace info
upload info.merge( :replace => true )
end
def delete_all repos
unless repos
raise "required repository name"
end
repos = @login + '/' + repos unless repos.include? '/'
list_files(repos).each { |obj|
delete repos, obj[:id]
}
end
private
def extract_error_message(stat)
# @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorResponses.html
error = FasterXmlSimple.xml_in(stat.content)['Error']
" due to #{error['Code']} (#{error['Message']})"
rescue
''
end
def delete repos, id
HTTPClient.post("https://github.com/#{repos}/downloads/#{id.gsub( "download_", '')}", {
"_method" => "delete",
"login" => @login,
"token" => @token
})
end
def list_files repos
raise "required repository name" unless repos
res = HTTPClient.get_content("https://github.com/#{repos}/downloads", {
"login" => @login,
"token" => @token
})
Nokogiri::HTML(res).xpath('id("manual_downloads")/li').map do |fileinfo|
obj = {
:description => fileinfo.at_xpath('descendant::h4').text,
:date => fileinfo.at_xpath('descendant::p/time').attribute('title').text,
:size => fileinfo.at_xpath('descendant::p/strong').text,
:id => /\d+$/.match(fileinfo.at_xpath('a').attribute('href').text)[0]
}
anchor = fileinfo.at_xpath('descendant::h4/a')
obj[:link] = anchor.attribute('href').text
obj[:name] = anchor.text
obj
end
end
end
end
end
#### END INLINE ####
# setup
login = `git config github.user`.chomp # your login for github
token = `git config github.token`.chomp # your token for github
repos = 'KentBeck/junit' # your repos name (like 'taberareloo')
gh = Net::GitHub::Upload.new(
:login => login,
:token => token
)
version = ARGV[0]
def upload(gh, version, repos, filename, description)
gh.upload(:repos => repos,
:file => "junit#{version}/#{filename}",
:description => description)
end
upload(gh, version, repos, "junit-#{version}-src.jar", 'Source jar')
upload(gh, version, repos, "junit-#{version}.jar", 'Basic jar')
upload(gh, version, repos, "junit-dep-#{version}.jar", 'Jar without hamcrest')
upload(gh, version, repos, "junit#{version}.zip", 'Source zip')
# # file upload
# direct_link = gh.upload(
# :repos => repos,
# :file => 'test/test',
# :description => "test file"
# )
# # direct link is link to Amazon S3.
# # Because GitHub refrection for file changing is async,
# # if you get changed file synchronously, you use this "direct_link"
#
# # data upload
# # you can define content_type => Amazon S3 Content-Type
# time = Time.now.to_i
# direct_link = gh.upload(
# :repos => repos,
# :data => 'test',
# :name => "test_#{time}.txt",
# :content_type => 'text/plain',
# :description => "test file2"
# )
#
# # replace file or data
# # thx id:rngtng !
# direct_link = gh.replace(
# :repos => repos,
# :file => 'test/test',
# :description => "test file"
# )
# direct_link = gh.replace(
# :repos => repos,
# :data => 'test',
# :name => "test_#{time}.txt",
# :content_type => 'text/plain',
# :description => "test file2"
# )