task/gemgem.rb in rack-handlers-0.7.0 vs task/gemgem.rb in rack-handlers-0.7.1
- old
+ new
@@ -1,202 +1,213 @@
-require 'pathname'
-
module Gemgem
class << self
- attr_accessor :dir, :spec
+ attr_accessor :dir, :spec, :spec_create
end
module_function
+ def gem_tag ; "#{spec.name}-#{spec.version}" ; end
+ def gem_path ; "#{pkg_dir}/#{gem_tag}.gem" ; end
+ def spec_path ; "#{dir}/#{spec.name}.gemspec" ; end
+ def pkg_dir ; "#{dir}/pkg" ; end
+ def escaped_dir; @escaped_dir ||= Regexp.escape(dir); end
+
+ def init dir, &block
+ self.dir = dir
+ $LOAD_PATH.unshift("#{dir}/lib")
+ ENV['RUBYLIB'] = "#{dir}/lib:#{ENV['RUBYLIB']}"
+ ENV['PATH'] = "#{dir}/bin:#{ENV['PATH']}"
+ self.spec_create = block
+ end
+
def create
- yield(spec = Gem::Specification.new{ |s|
+ spec = Gem::Specification.new do |s|
s.authors = ['Lin Jen-Shin (godfat)']
s.email = ['godfat (XD) godfat.org']
s.description = description.join
s.summary = description.first
+ s.license = readme['LICENSE'].sub(/.+\n\n/, '').lines.first.strip
- s.rubygems_version = Gem::VERSION
- s.date = Time.now.strftime('%Y-%m-%d')
- s.files = gem_files
- s.test_files = gem_files.grep(%r{^test/(.+?/)*test_.+?\.rb$})
- s.executables = Dir['bin/*'].map{ |f| File.basename(f) }
- s.require_paths = %w[lib]
- })
- spec.homepage ||= "https://github.com/godfat/#{spec.name}"
- spec
+ s.date = Time.now.strftime('%Y-%m-%d')
+ s.files = gem_files
+ s.test_files = test_files
+ s.executables = bin_files
+ end
+ spec_create.call(spec)
+ spec.homepage = "https://github.com/godfat/#{spec.name}"
+ self.spec = spec
end
- def readme
- path = %w[README.md README].find{ |name|
- File.exist?("#{Gemgem.dir}/#{name}")
- }
- @readme ||=
- if path
- ps = "##{File.read(path)}".
- scan(/((#+)[^\n]+\n\n.+?(?=\n\n\2[^#\n]+\n))/m).map(&:first)
- ps.inject({'HEADER' => ps.first}){ |r, s, i|
- r[s[/\w+/]] = s
- r
- }
+ def write
+ File.open(spec_path, 'w'){ |f| f << split_lines(spec.to_ruby) }
+ end
+
+ def split_lines ruby
+ ruby.gsub(/(.+?)\s*=\s*\[(.+?)\]/){ |s|
+ if $2.index(',')
+ "#{$1} = [\n #{$2.split(',').map(&:strip).join(",\n ")}]"
else
- {}
+ s
end
+ }
end
- def description
- @description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines.to_a
+ def strip_path path
+ strip_home_path(strip_cwd_path(path))
end
- def changes
- path = %w[CHANGES.md CHANGES].find{ |name|
- File.exist?("#{Gemgem.dir}/#{name}")
- }
- @changes ||=
- if path
- date = '\d+{4}\-\d+{2}\-\d{2}'
- File.read(path).match(
- /([^\n]+#{date}\n\n(.+?))(?=\n\n[^\n]+#{date}\n|\Z)/m)[1]
- else
- ''
- end
+ def strip_home_path path
+ path.sub(ENV['HOME'], '~')
end
- def ann_md
- "#{readme['HEADER'].sub(/([\w\-]+)/, "[\\1](#{spec.homepage})")}\n\n" \
- "##{readme['DESCRIPTION'][/[^\n]+\n\n[^\n]+/]}\n\n" \
- "### CHANGES:\n\n" \
- "###{changes}\n\n" \
- "##{readme['INSTALLATION']}\n\n" +
- if readme['SYNOPSIS'] then "##{readme['SYNOPSIS'][/[^\n]+\n\n[^\n]+/]}"
- else '' end
+ def strip_cwd_path path
+ path.sub(Dir.pwd, '.')
end
- def ann_html
- gem 'nokogiri'
- gem 'kramdown'
-
- IO.popen('kramdown', 'r+') do |md|
- md.puts Gemgem.ann_md
- md.close_write
- require 'nokogiri'
- html = Nokogiri::XML.parse("<gemgem>#{md.read}</gemgem>")
- html.css('*').each{ |n| n.delete('id') }
- html.root.children.to_html
- end
+ def git *args
+ `git --git-dir=#{dir}/.git #{args.join(' ')}`
end
- def ann_email
- "#{readme['HEADER'].sub(/([\w\-]+)/, "\\1 <#{spec.homepage}>")}\n\n" \
- "#{readme['DESCRIPTION']}\n\n" \
- "#{readme['INSTALLATION']}\n\n" +
- if readme['SYNOPSIS'] then "##{readme['SYNOPSIS']}\n\n" else '' end +
- "## CHANGES:\n\n" \
- "##{changes}\n\n"
+ def sh_git *args
+ Rake.sh('git', "--git-dir=#{dir}/.git", *args)
end
- def gem_tag
- "#{spec.name}-#{spec.version}"
+ def sh_gem *args
+ Rake.sh(Gem.ruby, '-S', 'gem', *args)
end
- def write
- File.open("#{dir}/#{spec.name}.gemspec", 'w'){ |f|
- f << split_lines(spec.to_ruby) }
+ def glob path=dir
+ Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
end
- def split_lines ruby
- ruby.gsub(/(.+?)\[(.+?)\]/){ |s|
- if $2.index(',')
- "#{$1}[\n #{$2.split(',').map(&:strip).join(",\n ")}]"
+ def readme
+ @readme ||=
+ if (path = "#{Gemgem.dir}/README.md") && File.exist?(path)
+ ps = "##{File.read(path)}".
+ scan(/((#+)[^\n]+\n\n.+?(?=(\n\n\2[^#\n]+\n)|\Z))/m).map(&:first)
+ ps.inject('HEADER' => ps.first){ |r, s, i|
+ r[s[/\w+/]] = s
+ r
+ }
else
- s
+ {}
end
- }
end
+ def description
+ # JRuby String#lines is returning an enumerator
+ @description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines.to_a
+ end
+
def all_files
- @all_files ||= find_files(Pathname.new(dir)).map{ |file|
- if file.to_s =~ %r{\.git/|\.git$}
- nil
+ @all_files ||= fold_files(glob).sort
+ end
+
+ def fold_files files
+ files.inject([]){ |r, path|
+ if File.file?(path) && path !~ %r{/\.git(/|$)} &&
+ (rpath = path[%r{^#{escaped_dir}/(.*$)}, 1])
+ r << rpath
+ elsif File.symlink?(path) # walk into symlinks...
+ r.concat(fold_files(glob(File.expand_path(path,
+ File.readlink(path)))))
else
- file.to_s
+ r
end
- }.compact.sort
+ }
end
def gem_files
- @gem_files ||= all_files - ignored_files
+ @gem_files ||= all_files.reject{ |f|
+ f =~ ignored_pattern && !git_files.include?(f)
+ }
end
- def ignored_files
- @ignored_file ||= all_files.select{ |path| ignore_patterns.find{ |ignore|
- path =~ ignore && !git_files.include?(path)}}
+ def test_files
+ @test_files ||= gem_files.grep(%r{^test/(.+?/)*test_.+?\.rb$})
end
+ def bin_files
+ @bin_files ||= gem_files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+ end
+
def git_files
@git_files ||= if File.exist?("#{dir}/.git")
- `git ls-files`.split("\n")
+ git('ls-files').split("\n")
else
[]
end
end
- # protected
- def find_files path
- path.children.select(&:file?).map{|file| file.to_s[(dir.size+1)..-1]} +
- path.children.select(&:directory?).map{|dir| find_files(dir)}.flatten
+ def ignored_files
+ @ignored_files ||= all_files.grep(ignored_pattern)
end
- def ignore_patterns
- @ignore_files ||= expand_patterns(
- gitignore.split("\n").reject{ |pattern|
- pattern.strip == ''
- }).map{ |pattern| %r{^([^/]+/)*?#{Regexp.escape(pattern)}(/[^/]+)*?$} }
+ def ignored_pattern
+ @ignored_pattern ||= Regexp.new(expand_patterns(gitignore).join('|'))
end
def expand_patterns pathes
- pathes.map{ |path|
- if path !~ /\*/
- path
- else
- expand_patterns(
- Dir[path] +
- Pathname.new(File.dirname(path)).children.select(&:directory?).
- map{ |prefix| "#{prefix}/#{File.basename(path)}" })
+ # http://git-scm.com/docs/gitignore
+ pathes.flat_map{ |path|
+ case path
+ when %r{\*}
+ Regexp.escape(path).gsub(/\\\*/, '[^/]*')
+ when %r{^/}
+ "^#{Regexp.escape(path[1..-1])}"
+ else # we didn't implement negative pattern for now
+ Regexp.escape(path)
end
- }.flatten
+ }
end
def gitignore
- if File.exist?(path = "#{dir}/.gitignore")
- File.read(path)
- else
- ''
- end
+ @gitignore ||= if File.exist?(path = "#{dir}/.gitignore")
+ File.read(path).lines.
+ reject{ |l| l == /^\s*(#|\s+$)/ }.map(&:strip)
+ else
+ []
+ end
end
end
namespace :gem do
desc 'Install gem'
task :install => [:build] do
- sh("#{Gem.ruby} -S gem install pkg/#{Gemgem.gem_tag}.gem")
+ Gemgem.sh_gem('install', Gemgem.gem_path)
end
desc 'Build gem'
task :build => [:spec] do
- sh("#{Gem.ruby} -S gem build #{Gemgem.spec.name}.gemspec")
- sh("mkdir -p pkg")
- sh("mv #{Gemgem.gem_tag}.gem pkg/")
+ require 'fileutils'
+ require 'rubygems/package'
+ gem = nil
+ Dir.chdir(Gemgem.dir) do
+ gem = Gem::Package.build(Gem::Specification.load(Gemgem.spec_path))
+ FileUtils.mkdir_p(Gemgem.pkg_dir)
+ FileUtils.mv(gem, Gemgem.pkg_dir) # gem is relative path, but might be ok
+ end
+ puts "\e[35mGem built: \e[33m" \
+ "#{Gemgem.strip_path("#{Gemgem.pkg_dir}/#{gem}")}\e[0m"
end
+desc 'Generate gemspec'
+task :spec do
+ Gemgem.create
+ Gemgem.write
+end
+
desc 'Release gem'
task :release => [:spec, :check, :build] do
- sh("git tag #{Gemgem.gem_tag}")
- sh("git push")
- sh("git push --tags")
- sh("#{Gem.ruby} -S gem push pkg/#{Gemgem.gem_tag}.gem")
+ Gemgem.module_eval do
+ sh_git('tag', Gemgem.gem_tag)
+ sh_git('push')
+ sh_git('push', '--tags')
+ sh_gem('push', Gemgem.gem_path)
+ end
end
task :check do
ver = Gemgem.spec.version.to_s
@@ -215,53 +226,39 @@
end # of gem namespace
desc 'Run tests in memory'
task :test do
+ next if Gemgem.test_files.empty?
+
require 'bacon'
Bacon.extend(Bacon::TestUnitOutput)
Bacon.summary_on_exit
- $LOAD_PATH.unshift('lib')
- Dir['./test/**/test_*.rb'].each{ |file| require file[0..-4] }
+ Gemgem.test_files.each{ |file| require "#{Gemgem.dir}/#{file[0..-4]}" }
end
-desc 'Run tests with shell'
-task 'test:shell', :RUBY_OPTS do |t, args|
- files = Dir['test/**/test_*.rb'].join(' ')
+desc 'Remove ignored files'
+task :clean => ['gem:spec'] do
+ next if Gemgem.ignored_files.empty?
- cmd = [Gem.ruby, args[:RUBY_OPTS],
- '-I', 'lib', '-S', 'bacon', '--quiet', files]
+ require 'fileutils'
+ trash = File.expand_path("~/.Trash/#{Gemgem.spec.name}")
+ puts "Move the following files into:" \
+ " \e[35m#{Gemgem.strip_path(trash)}\e[33m"
- sh(cmd.compact.join(' '))
-end
+ Gemgem.ignored_files.each do |file|
+ from = "#{Gemgem.dir}/#{file}"
+ to = "#{trash}/#{File.dirname(file)}"
+ puts Gemgem.strip_path(from)
-desc 'Generate ann markdown'
-task 'ann:md' => ['gem:spec'] do
- puts Gemgem.ann_md
-end
+ FileUtils.mkdir_p(to)
+ FileUtils.mv(from, to)
+ end
-desc 'Generate ann html'
-task 'ann:html' => ['gem:spec'] do
- puts Gemgem.ann_html
+ print "\e[0m"
end
-desc 'Generate ann email'
-task 'ann:email' => ['gem:spec'] do
- puts Gemgem.ann_email
-end
-
-desc 'Generate rdoc'
-task :doc => ['gem:spec'] do
- sh("yardoc -o rdoc --main README.md" \
- " --files #{Gemgem.spec.extra_rdoc_files.join(',')}")
-end
-
-desc 'Remove ignored files'
-task :clean => ['gem:spec'] do
- trash = "~/.Trash/#{Gemgem.spec.name}/"
- sh "mkdir -p #{trash}" unless File.exist?(File.expand_path(trash))
- Gemgem.ignored_files.each{ |file| sh "mv #{file} #{trash}" }
-end
-
task :default do
- puts `#{Gem.ruby} -S #{$PROGRAM_NAME} -T`
+ # Is there a reliable way to do this in the current process?
+ # It failed miserably before between Rake versions...
+ exec "#{Gem.ruby} -S #{$PROGRAM_NAME} -f #{Rake.application.rakefile} -T"
end