Class: Reap::Project
- Inherits:
-
Object
- Object
- Reap::Project
- Includes:
- Utilities
- Defined in:
- lib/reap/project.rb,
lib/reap/defaults.rb,
lib/reap/metadata.rb,
lib/reap/settings.rb,
lib/reap/project/gem.rb,
lib/reap/project/log.rb,
lib/reap/project/scm.rb,
lib/reap/project/html.rb,
lib/reap/project/make.rb,
lib/reap/project/rdoc.rb,
lib/reap/project/site.rb,
lib/reap/project/spec.rb,
lib/reap/project/test.rb,
lib/reap/project/check.rb,
lib/reap/project/clean.rb,
lib/reap/project/stats.rb,
lib/reap/project/package.rb,
lib/reap/project/publish.rb,
lib/reap/project/release.rb,
lib/reap/project/version.rb,
lib/reap/project/announce.rb,
lib/reap/project/scaffold.rb
Overview
Project
The Project class is the main class of Reap. It provides the tools for working with a project. The CLI Application class delegates to this class, for instance.
Defined Under Namespace
Classes: Defaults, Metadata, Settings
Constant Summary collapse
- MAKE_COMMAND =
The Make tool routes to extension Makefile(s). Presently, it is designed to support only extconf.rb design.
TODO: win32 cross-compile ?
ENV['make'] || (RUBY_PLATFORM =~ /(win|w)32$/ ? 'nmake' : 'make')
- PACKAGE_STORE =
'pkg'
Instance Method Summary collapse
-
#announce(options = nil) ⇒ Object
Generate and email a release announcement.
-
#chdir_to_project(&block) ⇒ Object
Change directory to project’s root location, and execute block if given.
-
#check_load(options = nil) ⇒ Object
Load each script independently to ensure there are no require dependency issues.
-
#check_syntax(options = nil) ⇒ Object
Verify syntax of ruby scripts.
-
#clean(options = nil) ⇒ Object
Clean scrap products.
-
#clobber(options = nil) ⇒ Object
Run all clobber methods.
-
#clobber_packages(options = nil) ⇒ Object
Remove packages.
-
#clobber_rdoc(options = nil) ⇒ Object
Remove rdocs products.
-
#clobber_ridoc(options = nil) ⇒ Object
Remove ri products.
-
#compiles? ⇒ Boolean
Check to see if this project has extensions that need to be compiled.
-
#current_platform ⇒ Object
Current platform.
- #debug=(x) ⇒ Object
- #debug? ⇒ Boolean
-
#defaults ⇒ Object
Task defaults.
-
#display_location ⇒ Object
Display the project’s root location.
-
#document(options) ⇒ Object
Generate documentation.
- #dryrun=(x) ⇒ Object (also: #noharm=)
-
#dryrun? ⇒ Boolean
(also: #noharm?)
alias_method :init_options, :options # TODO: Improve me! (see stamp.rb).
-
#extensions ⇒ Object
Extension directories.
- #force=(x) ⇒ Object
- #force? ⇒ Boolean
-
#gem_clobber(options = nil) ⇒ Object
Remove gem package products.
-
#gem_install(options = nil) ⇒ Object
Install gem package, creating the package if not already created.
-
#gem_package(options = nil) ⇒ Object
Create a Gem package.
-
#gem_uninstall ⇒ Object
Uninstall gem package.
-
#html ⇒ Object
Create web index.html from README.
-
#initialize(options = nil) ⇒ Project
constructor
New Project.
-
#introspect(options) ⇒ Object
Query infromation about reap settings and/or the current project.
-
#invoke(command, *args) ⇒ Object
Invoke a tool.
-
#location ⇒ Object
Location of project.
-
#log(*args) ⇒ Object
Update all logs.
-
#log_changes(options = nil) ⇒ Object
Generate ChangeLog.
-
#log_notes(options = {}) ⇒ Object
Collect embedded notes.
-
#make ⇒ Object
Compile extensions.
-
#make_clean ⇒ Object
Remove enouhg compile products for a clean compile.
-
#make_config ⇒ Object
Create Makefile(s).
-
#make_distclean ⇒ Object
(also: #clobber_make)
Remove all compile products.
-
#make_static ⇒ Object
Compile static.
-
#manifest_file ⇒ Object
Project manifest file.
-
#metadata ⇒ Object
Project metadata.
-
#options ⇒ Object
Common options.
-
#package(options = nil) ⇒ Object
General pack command.
-
#package_gem(options = nil) ⇒ Object
Routes to #gem_package.
-
#package_store ⇒ Object
Returns the package storage directory (now constant ‘pkg’).
-
#package_tgz(options = nil) ⇒ Object
Create a Tar’d Gzip package.
-
#package_zip(options = nil) ⇒ Object
Create Zip package.
-
#prepare(options) ⇒ Object
Prepare for packaging (clean, distclean, version stamp).
-
#publish(options = nil) ⇒ Object
Publish website to rubyforge.
-
#rdoc(options = nil) ⇒ Object
Generate rdocs.
-
#release(options = {}) ⇒ Object
Release packages (to rubyforge).
-
#ridoc(options = nil) ⇒ Object
generate local ri docs.
-
#rollout(options = {}) ⇒ Object
A complete rollout.
-
#runmodes ⇒ Object
Run modes.
- #scaffold(options) ⇒ Object
-
#scaffold_rakefile(fname) ⇒ Object
Add tasks in Rakefile form to project.
- #scaffold_setup_rb(fname) ⇒ Object
-
#scaffold_skeleton(options = nil) ⇒ Object
Create a project skeleton.
-
#scaffold_task(fname) ⇒ Object
Add a user tasks to the project.
-
#scaffold_tasks(fname) ⇒ Object
Add all user tasks to the project.
-
#scm? ⇒ Boolean
Determine if project is under version control.
-
#scm_branch(options = nil) ⇒ Object
Branch current version of project.
-
#scm_log(options = {}) ⇒ Object
Generate ChangeLog.
-
#scm_tag(options = nil) ⇒ Object
Tag current versoin of project.
-
#settings ⇒ Object
Task user settings.
-
#site_install ⇒ Object
Install via project’s install/setup script.
-
#site_uninstall ⇒ Object
TODO: Create uninstall task.
-
#spec(options = nil) ⇒ Object
Run all specs with basic output.
-
#spec_doc(options = nil) ⇒ Object
Run all specs with text output.
-
#stamp(options = {}) ⇒ Object
Update VERSION stamp file.
-
#stats(options = nil) ⇒ Object
Simple code count analysis.
-
#test_cross(options = nil) ⇒ Object
Run cross comparison testing.
-
#test_load(options = nil) ⇒ Object
Load each test independently to ensure there are no require dependency issues.
-
#test_solo(options = nil) ⇒ Object
Run unit-tests.
-
#test_unit(options = {}) ⇒ Object
Run unit tests.
- #trace=(x) ⇒ Object
- #trace? ⇒ Boolean
- #verbose=(x) ⇒ Object
- #verbose? ⇒ Boolean
Methods included from Utilities
#ask, #bin?, #cd, #command_paths, #compress, #dir!, #dir?, directory!, directory?, #email, exist!, exist?, #exists!, #exists?, #file!, #file?, #fileutils, #glob, #list_option, #multiglob, #multiglob_r, #out_of_date?, #password, path!, path?, #read, #rm_r, #safe?, #sh, #stage, #stage_manifest, #status, #write, #ziputils
Constructor Details
#initialize(options = nil) ⇒ Project
New Project.
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/reap/project.rb', line 43 def initialize(=nil) @options = || {} @location = locate raise LoadError, "no .reap configuration file" unless @location @metadata = Metadata.read(location) @settings = Settings.read(location, @metadata) @defaults = Defaults.new(@metadata) @runmodes = RunModes.new() end |
Instance Method Details
#announce(options = nil) ⇒ Object
Generate and email a release announcement. The announcement text is read from ANNOUNCEtxt or another template file is specified, or if no template is given, the announcemnet is automatically built from project metadata, ant the CHANGES and NOTES files.
Templates support metadata substitutions using $name$ syntax. Also, it will subsititue the first line matching /please see notes/i for the notelog. And /please see change/i for the changelog.
The following settings apply:
template Announcement template file (ANNOUNCE.txt).
to Email address(es) to send announcemnt.
If mailto is set then these also apply:
from Message FROM address [email].
subject Subject of email message ([ANN] title verison).
server Email server to route message.
port Email server's port.
domain Email server's domain name.
account Email account name [email].
login Login type: plain, cram_md5 or login.
secure Uses TLS security, true or false?
The announcement will be printed to standard out before sending so it can be verified.
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 |
# File 'lib/reap/project/announce.rb', line 36 def announce(=nil) = (, 'announce') announcement = Announcement.new do |ann| ann.cutoff = ['cutoff'] ann.template = ['template'] ann. = end if dryrun? puts "\n#{announcement.}\n\n" if verbose? else puts "\n#{announcement.}\n\n" end ['message'] = announcement. ['version'] = .version ['title'] ||= .title ['subject'] ||= "%s, v%s release" ['subject'] = ['subject'] % [ ['title'], .version ] actions = [] select = ['hosts'] hosts(select).each do |host| if host.respond_to?(:announce) if host.announce_confirm?() actions << lambda{ host.announce() } end end end actions.each{ |a| a.call } end |
#chdir_to_project(&block) ⇒ Object
Change directory to project’s root location, and execute block if given. If a block is provided, the current directory will revert back to what it was prior to this call, otherwise it will remain changed.
132 133 134 135 136 137 138 |
# File 'lib/reap/project.rb', line 132 def chdir_to_project(&block) if block Dir.chdir(location, &block) else Dir.chdir(location) end end |
#check_load(options = nil) ⇒ Object
Load each script independently to ensure there are no require dependency issues.
WARNING! You should only run this on scripts that have no toplevel side-effects!!!
This takes one option :scripts
which is a glob or list of globs of the scripts to check. By default this is all scripts in the libpath(s).
FIXME: This isn’t routing output to dev/null as expected ?
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 |
# File 'lib/reap/project/check.rb', line 63 def check_load(=nil) = (, 'check-load', 'check') make if compiles? libpath = ['libpath'] || .libpath exclude = ['exclude'] libpath = list_option(libpath) exclude = list_option(exclude) files = multiglob_r(*libpath) - multiglob_r(exclude) files = files.select{ |f| File.extname(f) == '.rb' } max = files.collect{ |f| f.size }.max list = [] files.each do |s| next unless File.file?(s) #if not system "ruby -c -Ibin:lib:test #{s} &> /dev/null" then cmd = "ruby -I#{libpath.join(':')} #{s} > /dev/null 2>&1" puts cmd if debug? if r = system(cmd) puts "%-#{max}s [PASS]" % [s] else puts "%-#{max}s [FAIL]" % [s] list << s #:load end end puts " #{list.size} Load Failures" if verbose? unless list.empty? puts "\n-- Load Failures --\n" list.each do |f| print "* " system "ruby -I#{libpath} #{f} 2>&1" #puts end puts end end end |
#check_syntax(options = nil) ⇒ Object
Verify syntax of ruby scripts.
This takes one option :scripts
which is a glob or list of globs of the scripts to check. By default this is all scripts in the libpath(s).
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 |
# File 'lib/reap/project/check.rb', line 10 def check_syntax(=nil) = (, 'check-syntax', 'check') libpath = ['loadpath'] || .loadpath exclude = ['exclude'] #libpath = libpath.split(/[:;]/) unless Array===libpath libpath = list_option(libpath) exclude = list_option(exclude) files = multiglob_r(*libpath) - multiglob_r(exclude) files = files.select{ |f| File.extname(f) == '.rb' } max = files.collect{ |f| f.size }.max list = [] files.each do |s| next unless File.file?(s) #if not system "ruby -c -Ibin:lib:test #{s} &> /dev/null" then r = system "ruby -c -I#{libpath} #{s} > /dev/null 2>&1" if r puts("%-#{max}s [PASS]" % [s]) #if verbose? else puts("%-#{max}s [FAIL]" % [s]) #if verbose? list << s #:syntax end end puts " #{list.size} Syntax Errors" if verbose? unless list.empty? puts "\n-- Syntax Errors --\n" list.each do |f| print "* " system "ruby -c -I#{libpath} #{f} 2>&1" #puts end puts end end end |
#clean(options = nil) ⇒ Object
Clean scrap products. All directory paths and or file globs listed under the clean configuration entry, can be removed via this method. By default all files ending with “~” or .back are removed. To specifcy an alternate provide a list of files and/or glibs under remove:
sub-entry. You can also provide an exclude:
sub-entry to isolate files not to be removed. For example, on might do:
clean:
remove [ '**/*~', '**/*.bak', '.config' ]
Clean is run as a prerequiste to #release via #prepare.
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 |
# File 'lib/reap/project/clean.rb', line 18 def clean(=nil) = (, 'clean') remove = ['remove'] exclude = ['exclude'] remove = list_option(remove) exclude = list_option(exclude) files = multiglob_r(*remove) - multiglob_r(exclude) make_clean if compiles? return if files.empty? puts files.join("\n") if verbose? ans = ask("Remove files?", "yN").downcase return unless ans == 'y' or ans == 'yes' end files.each do |f| rm(f) if File.exist?(f) end end |
#clobber(options = nil) ⇒ Object
Run all clobber methods. This method literally looks for all other methods starting with the phrase “clobber_” and calls them, then runs #clean as well.
49 50 51 52 53 54 55 |
# File 'lib/reap/project/clean.rb', line 49 def clobber(=nil) clean clobber_methods = methods.select{ |m| m.to_s =~ /^clobber_/ } clobber_methods.each do |m| send(m) end end |
#clobber_packages(options = nil) ⇒ Object
Remove packages.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/reap/project/package.rb', line 25 def clobber_packages(=nil) = (, 'package') store = 'pkg' packages = glob(File.join(store, '*')) packages.each do |path| rm_r(path) puts "Removed #{path}" unless dryrun? end end |
#clobber_rdoc(options = nil) ⇒ Object
Remove rdocs products.
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/reap/project/rdoc.rb', line 79 def clobber_rdoc(=nil) = (, 'doc-rdoc', 'rdoc') output = ['output'] if File.directory?(output) rm_r(output) puts "Removed #{output}" unless dryrun? end end |
#clobber_ridoc(options = nil) ⇒ Object
Remove ri products.
159 160 161 162 163 164 165 166 167 168 |
# File 'lib/reap/project/rdoc.rb', line 159 def clobber_ridoc(=nil) = (, 'doc-ri', 'ri') output = ['output'] if File.directory?(output) rm_r(output) puts "Removed #{output}" unless dryrun? end end |
#compiles? ⇒ Boolean
Check to see if this project has extensions that need to be compiled.
17 18 19 |
# File 'lib/reap/project/make.rb', line 17 def compiles? !extensions.empty? end |
#current_platform ⇒ Object
Current platform.
19 20 21 |
# File 'lib/reap/project/package.rb', line 19 def current_platform Platform.local.to_s end |
#debug=(x) ⇒ Object
92 |
# File 'lib/reap/project.rb', line 92 def debug=(x) ; runmodes.debug = x ; end |
#debug? ⇒ Boolean
86 |
# File 'lib/reap/project.rb', line 86 def debug? ; runmodes.debug? ; end |
#defaults ⇒ Object
Task defaults.
66 |
# File 'lib/reap/project.rb', line 66 def defaults ; @defaults ; end |
#display_location ⇒ Object
Display the project’s root location.
122 123 124 |
# File 'lib/reap/project.rb', line 122 def display_location puts "[#{location}]" end |
#document(options) ⇒ Object
Generate documentation. At this time it simply means generating rdocs.
8 9 10 11 |
# File 'lib/reap/project/rdoc.rb', line 8 def document() rdoc() ridoc() end |
#dryrun=(x) ⇒ Object Also known as: noharm=
88 |
# File 'lib/reap/project.rb', line 88 def dryrun=(x) ; runmodes.dryrun = x ; end |
#dryrun? ⇒ Boolean Also known as: noharm?
alias_method :init_options, :options # TODO: Improve me! (see stamp.rb)
82 |
# File 'lib/reap/project.rb', line 82 def dryrun? ; runmodes.dryrun? ; end |
#extensions ⇒ Object
Extension directories. Often this will simply be ‘ext’. but sometimes more then one extension is needed and are kept in separate directories. This works by looking for ext/*/.c files, where ever they are is considered an extension directory.
26 27 28 |
# File 'lib/reap/project/make.rb', line 26 def extensions @extensions ||= Dir['ext/**/*.c'].collect{ |file| File.dirname(file) }.uniq end |
#force=(x) ⇒ Object
90 |
# File 'lib/reap/project.rb', line 90 def force=(x) ; runmodes.force = x ; end |
#force? ⇒ Boolean
84 |
# File 'lib/reap/project.rb', line 84 def force? ; runmodes.force? ; end |
#gem_clobber(options = nil) ⇒ Object
Remove gem package products.
9 10 11 12 13 14 15 16 17 |
# File 'lib/reap/project/gem.rb', line 9 def gem_clobber(=nil) store = "pkg" packages = glob(File.join(store, '*.gem')) packages.each do |path| File.directory?(path) ? rm_r(path) : rm(path) end end |
#gem_install(options = nil) ⇒ Object
Install gem package, creating the package if not already created.
TODO: Endure that we even need a gem package using #out_of_date?
31 32 33 34 |
# File 'lib/reap/project/gem.rb', line 31 def gem_install(=nil) file = gem_package() sh "gem install #{file}" end |
#gem_package(options = nil) ⇒ Object
Create a Gem package.
TODO: Should this use staging too, like zip/tgz?
23 24 25 |
# File 'lib/reap/project/gem.rb', line 23 def gem_package(=nil) return package_gem(=nil) end |
#gem_uninstall ⇒ Object
Uninstall gem package.
TODO: Sepcify version?
40 41 42 43 44 |
# File 'lib/reap/project/gem.rb', line 40 def gem_uninstall i = .package_name.rindex('-') name, version = .package_name[0...i], .package_name[i+1..-1] sh "gem uninstall #{name} -v #{version}" end |
#html ⇒ Object
Create web index.html from README. (Not yet used)
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 |
# File 'lib/reap/project/html.rb', line 7 def html status_title "Creating HTML documents" require 'rdoc/markup/simple_markup' require 'rdoc/markup/simple_markup/to_html' = (, 'html') output = ['output'] files = ['files'] style = ['css'] output ||= 'doc' files ||= '[A-Z]*' style ||= Dir.glob('*.css').first files = Dir.glob(files) s = SM::SimpleMarkup.new h = SM::ToHtml.new files.each do |file| unless File.exist?(file) puts "Warning: file does not exist -- #{file}" end end mkdir_p(output) unless dryrun? files.each do |file| name = file.downcase.chomp('.txt') if /^readme/ =~ name name = "index" end path = File.join(output, name + '.html') next unless out_of_date?(path, file) title = "#{package.title} #{name.upcase}" input = File.read(file) output = s.convert(input, h) # FIX text = '' text << %{<html>} text << %{<head>} text << %{ <title>#{title}<title>} text << %{ <link rel="stylesheet" TYPE="text/css" HREF="#{style}">} if style text << %{</head>} text << %{<body>} text << output text << %{</body>} text << %{</html>} write(path, text) puts "Created #{path}" end end |
#introspect(options) ⇒ Object
Query infromation about reap settings and/or the current project.
NOTE: This would dhave been naed #inspect but for the built-in method.
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 |
# File 'lib/reap/project.rb', line 151 def introspect() args = ['arguments'] if args args.each do |field| case field when 'defaults' y defaults when 'settings' y settings when 'metadata' y else puts .send(field) end end else puts puts "#{.title} #{.version}" puts .brief puts .homepage puts puts .description puts puts .copyright puts end end |
#invoke(command, *args) ⇒ Object
Invoke a tool.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/reap/project.rb', line 99 def invoke(command, *args) begin #display_location meth = method(command) chdir_to_project do case meth.arity when 0 meth.call else meth.call(*args) end end rescue LoadError => e if trace? raise e else abort e..capitalize + '.' end end end |
#location ⇒ Object
Location of project.
58 |
# File 'lib/reap/project.rb', line 58 def location ; @location ; end |
#log(*args) ⇒ Object
Update all logs.
9 10 11 12 |
# File 'lib/reap/project/log.rb', line 9 def log(*args) log_changes(*args) log_notes(*args) end |
#log_changes(options = nil) ⇒ Object
Generate ChangeLog. This routes to the source control manager library.
17 18 19 20 |
# File 'lib/reap/project/log.rb', line 17 def log_changes(=nil) = (, 'log-changes', 'log') scm_log() end |
#log_notes(options = {}) ⇒ Object
Collect embedded notes.
This task scans source code for developer notes and writes to well organized files. This tool can lookup and list TODO, FIXME and other types of labeled comments from source code.
files Glob(s) of files to search.
labels Labels to search for. Defaults to [ 'TODO', 'FIXME' ].
output Output directory. Defaults to log/.
TODO: Remove format field, and ultimately use XML as primary format?
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 |
# File 'lib/reap/project/log.rb', line 36 def log_notes(={}) = (, 'log-notes', 'log') loadpath = ['loadpath'] || .loadpath labels = ['labels'] || ['TODO', 'FIXME', 'OPTIMIZE'] output = ['output'] || 'log' loadpath = list_option(loadpath) labels = labels.split(',') if String === labels labels = [labels].flatten.compact output.chomp!('/') records, counts = log_notes_extract(labels, loadpath) notes = log_notes_format(labels, records, (format=nil)) if records.empty? puts "No #{labels.join(', ')} notes." else files_saved = log_notes_save(output, notes, labels) files_saved.each do |file| puts "Updated #{file}" end puts counts.collect{|l,n| "#{n} #{l}s"}.join(', ') end end |
#make ⇒ Object
Compile extensions.
32 33 34 35 |
# File 'lib/reap/project/make.rb', line 32 def make make_config make_target end |
#make_clean ⇒ Object
Remove enouhg compile products for a clean compile.
46 47 48 |
# File 'lib/reap/project/make.rb', line 46 def make_clean make_target 'clean' end |
#make_config ⇒ Object
Create Makefile(s).
64 65 66 67 68 69 70 71 |
# File 'lib/reap/project/make.rb', line 64 def make_config extensions.each do |directory| next if File.exist?(File.join(directory, 'Makefile')) cd(directory) do sh "ruby extconf.rb" end end end |
#make_distclean ⇒ Object Also known as: clobber_make
Remove all compile products.
52 53 54 55 56 57 58 |
# File 'lib/reap/project/make.rb', line 52 def make_distclean make_target 'distclean' extensions.each do |directory| makefile = File.join(directory, 'Makefile') rm(makefile) if File.exist?(makefile) end end |
#make_static ⇒ Object
Compile static.
39 40 41 42 |
# File 'lib/reap/project/make.rb', line 39 def make_static make_config make_target 'static' end |
#manifest_file ⇒ Object
Project manifest file.
181 182 183 |
# File 'lib/reap/project.rb', line 181 def manifest_file Dir.glob('Manifest{,.txt}', File::FNM_CASEFOLD).first end |
#metadata ⇒ Object
Project metadata.
62 |
# File 'lib/reap/project.rb', line 62 def ; @metadata ; end |
#options ⇒ Object
Common options.
78 |
# File 'lib/reap/project.rb', line 78 def ; @options ; end |
#package(options = nil) ⇒ Object
General pack command.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/reap/project/package.rb', line 54 def package(=nil) packopts = (, 'package') formats = packopts['formats'] || ['gem', 'tgz'] formats = [formats].flatten prepare() puts unless dryrun? formats.each do |format| send("package_#{format}", ) #puts unless dryrun? end end |
#package_gem(options = nil) ⇒ Object
Routes to #gem_package.
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 |
# File 'lib/reap/project/package.rb', line 72 def package_gem(=nil) begin require 'rubygems/specification' Gem::manage_gems rescue LoadError #raise LoadError, "RubyGems is not installed?" end = (, 'package-gem', 'package') extension = '.gem' platform = .delete('platform') || 'none' platforms = [] platforms << nil if platform != 'only' platforms << 'current' if platform != 'none' platforms.each do |pl| ['platform'] = pl fname, = package_prepare_stage(extension, ) next unless fname # if already built stage = File.join(package_store, fname) if dryrun? status "gem build #{stage}" else file = nil cd(stage) do #status "vi #{metadata.name}.gemspec" builder = ::Gem::Builder.new(gemspec()) status "gem build #{stage}" unless dryrun? file = builder.build file = File.(file) end end # transfer gem package to package store mkdir_p(package_store) destination = File.join(package_store, File.basename(file)) mv(file, package_store) unless File.(file) == File.(destination) puts end end end |
#package_store ⇒ Object
Returns the package storage directory (now constant ‘pkg’).
13 14 15 |
# File 'lib/reap/project/package.rb', line 13 def package_store PACKAGE_STORE end |
#package_tgz(options = nil) ⇒ Object
Create a Tar’d Gzip package.
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 |
# File 'lib/reap/project/package.rb', line 126 def package_tgz(=nil) = (, 'package-tgz', 'package') platform = .delete('platform') || 'none' extension = '.tgz' platforms = [] platforms << nil if platform != 'only' platforms << current_platform if platform != 'none' platforms.each do |pl| ['platform'] = pl fname, = package_prepare_stage(extension, ) next unless fname # if already built if dryrun? status "tar -cxf #{fname}.tgz" else file = nil cd(package_store) do file = compress(:tgz, fname) end transfer(file, package_store) report_package_built(file) end end end |
#package_zip(options = nil) ⇒ Object
Create Zip package.
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 |
# File 'lib/reap/project/package.rb', line 155 def package_zip(=nil) = (, 'package-zip', 'package') platform = .delete('platform') || 'none' extension = '.zip' platforms = [] platforms << nil if platform != 'only' platforms << current_platform if platform != 'none' platforms.each do |pl| ['platform'] = pl fname, = package_prepare_stage(extension, ) next unless fname # if already built if dryrun? status "zip -r #{fname}.zip ." else file = nil cd(package_store) do file = compress(:zip, fname) end transfer(file, package_store) report_package_built(file) end end end |
#prepare(options) ⇒ Object
Prepare for packaging (clean, distclean, version stamp).
TODO: When we add support for binary packages distclean
should not be done for them.
43 44 45 46 47 48 49 50 |
# File 'lib/reap/project/package.rb', line 43 def prepare() @prepared ||= ( clean make_distclean if compiles? stamp() true ) end |
#publish(options = nil) ⇒ Object
Publish website to rubyforge.
This task publishes the source dir (deafult ‘doc’) to a rubyforge website.
Uses RSync to upload files to webserver.
TODO: Add FTP/SFTP support.
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 |
# File 'lib/reap/project/publish.rb', line 14 def publish(=nil) = (, 'publish', 'rubyforge') project = ['project'] || .project webdir = ['webdir'] source = ['source'] username = ['username'] || ENV['RUBYFORGE_USERNAME'] clear = ['clear'] protect = ['protect'] exclude = ['exclude'] source ||= "doc" username ||= ENV['RUBYFORGE_USERNAME'] if clear protect = protect().to_a exclude = exclude().to_a else protect = %w{usage statcvs statsvn robot.txt wiki} + [protect].flatten exclude = %w{.svn} + [exclude].flatten end abort "No project name." unless project abort "No username." unless username if webdir and webdir != '.' destination = File.join(project, webdir) else destination = project end dir = source.chomp('/') + '/' url = "#{username}@rubyforge.org:/var/www/gforge-projects/#{destination}" op = ['-rLvz', '--delete-after'] # maybe -p ? # Using commandline filter options didn't seem # to work, so I opted for creating an .rsync_filter file for # all cases. unless protect.empty? && exclude.empty? rsync_file = File.join(source,'.rsync-filter') unless file?(rsync_file) File.open(rsync_file, 'w') do |f| exclude.each{|e| f << "- #{e}\n"} protect.each{|e| f << "P #{e}\n"} end end op << "--filter='dir-merge #{rsync_file}'" end args = op + [dir, url] sh "rsync #{args.to_params}" end |
#rdoc(options = nil) ⇒ Object
Generate rdocs.
Generate Rdoc documentation. Settings are the same as the rdoc command’s option, with two exceptions: inline
for inline-source
and output
for op
.
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 |
# File 'lib/reap/project/rdoc.rb', line 20 def rdoc(=nil) = (, 'doc-rdoc', 'rdoc', 'doc') #options = DEFAULT['rdoc'].merge(options) ['title'] ||= .title targets = .delete('targets') || {'' => } output = ['output'] adfile = ['adfile'] adfile = [adfile].flatten.find do |f| File.exist?(f) end targets.each do |subdir, target| target = .merge(target) target_solo = target['solo'] target_main = Dir.glob(target['main'].to_s, File::FNM_CASEFOLD).first #target_main = File.expand_path(target_main) if target_main #target_output = File.expand_path(File.join(output, subdir)) target_output = File.join(output, subdir) cmdopts = {} #cmdopts['op'] = target_output cmdopts['main'] = target_main if target_main cmdopts['template'] = target['template'] || ENV['RDOC_TEMPLATE'] || 'html' #cmdopts['merge'] = target['merge'] cmdopts['inline-source'] = target['inline'] cmdopts['exclude'] = list_option(target['exclude']) files = list_option(target['include']) files = files.collect{ |g| Dir[g] }.flatten # Need this to remove unwanted toplevel files. files = files - ['Rakefile', 'Rakefile.rb'] # b/c rdoc's exlcude options doesn't work well. files = files - [manifest_file].compact #folder = target['chdir'] || '.' #puts "cd #{folder}" if dryrun? # TODO: Shouldn't chdir do this automatically? #chdir(folder) do if target_solo input_files = files.collect{ |i| multiglob_r(i) }.flatten.reject{ |f| File.directory?(f) } input_files.each do |input_file| out = File.join(target_output, File.basename(input_file).chomp(File.extname(input_file))) rdoc_target(out, input_file, cmdopts) rdoc_insert_ads(out, adfile) end else input_files = files.collect{ |i| dir?(i) ? File.join(i,'**','*') : i } rdoc_target(target_output, input_files, cmdopts) rdoc_insert_ads(target_output, adfile) end #end end end |
#release(options = {}) ⇒ Object
Release packages (to rubyforge). This generates the packages, and then distributes them to the file server.
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 |
# File 'lib/reap/project/release.rb', line 11 def release(={}) package() = (, 'release') store = 'pkg' version = .version ['version'] = version ['store'] = store changelog = ['changelog'] #|| DEFAULT['release']['changelog'] || DEFAULT['rubyforge']['changelog'] notelog = ['notelog'] #|| DEFAULT['release']['notelog'] || DEFAULT['rubyforge']['notelog'] changelog = Dir.glob(changelog.to_s, File::FNM_CASEFOLD).first notelog = Dir.glob(notelog.to_s, File::FNM_CASEFOLD).first ['changelog'] = changelog if changelog && File.exist?(changelog) ['notelog'] = notelog if notelog && File.exist?(notelog) files = ['files'] || [] if files.empty? files = Dir[File.join(store, '*')].select do |file| /#{version}[.]/ =~ file end ['files'] = files #files = Dir.glob(File.join(store,"#{name}-#{version}*")) end actions = [] select = ['hosts'] hosts(select).each do |host| if host.respond_to?(:release) # Not going to do dryrun in Rubyforge class b/c it still requires logging in. if dryrun? puts "release: #{} #{host.basename.downcase}" else if host.release_confirm?() actions << lambda{ host.release() } end end end end actions.each{ |a| a.call } end |
#ridoc(options = nil) ⇒ Object
generate local ri docs
Generate RI documentation. This utilizes rdoc to produce the appropriate files.
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 |
# File 'lib/reap/project/rdoc.rb', line 131 def ridoc(=nil) = (, 'doc-ri', 'ri') #options = DEFAULT['ri'].merge(options) cmdopts = {} cmdopts['op'] = ['output'] cmdopts['exclude'] = ['exclude'] output = ['output'] files = ['include'] || .loadpath #['lib', '[A-Z]*'] input = files #.collect do |i| # dir?(i) ? File.join(i,'**','*') : i #end if out_of_date?(output, *input) or force? rm_r(output) if exist?(output) and safe?(output) # remove old ridocs #input = input.collect{ |i| glob(i) }.flatten vector = [input, cmdopts] sh "rdoc --ri -M -a #{vector.to_console}" else puts "RI Docs are current." end end |
#rollout(options = {}) ⇒ Object
A complete rollout. This will prepare (clean, stamp and package), then document, publish and release, tag and announce. It will do under direction. You can use the –force option to bypass this and have evey action taken automatically.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/reap/project/release.rb', line 67 def rollout(={}) if force? doc, pub, ann, tag = true, true, true, true else doc = ask("Generate doumentation?", "yN").downcase =~ /^(y|yes)$/i pub = ask("Publish website? ", "yN") =~ /^(y|yes)$/i tag = scm? ? (ask("Tag current version? ", "yN") =~ /^(y|yes)$/i) : false ann = ask("Announce release? ", "yN") =~ /^(y|yes)$/i puts end document() if doc publish() if pub #package(options) release() scm_tag() if tag announce() if ann end |
#runmodes ⇒ Object
Run modes.
74 |
# File 'lib/reap/project.rb', line 74 def runmodes ; @runmodes ; end |
#scaffold(options) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/reap/project/scaffold.rb', line 7 def scaffold() requests = ['arguments'] if requests requests.each do |f| case f #when /^(meta\/)?project(info)?(.yaml|.yml)?$/i # scaffold_projectfile(f) when /^rake(file)?$/i scaffold_rakefile(f) when /^setup[.]rb$/ scaffold_setup_rb(f) when /^(task|script)s?\//i scaffold_task(f) when /^(task|script)(s)?$/ scaffold_tasks(f) else raise "Unknown scaffolding." end end else scaffold_skeleton(=nil) end end |
#scaffold_rakefile(fname) ⇒ Object
Add tasks in Rakefile form to project.
44 45 46 47 |
# File 'lib/reap/project/scaffold.rb', line 44 def scaffold_rakefile(fname) from = File.join(data_dir, 'buildset', 'rake', 'Rakefile') cp(from, fname) unless File.exist?(fname) end |
#scaffold_setup_rb(fname) ⇒ Object
51 52 53 54 |
# File 'lib/reap/project/scaffold.rb', line 51 def scaffold_setup_rb(fname) from = File.join(data_dir, 'buidset', 'rake', 'setup.rb') cp(from, fname) unless File.exist?(fname) end |
#scaffold_skeleton(options = nil) ⇒ Object
Create a project skeleton.
TODO: Improve scaffolding. Make more intelligent.
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 |
# File 'lib/reap/project/scaffold.rb', line 74 def scaffold_skeleton(=nil) = ( || {}).rekey(:to_s) files = glob('**/*') - glob('meta/**/*') - ['.reap', 'meta'] unless files.empty? ans = ask("Directory isn't empty. Are you sure you want to add scaffolding?", 'yN') case ans.downcase when 'y', 'yes' else abort "Scaffolding aborted." end end # if options['svn'] # if glob('**/*').empty? # mkdir_p('trunk') # mkdir_p('branches') # mkdir_p('tags') # chdir('trunk') # else # abort "Can't create a svn repo unless directory is empty." # end # end paths = nil dir = File.join(data_dir, 'base') chdir(dir){ paths = Dir['**/*'] } dirs = paths.select{ |f| File.directory?(File.join(dir, f)) } files = (paths - dirs).reject{ |f| /[.]svn/ =~ f } dirs.each do |dname| if File.exist?(dname) and !File.directory?(dname) abort "Directory to be created clashes with a prexistent file -- #{dname}" end end dirs.each do |dname| mkdir_p(dname) unless File.exist?(dname) end files.each do |fname| next if File.exist?(fname) file = File.join(dir, fname) if File.extname(file) == '.erb' erb = ERB.new(File.read(file)) txt = erb.result(.get_binding) File.open(fname.chomp('.erb'), 'w'){ |f| f << txt } else cp(file, fname) end end # A little extra love. dir = File.join('lib',.name) mkdir_p(dir) unless File.exist?(dir) end |
#scaffold_task(fname) ⇒ Object
Add a user tasks to the project.
58 59 60 61 |
# File 'lib/reap/project/scaffold.rb', line 58 def scaffold_task(fname) from = File.join(data_dir, 'buildset', 'tasks', 'task', File.basename(fname)) cp(from, fname) unless File.exist?(fname) end |
#scaffold_tasks(fname) ⇒ Object
Add all user tasks to the project.
65 66 67 68 |
# File 'lib/reap/project/scaffold.rb', line 65 def scaffold_tasks(fname) dir = File.join(data_dir, 'buildset', 'tasks', 'task') cp_r(dir, fname) end |
#scm? ⇒ Boolean
Determine if project is under version control.
TODO: scm? may need to be made more robsut.
11 12 13 |
# File 'lib/reap/project/scm.rb', line 11 def scm? Systems::System.detect end |
#scm_branch(options = nil) ⇒ Object
Branch current version of project. This method routes to the appropriate method for the project’s source control manager.
message Optional commit message. This is intended
for commandline usage. (Use -m for shorthand).
TODO: How should metadata.repository come into play here?
73 74 75 76 |
# File 'lib/reap/project/scm.rb', line 73 def scm_branch(=nil) = (, 'scm-branch', 'scm') scm.branch() end |
#scm_log(options = {}) ⇒ Object
Generate ChangeLog. This method routes to the appropriate method for the project’s source control manager.
change File path to store rdoc formated changelog. Default is 'log/changelog.txt'.
xmlchange File path to store XML formated changelog. Default is 'doc/log/changelog.xml'.
Set either to false to supress creation.
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 |
# File 'lib/reap/project/scm.rb', line 24 def scm_log(={}) #create_txtlog = (options['txtlog'] != false) #create_xmllog = (options['xmllog'] != false) xmlout = ['xmloutput'] || 'site/log' # TODO: How to set site/? #if create_txtlog txtlog = apply_naming_policy('changelog', 'rdoc') txtlog = File.join('log', txtlog) #end #if create_xmllog xmllog = apply_naming_policy('changelog', 'xml') xmllog = File.join(xmlout, xmllog) #end #txtlog = File.join('lib', txtlog) unless txtlog.include?('/') #xmllog = File.join(xmldir, xmllog) unless xmllog.include?('/') txtlog ||= ['txtlog'] xmllog ||= ['xmllog'] scm.log(txtlog) scm.log_xml(xmllog) if xmllog end |
#scm_tag(options = nil) ⇒ Object
Tag current versoin of project. This method routes to the appropriate method for the project’s source control manager.
message Optional commit message. This is intended for commandline
usage. (Use -m for shorthand).
TODO: How should metadata.repository come into play here?
59 60 61 62 |
# File 'lib/reap/project/scm.rb', line 59 def scm_tag(=nil) = (, 'scm-tag', 'scm') scm.tag() end |
#settings ⇒ Object
Task user settings.
70 |
# File 'lib/reap/project.rb', line 70 def settings ; @settings ; end |
#site_install ⇒ Object
Install via project’s install/setup script.
TODO: Remove special reap options from command line.
9 10 11 12 13 14 15 16 |
# File 'lib/reap/project/site.rb', line 9 def site_install script = glob("setup.rb,install.rb,task/setup,task/install").first if script sh "#{script} #{ARGV.join(' ')}" else abort "Project needs an install/setup script." end end |
#site_uninstall ⇒ Object
TODO: Create uninstall task.
20 21 22 |
# File 'lib/reap/project/site.rb', line 20 def site_uninstall abort "Not yet implemented." end |
#spec(options = nil) ⇒ Object
Run all specs with basic output.
Options:
specs File glob(s) of spec files. Defaults to ['spec/**/*_spec.rb', 'spec/**/spec_*.rb'].
loadpath Paths to add $LOAD_PATH. Defaults to ['lib'].
live Ignore loadpath, use installed libraries instead. Default is false.
require Lib(s) to require before excuting specifications.
warning Whether to show warnings or not. Default is false.
command Spec command to use. Defaults to 'spec'.
format Format of RSpec output.
rubyopt Additional options to pass to the ruby command.
specopt Additional commandline options for spec command.
– RCOV suppot?
ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts]
++
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 |
# File 'lib/reap/project/spec.rb', line 29 def spec(=nil) = (, 'spec') #specs = options['specs'] || DEFAULT['spec']['specs'] #reqs = options['require'] || DEFAULT['spec']['require'] #warning = options['warning'] || DEFAULT['spec']['false'] #command = options['command'] || DEFAULT['spec']['command'] specs = ['specs'] warning = ['warning'] command = ['command'] || 'spec' loadpath = ['loadpath'] || .loadpath format = ['format'] rubyopt = ['rubyopt'] specopt = ['specopt'] live = ['live'] specs = list_option(specs) loadpath = list_option(loadpath) requires = list_option(requires) files = multiglob(*specs) if files.empty? puts "No specifications." else #RakeFileUtils.verbose(verbose) do # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts] cmd = "ruby" cmd << " -w" if warning cmd << %[ -I"#{loadpath.join(':')}"] unless loadpath.empty? cmd << %[ -r"#{requires.join(':')}"] unless requires.empty? cmd << rubyopt #.join(" ") cmd << " " #rb_opts << "-S rcov" if rcov #cmd << rcov_option_list #cmd << %[ -o "#{rcov_dir}" ] if rcov cmd << command cmd << " " #cmd << "-- " if rcov cmd << files.join(' ') cmd << " " cmd << specopt #.join(' ') cmd << " --format #{format}" if format puts cmd if verbose? unless system(cmd) STDERR.puts if raise("Command #{cmd} failed") if fail_on_error end #end end end |
#spec_doc(options = nil) ⇒ Object
Run all specs with text output
85 86 87 88 89 |
# File 'lib/reap/project/spec.rb', line 85 def spec_doc(=nil) ||= {} ['format'] = 'specdoc' spec() end |
#stamp(options = {}) ⇒ Object
Update VERSION stamp file.
This file is either called VERSION, or meta/version (case-insensitive and with optional .txt extension).
The format of the files is:
x.y.z status (date)
For exmaple:
1.2.4 alpha (2008-10-10)
On the command line:
--major will bump the major number
--minor will bump the minor number
--tiny will bump the tiny number
--teeny will bump the teeny number
One can alternately specify the entire version:
--version=x.y.z
As well as status:
--status=(alpha, beta, rc1, rc2, ...)
TODO: Should we also update a lib/version.rb file? TODO: Considerding createing a standard status marker (a=alpha, b=beta, r=release candidate)
So a version would read, eg. 1.2.4a, or with status number, eg. 1.2.4r1).
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 |
# File 'lib/reap/project/version.rb', line 37 def stamp(={}) version = ['version'] status = ['status'] bumps = [ ['major'], ['minor'], ['tiny'], ['teeny'] ] bump = bumps.any?{|x|x} abort "Specify bumps or version, not both." if bump and version #options = configure_options(options, 'stamp') version = version || .version || '0.0.0' status = status || .status || '0.0.0' if bump points = version.to_s.split(/[.]/).collect do |x| x.to_i end if ['major'] points[0] += 1 points[1..-1] = *([0] * points[1..-1].size) elsif ['minor'] points[1] += 1 points[2..-1] = *([0] * points[2..-1].size) elsif ['tiny'] points[2] += 1 points[3..-1] = *([0] * points[3..-1].size) elsif ['teeny'] points[3] += 1 end version = points.join('.') #.chomp('.0') else abort "Invalid version -- #{version}" unless String===version && /^[0-9]/ =~ version end = File.directory?('meta') file = glob('{,meta/}version{,.txt}', File::FNM_CASEFOLD).first file = ( ? 'meta/version' : 'VERSION') unless file text = "#{version} #{status} (#{Time.now.strftime('%Y-%m-%d')})" if File.exist?(file) old_text = File.read(file).strip old_version, old_status, old_date = *old_text.split(/\s/) if old_version == "#{version}" && old_status == status puts old_text return end end if dryrun? puts "echo '#{text}' > #{file}" else write(file, text) puts text puts "#{file} updated." .version = version .status = status .released = Time.now end # TODO: Stamp .roll if roll file exists. # should we read current .roll file and use as defaults? if File.exist?('.roll') str = [] str << "name = #{.name}" str << "version = #{.version}" str << "status = #{.status}" str << "date = #{.date}" str << "default = #{.default}" str << "libpath = #{.libpath}" # File.open('.roll','w'){ |f| f << str.join("\n") } end end |
#stats(options = nil) ⇒ Object
Simple code count analysis.
Scan source code counting files, lines of code and comments and presents a report of it’s findings.
loadpath Path to include in analysis. The default
is the project's loadpath.
exclude File globs to exclude from analysis. Default
is 'ext' b/c this does not yet support C analysis.
TODO: Add C support for ext/.
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 |
# File 'lib/reap/project/stats.rb', line 22 def stats(=nil) = (, 'stats') loadpath = ['loadpath'] || .loadpath exclude = ['exclude'] || ['ext'] loadpath = list_option(loadpath) exclude = list_option(exclude) files = multiglob_r(*loadpath) - multiglob_r(*exclude) #() #.inject([]){ |memo, find| memo.concat(glob(find)); memo } #Dir.multiglob_with_default(DEFAULT_STATS_FILES) fc, l, c, r, t, s = *line_count(*files) fct, lt, ct, rt, tt, st = *([0]*6) if File.directory?('test') fct, lt, ct, rt, tt, st = *line_count('test/**/*') t = lt if lt > 0 end rat = lambda do |d,n| if d > n and n != 0 "%.1f" % [ d.to_f / n ] elsif n > d and d != 0 "-" #"%.1f:1" % [ n.to_f / d ] elsif d == 0 or n == 0 "-" else "1.0" end end per = lambda do |n,d| if d != 0 (((n.to_f / d)*100).to_i).to_s + "%" else "-" end end max = l.to_s.size + 4 puts #puts "FILES:" #puts " source: #{fc}" #puts " test : #{fct}" #puts " total : #{fc+fct}" #puts #puts "LINES:" #puts " code : %#{max}s %4s" % [ c.to_s, per[c,l] ] #puts " docs : %#{max}s %4s" % [ r.to_s, per[r,l] ] #puts " space : %#{max}s %4s" % [ s.to_s, per[s,l] ] #puts " test : %#{max}s %4s" % [ t.to_s, per[t,l] ] #puts " total : %#{max}s %4s" % [ l.to_s, per[l,l] ] #puts #puts "Ratio to 1 :" #puts " code to test : #{rat[c,t]} #{per[c,t]}" head = ["Total", "Code", "-%-", "Docs", "-%-", "Blank", "-%-", "Files"] prod = [l.to_s, c.to_s, per[c,l], r.to_s, per[r,l], s.to_s, per[s,l], fc] test = [lt.to_s, ct.to_s, per[ct,l], rt.to_s, per[rt,l], st.to_s, per[st,l], fct] totl = [(l+lt), (c+ct), per[c+ct,l+lt], (r+rt), per[r+rt,l+lt], (s+st), per[s+st,l+lt], (fc+fct)] puts "TYPE %#{max}s %#{max}s %4s %#{max}s %4s %#{max}s %4s %#{max}s" % head puts "Source %#{max}s %#{max}s %4s %#{max}s %4s %#{max}s %4s %#{max}s" % prod puts "Test %#{max}s %#{max}s %4s %#{max}s %4s %#{max}s %4s %#{max}s" % test puts "Total %#{max}s %#{max}s %4s %#{max}s %4s %#{max}s %4s %#{max}s" % totl puts puts "RATIO Code Docs Blank Test Total" puts "Code %7s %7s %7s %7s %7s" % [ rat[c,c], rat[c,r], rat[c,s], rat[c,t], rat[c,l] ] puts "Docs %7s %7s %7s %7s %7s" % [ rat[r,c], rat[r,r], rat[r,s], rat[r,t], rat[r,l] ] puts "Blank %7s %7s %7s %7s %7s" % [ rat[s,c], rat[s,r], rat[s,s], rat[s,t], rat[s,l] ] puts "Test %7s %7s %7s %7s %7s" % [ rat[t,c], rat[t,r], rat[t,s], rat[t,t], rat[t,l] ] puts "Total %7s %7s %7s %7s %7s" % [ rat[l,c], rat[l,r], rat[l,s], rat[l,t], rat[l,l] ] puts end |
#test_cross(options = nil) ⇒ Object
Run cross comparison testing.
This tool runs unit tests in pairs to make sure there is cross library compatibility. Each pari is run in a separate interpretor to prevent script clash. This makes for a more robust test facility and prevents potential conflicts between test scripts.
tests Test files (eg. test/tc_**/*.rb) [test/**/*]
loadpath Directories to include in load path.
require List of files to require prior to running tests.
live Deactive use of local libs and test against install.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/reap/project/test.rb', line 197 def test_cross(=nil) = test_configuration() tests = ['tests'] loadpath = ['loadpath'] requires = ['requires'] live = ['live'] exclude = ['exclude'] log = ['log'] != false files = multiglob_r(*tests) - multiglob_r(exclude) return puts("No tests.") if files.empty? files = files.select{ |f| File.extname(f) == '.rb' and File.file?(f) } width = files.collect{ |f| f.size }.max pairs = files.inject([]){ |m, f| files.collect{ |g| m << [f,g] }; m } make if compiles? cmd = %[ruby -I#{loadpath.join(':')} -e"load('./%s'); load('%s')"] dis = "%-#{width}s %-#{width}s" testruns = pairs.collect do |pair| { 'file' => pair, 'command' => cmd % pair, 'display' => dis % pair } end report = test_loop_runner(testruns) puts report if log && !dryrun? logfile = File.join('log', apply_naming_policy('testlog', 'txt')) File.open(logfile, 'a') do |f| f << "= Cross Test @ #{Time.now}\n" f << report f << "\n" end end end |
#test_load(options = nil) ⇒ Object
Load each test independently to ensure there are no require dependency issues. This is actually a bit redundant as test-solo will also cover these results. So we may deprecate this in the future. This does not generate a test log entry.
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 |
# File 'lib/reap/project/test.rb', line 92 def test_load(=nil) = test_configuration() tests = ['tests'] loadpath = ['loadpath'] requires = ['requires'] live = ['live'] exclude = ['exclude'] files = multiglob_r(*tests) - multiglob_r(*exclude) return puts("No tests.") if files.empty? max = files.collect{ |f| f.size }.max list = [] files.each do |f| next unless File.file?(f) if r = system("ruby -I#{loadpath.join(':')} #{f} > /dev/null 2>&1") puts "%-#{max}s [PASS]" % [f] #if verbose? else puts "%-#{max}s [FAIL]" % [f] #if verbose? list << f end end puts " #{list.size} Load Failures" if verbose? unless list.empty? puts "\n-- Load Failures --\n" list.each do |f| print "* " system "ruby -I#{loadpath} #{f} 2>&1" #puts end puts end end end |
#test_solo(options = nil) ⇒ Object
Run unit-tests. Each test is run in a separate interpretor to prevent script clash. This makes for a more robust test facility and prevents potential conflicts between test scripts.
tests Test files (eg. test/tc_**/*.rb) [test/**/*]
loadpath Directories to include in load path [lib].
require List of files to require prior to running tests.
live Deactive use of local libs and test against install.
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 |
# File 'lib/reap/project/test.rb', line 142 def test_solo(=nil) = test_configuration() tests = ['tests'] loadpath = ['loadpath'] requires = ['requires'] live = ['live'] exclude = ['exclude'] log = ['log'] != false files = multiglob_r(*tests) - multiglob_r(*exclude) return puts("No tests.") if files.empty? files = files.select{ |f| File.extname(f) == '.rb' and File.file?(f) } width = files.collect{ |f| f.size }.max make if compiles? cmd = %[ruby -I#{loadpath.join(':')} %s] dis = "%-#{width}s" testruns = files.collect do |file| { 'files' => file, 'command' => cmd % file, 'display' => dis % file } end report = test_loop_runner(testruns) puts report if log && !dryrun? logfile = File.join('log', apply_naming_policy('testlog', 'txt')) File.open(logfile, 'a') do |f| f << "= Solo Test @ #{Time.now}\n" f << report f << "\n" end end end |
#test_unit(options = {}) ⇒ Object
Run unit tests. Unlike test-solo and test-cross this loads all tests and runs them together in a single process.
Note that this shells out to the testrb program.
TODO: Generate a test log entry?
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 |
# File 'lib/reap/project/test.rb', line 39 def test_unit(={}) = test_configuration() tests = ['tests'] loadpath = ['loadpath'] requires = ['requires'] live = ['live'] exclude = ['exclude'] #log = options['log'] != false #logfile = File.join('log', apply_naming_policy('test', 'log')) # what about arguments for selecting specific tests? tests = ['arguments'] if ['arguments'] #unless live # loadpath.each do |lp| # $LOAD_PATH.unshift(File.expand_path(lp)) # end #end if File.exist?('test/suite.rb') files = 'test/suite.rb' else files = multiglob_r(*tests) end if files.empty? $stderr.puts "No tests." return end filelist = files.select{|file| !File.directory?(file) }.join(' ') if live command = %[testrb #{filelist} 2>&1] else command = %[testrb -I#{loadpath.join(':')} #{filelist} 2>&1] end sh command #if log && !dryrun? # command = %[testrb -I#{loadpath} #{filelist} > #{logfile} 2>&1] # /dev/null 2>&1 # system command # puts "Updated #{logfile}" #end end |
#trace=(x) ⇒ Object
89 |
# File 'lib/reap/project.rb', line 89 def trace=(x) ; runmodes.trace = x ; end |
#trace? ⇒ Boolean
83 |
# File 'lib/reap/project.rb', line 83 def trace? ; runmodes.trace? ; end |
#verbose=(x) ⇒ Object
91 |
# File 'lib/reap/project.rb', line 91 def verbose=(x) ; runmodes.verbose = x ; end |
#verbose? ⇒ Boolean
85 |
# File 'lib/reap/project.rb', line 85 def verbose? ; runmodes.verbose? ; end |