Merge pull request #1128 from voxik/patch-1
[rubygems] / Rakefile
1 # -*- ruby -*-
2
3 require 'rubygems'
4 require 'rubygems/package_task'
5
6 if ENV['YAML'] == "syck"
7   ENV['TEST_SYCK'] = "1"
8 end
9
10 begin
11   require 'psych'
12 rescue ::LoadError
13   require 'yaml'
14 end
15
16 require 'hoe'
17
18 Hoe::RUBY_FLAGS << " --disable-gems" if RUBY_VERSION > "1.9"
19
20 Hoe.plugin :minitest
21 Hoe.plugin :git
22 Hoe.plugin :travis
23
24 hoe = Hoe.spec 'rubygems-update' do
25   self.author         = ['Jim Weirich', 'Chad Fowler', 'Eric Hodel']
26   self.email          = %w[rubygems-developers@rubyforge.org]
27   self.readme_file    = 'README.rdoc'
28
29   license 'Ruby'
30   license 'MIT'
31
32   spec_extras[:required_rubygems_version] = Gem::Requirement.default
33   spec_extras[:required_ruby_version]     = Gem::Requirement.new '>= 1.8.7'
34   spec_extras[:executables]               = ['update_rubygems']
35
36   rdoc_locations <<
37     'docs.seattlerb.org:/data/www/docs.seattlerb.org/rubygems/'
38
39   clean_globs.push('**/debug.log',
40                    '*.out',
41                    '.config',
42                    'data__',
43                    'html',
44                    'logs',
45                    'graph.dot',
46                    'pkgs/sources/sources*.gem',
47                    'scripts/*.hieraki')
48
49   dependency 'builder',       '~> 2.1',   :dev
50   dependency 'hoe-seattlerb', '~> 1.2',   :dev
51   dependency 'rdoc',          '~> 3.0',   :dev
52   dependency 'ZenTest',       '~> 4.5',   :dev
53   dependency 'rake',          '~> 0.9.3', :dev
54   dependency 'minitest',      '~> 4.0',   :dev
55
56   self.extra_rdoc_files = Dir["*.rdoc"] + %w[
57     CVE-2013-4287.txt
58     CVE-2013-4363.txt
59   ]
60
61   spec_extras['rdoc_options'] = proc do |rdoc_options|
62     rdoc_options << "--title=RubyGems Update Documentation"
63   end
64
65   self.rsync_args += " --no-p -O"
66
67   spec_extras['require_paths'] = %w[hide_lib_for_update]
68 end
69
70 v = hoe.version
71
72 hoe.test_prelude = 'gem "minitest", "~> 4.0"'
73
74 Rake::Task['docs'].clear
75 Rake::Task['clobber_docs'].clear
76
77 begin
78   require 'rdoc/task'
79
80   RDoc::Task.new :rdoc => 'docs', :clobber_rdoc => 'clobber_docs' do |doc|
81     doc.main   = hoe.readme_file
82     doc.title  = "RubyGems #{v} API Documentation"
83
84     rdoc_files = Rake::FileList.new %w[lib History.txt LICENSE.txt MIT.txt]
85     rdoc_files.add hoe.extra_rdoc_files
86
87     doc.rdoc_files = rdoc_files
88
89     doc.rdoc_dir = 'doc'
90   end
91 rescue LoadError, RuntimeError # rake 10.1 on rdoc from ruby 1.9.2 and earlier
92   task 'docs' do
93     abort 'You must install rdoc to build documentation, try `rake newb` again'
94   end
95 end
96
97 desc "Install gems needed to run the tests"
98 task :install_test_deps => :clean_env do
99   sh "gem install minitest -v '~> 4.0'"
100 end
101
102 # --------------------------------------------------------------------
103 # Creating a release
104
105 task :prerelease => [:clobber, :check_manifest, :test]
106
107 task :postrelease => %w[upload guides:publish blog:publish publish_docs]
108
109 file "pkg/rubygems-#{v}" => "pkg/rubygems-update-#{v}" do |t|
110   require 'find'
111
112   dest_root = File.expand_path t.name
113
114   cd t.source do
115     Find.find '.' do |file|
116       dest = File.expand_path file, dest_root
117
118       if File.directory? file then
119         mkdir_p dest
120       else
121         rm_f dest
122         safe_ln file, dest
123       end
124     end
125   end
126 end
127
128 source_pkg_dir = "pkg/rubygems-#{v}"
129
130 file "pkg/rubygems-#{v}.tgz" => source_pkg_dir do
131   cd 'pkg' do
132     sh "tar -czf rubygems-#{v}.tgz rubygems-#{v}"
133   end
134 end
135
136 file "pkg/rubygems-#{v}.zip" => source_pkg_dir do
137   cd 'pkg' do
138     sh "zip -q -r rubygems-#{v}.zip rubygems-#{v}"
139   end
140 end
141
142 file "pkg/rubygems-update-#{v}.gem"
143
144 task :package => %W[
145        pkg/rubygems-update-#{v}.gem
146        pkg/rubygems-#{v}.tgz
147        pkg/rubygems-#{v}.zip
148      ]
149
150 desc "Upload release to gemcutter S3"
151 task :upload_to_gemcutter do
152   sh "s3cmd put -P pkg/rubygems-update-#{v}.gem pkg/rubygems-#{v}.zip pkg/rubygems-#{v}.tgz s3://production.s3.rubygems.org/rubygems/"
153 end
154
155 desc "Upload release to rubygems.org"
156 task :upload => %w[upload_to_gemcutter]
157
158 on_master = `git branch --list master`.strip == '* master'
159 on_master = true if ENV['FORCE']
160
161 Rake::Task['publish_docs'].clear unless on_master
162
163 directory '../guides.rubygems.org' do
164   sh 'git', 'clone',
165      'git@github.com:rubygems/guides.git',
166      '../guides.rubygems.org'
167 end
168
169 namespace 'guides' do
170   task 'pull' => %w[../guides.rubygems.org] do
171     chdir '../guides.rubygems.org' do
172       sh 'git', 'pull'
173     end
174   end
175
176   task 'update' => %w[../guides.rubygems.org] do
177     lib_dir = File.join Dir.pwd, 'lib'
178
179     chdir '../guides.rubygems.org' do
180       ruby '-I', lib_dir, '-S', 'rake', 'command_guide'
181       ruby '-I', lib_dir, '-S', 'rake', 'spec_guide'
182     end
183   end
184
185   task 'commit' => %w[../guides.rubygems.org] do
186     chdir '../guides.rubygems.org' do
187       begin
188         sh 'git', 'diff', '--quiet'
189       rescue
190         sh 'git', 'commit', 'command-reference.md', 'specification-reference.md',
191            '-m', "Rebuild for RubyGems #{v}"
192       end
193     end
194   end
195
196   task 'push' => %w[../guides.rubygems.org] do
197     chdir '../guides.rubygems.org' do
198       sh 'git', 'push'
199     end
200   end
201
202   desc 'Updates and publishes the guides for the just-released RubyGems'
203   task 'publish'
204
205   task 'publish' => %w[
206     guides:pull
207     guides:update
208     guides:commit
209     guides:push
210   ] if on_master
211 end
212
213 directory '../blog.rubygems.org' do
214   sh 'git', 'clone',
215      'git@github.com:rubygems/rubygems.github.com.git',
216      '../blog.rubygems.org'
217 end
218
219 namespace 'blog' do
220   date = Time.now.strftime '%Y-%m-%d'
221   post_page = "_posts/#{date}-#{v}-released.md"
222   checksums = ''
223
224   task 'checksums' => 'package' do
225     require 'digest'
226     Dir['pkg/*{tgz,zip,gem}'].map do |file|
227       digest = Digest::SHA256.new
228
229       open file, 'rb' do |io|
230         while chunk = io.read(65536) do
231           digest.update chunk
232         end
233       end
234
235       checksums << "* #{File.basename(file)}  \n"
236       checksums << "  #{digest.hexdigest}\n"
237     end
238   end
239
240   task 'pull' => %w[../blog.rubygems.org] do
241     chdir '../blog.rubygems.org' do
242       sh 'git', 'pull'
243     end
244   end
245
246   path = File.join '../blog.rubygems.org', post_page
247
248   task 'update' => [path]
249
250   file path => 'checksums' do
251     name  = `git config --get user.name`.strip
252     email = `git config --get user.email`.strip
253
254     history = File.read 'History.txt'
255
256     history.force_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
257
258     _, change_log, = history.split %r%^===\s*\d.*%, 3
259
260     change_types = []
261
262     lines = change_log.strip.lines
263     change_log = []
264
265     while line = lines.shift do
266       case line
267       when /(^[A-Z].*)/ then
268         change_types << $1
269         change_log << "_#{$1}_\n"
270       when /^\*/ then
271         entry = [line.strip]
272
273         while /^  \S/ =~ lines.first do
274           entry << lines.shift.strip
275         end
276
277         change_log << "#{entry.join ' '}\n"
278       else
279         change_log << line
280       end
281     end
282
283     change_log = change_log.join
284
285     change_types = change_types.map do |change_type|
286       change_type.downcase.tr '^a-z ', ''
287     end
288
289     last_change_type = change_types.pop
290
291     if change_types.empty? then
292       change_types = ''
293     else
294       change_types = change_types.join(', ') << ' and '
295     end
296
297     change_types << last_change_type
298
299     require 'tempfile'
300
301     Tempfile.open 'blog_post' do |io|
302       io.write <<-ANNOUNCEMENT
303 ---
304 title: #{v} Released
305 layout: post
306 author: #{name}
307 author_email: #{email}
308 ---
309
310 RubyGems #{v} includes #{change_types}.
311
312 To update to the latest RubyGems you can run:
313
314     gem update --system
315
316 If you need to upgrade or downgrade please follow the [how to upgrade/downgrade
317 RubyGems][upgrading] instructions.  To install RubyGems by hand see the
318 [Download RubyGems][download] page.
319
320 #{change_log}
321
322 SHA256 Checksums:
323
324 #{checksums}
325
326 [download]: http://rubygems.org/pages/download
327 [upgrading]: http://docs.seattlerb.org/rubygems/UPGRADING_rdoc.html
328
329       ANNOUNCEMENT
330
331       io.flush
332
333       sh ENV['EDITOR'], io.path
334
335       FileUtils.cp io.path, path
336     end
337   end
338
339   task 'commit' => %w[../blog.rubygems.org] do
340     chdir '../blog.rubygems.org' do
341       sh 'git', 'add', post_page
342       sh 'git', 'commit', post_page,
343          '-m', "Added #{v} release announcement"
344     end
345   end
346
347   task 'push' => %w[../blog.rubygems.org] do
348     chdir '../blog.rubygems.org' do
349       sh 'git', 'push'
350     end
351   end
352
353   desc 'Updates and publishes the blog for the just-released RubyGems'
354   task 'publish' => %w[
355     blog:pull
356     blog:update
357     blog:commit
358     blog:push
359   ]
360 end
361
362 # Misc Tasks ---------------------------------------------------------
363
364 # These tasks expect to have the following directory structure:
365 #
366 #   git/git.rubini.us/code # Rubinius git HEAD checkout
367 #   svn/ruby/trunk         # ruby subversion HEAD checkout
368 #   svn/rubygems/trunk     # RubyGems subversion HEAD checkout
369 #
370 # If you don't have this directory structure, set RUBY_PATH and/or
371 # RUBINIUS_PATH.
372
373 def rsync_with dir
374   rsync_options =
375     "-avP " +
376     "--exclude '*svn*' " +
377     "--exclude '*swp' " +
378     "--exclude '*rbc' " +
379     "--exclude '*.rej' " +
380     "--exclude '*.orig' " +
381     "--exclude 'lib/rubygems/defaults/*' " +
382     "--exclude gauntlet_rubygems.rb"
383
384   sh "rsync #{rsync_options} bin/gem             #{dir}/bin/gem"
385   sh "rsync #{rsync_options} lib/                #{dir}/lib"
386   sh "rsync #{rsync_options} test/               #{dir}/test"
387 end
388
389 def diff_with dir
390   diff_options = "-urpN --exclude '*svn*' --exclude '*swp' --exclude '*rbc'"
391   sh "diff #{diff_options} bin/gem             #{dir}/bin/gem;         true"
392   sh "diff #{diff_options} lib/ubygems.rb      #{dir}/lib/ubygems.rb;  true"
393   sh "diff #{diff_options} lib/rubygems.rb     #{dir}/lib/rubygems.rb; true"
394   sh "diff #{diff_options} lib/rubygems        #{dir}/lib/rubygems;    true"
395   sh "diff #{diff_options} lib/rbconfig        #{dir}/lib/rbconfig;    true"
396   sh "diff #{diff_options} test/rubygems       #{dir}/test/rubygems;   true"
397 end
398
399 rubinius_dir = ENV['RUBINIUS_PATH'] || '../git.rubini.us/code'
400 ruby_dir     = ENV['RUBY_PATH']     || '../../svn/ruby/trunk'
401
402 desc "Updates Ruby HEAD with the currently checked-out copy of RubyGems."
403 task :update_ruby do
404   rsync_with ruby_dir
405 end
406
407 desc "Updates Rubinius HEAD with the currently checked-out copy of RubyGems."
408 task :update_rubinius do
409   rsync_with rubinius_dir
410 end
411
412 desc "Diffs Ruby HEAD with the currently checked-out copy of RubyGems."
413 task :diff_ruby do
414   diff_with ruby_dir
415 end
416
417 desc "Diffs Rubinius HEAD with the currently checked-out copy of RubyGems."
418 task :diff_rubinius do
419   diff_with rubinius_dir
420 end
421
422 desc "Cleanup trailing whitespace"
423 task :whitespace do
424   system 'find . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 sed -i "" -E "s/[[:space:]]*$//"'
425 end