summaryrefslogtreecommitdiffstats
path: root/junit4/build/github_upload.rb
blob: ad5df46d52733e162da37d2fe851d301d5851bba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# 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"
# )