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
|
require 'pathname'
# Public: A Class containing all the metadata and utilities needed to manage a
# ruby project.
class ThisProject
# The name of this project
attr_accessor :name
# The author's name
attr_accessor :author
# The email address of the author(s)
attr_accessor :email
# The homepage of this project
attr_accessor :homepage
# The regex of files to exclude from the manifest
attr_accessor :exclude_from_manifest
# The hash of Gem::Specifications keyed' by platform
attr_accessor :gemspecs
# Public: Initialize ThisProject
#
# Yields self
def initialize(&block)
@exclude_from_manifest = Regexp.union(/\.(git|DS_Store)/,
/^(doc|coverage|pkg|tmp|Gemfile(\.lock)?)/,
/^[^\/]+\.gemspec/,
/\.(swp|jar|bundle|so|rvmrc|travis.yml|byebug_history)$/,
/~$/)
@gemspecs = Hash.new
yield self if block_given?
end
# Public: return the version of ThisProject
#
# Search the ruby files in the project looking for the one that has the
# version string in it. This does not eval any code in the project, it parses
# the source code looking for the string.
#
# Returns a String version
def version
[ "lib/#{ name }.rb", "lib/#{ name }/version.rb" ].each do |v|
path = project_path( v )
line = path.read[/^\s*VERSION\s*=\s*.*/]
if line then
return line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
end
end
end
# Internal: Return a section of an RDoc file with the given section name
#
# path - the relative path in the project of the file to parse
# section_name - the section out of the file from which to parse data
#
# Retuns the text of the section as an array of paragrphs.
def section_of( file, section_name )
re = /^[=#]+ (.*)$/
sectional = project_path( file )
parts = sectional.read.split( re )[1..-1]
parts.map! { |p| p.strip }
sections = Hash.new
Hash[*parts].each do |k,v|
sections[k] = v.split("\n\n")
end
return sections[section_name]
end
# Internal: print out a warning about the give task
def task_warning( task )
warn "WARNING: '#{task}' tasks are not defined. Please run 'rake develop'"
end
# Internal: Return the full path to the file that is relative to the project
# root.
#
# path - the relative path of the file from the project root
#
# Returns the Pathname of the file
def project_path( *relative_path )
project_root.join( *relative_path )
end
# Internal: The absolute path of this file
#
# Returns the Pathname of this file.
def this_file_path
Pathname.new( __FILE__ ).expand_path
end
# Internal: The root directory of this project
#
# This is defined as being the directory that is in the path of this project
# that has the first Rakefile
#
# Returns the Pathname of the directory
def project_root
this_file_path.ascend do |p|
rakefile = p.join( 'Rakefile' )
return p if rakefile.exist?
end
end
# Internal: Returns the contents of the Manifest.txt file as an array
#
# Returns an Array of strings
def manifest
manifest_file = project_path( "Manifest.txt" )
abort "You need a Manifest.txt" unless manifest_file.readable?
manifest_file.readlines.map { |l| l.strip }
end
# Internal: Return the files that define the extensions
#
# Returns an Array
def extension_conf_files
manifest.grep( /extconf.rb\Z/ )
end
# Internal: Returns the gemspace associated with the current ruby platform
def platform_gemspec
gemspecs.fetch(platform) { This.ruby_gemspec }
end
def core_gemspec
Gem::Specification.new do |spec|
spec.name = name
spec.version = version
spec.author = author
spec.email = email
spec.homepage = homepage
spec.summary = summary
spec.description = description
spec.license = license
spec.files = manifest
spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
spec.test_files = spec.files.grep(/^spec/)
spec.extra_rdoc_files += spec.files.grep(/(txt|rdoc|md)$/)
spec.rdoc_options = [ "--main" , 'README.md',
"--markup", "tomdoc" ]
spec.required_ruby_version = '>= 2.2.2'
end
end
# Internal: Return the gemspec for the ruby platform
def ruby_gemspec( core = core_gemspec, &block )
yielding_gemspec( 'ruby', core, &block )
end
# Internal: Return the gemspec for the jruby platform
def java_gemspec( core = core_gemspec, &block )
yielding_gemspec( 'java', core, &block )
end
# Internal: give an initial spec and a key, create a new gemspec based off of
# it.
#
# This will force the new gemspecs 'platform' to be that of the key, since the
# only reason you would have multiple gemspecs at this point is to deal with
# different platforms.
def yielding_gemspec( key, core )
spec = gemspecs[key] ||= core.dup
spec.platform = key
yield spec if block_given?
return spec
end
# Internal: Return the platform of ThisProject at the current moment in time.
def platform
(RUBY_PLATFORM == "java") ? 'java' : Gem::Platform::RUBY
end
# Internal: Return the Description section of the README.rdoc file
def description_section
section_of( 'README.md', 'Description')
end
# Internal: Return the summary text from the README
def summary
description_section.first
end
# Internal: Return the full description text from the README
def description
description_section.join(" ").tr("\n", ' ').gsub(/[{}]/,'').gsub(/\[[^\]]+\]/,'') # strip rdoc
end
def license
license_file = project_path("LICENSE")
line = license_file.readlines.first
line.split(/\s+/).first
end
# Internal: The path to the gemspec file
def gemspec_file
project_path( "#{ name }.gemspec" )
end
end
This = ThisProject.new
|