Class: Reap::Project
- Inherits:
-
Object
- Object
- Reap::Project
- Includes:
- Utilities
- Defined in:
- lib/reap/project.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/svn.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,
lib/reap/project/rubyforge.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
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')
Instance Attribute Summary
Attributes included from Utilities
#dryrun, #force, #trace, #verbose
Instance Method Summary collapse
-
#announce(options = nil) ⇒ Object
Make a release announcement.
-
#announce_message(options = {}) ⇒ Object
Make 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.
- #debug=(x) ⇒ Object
- #debug? ⇒ Boolean
-
#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_docs(options = nil) ⇒ Object
Create off-line documentation package.
-
#package_gem(options = nil) ⇒ Object
Routes to $gem_package.
-
#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, 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.
-
#rubyforge(options = nil) ⇒ Object
Returns Rubyforge system object.
-
#rubyforge_release(options) ⇒ Object
Release packages to rubyforge.
- #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_branch(*args) ⇒ Object
Branch current version of project.
-
#scm_log(options = {}) ⇒ Object
Generate ChangeLog.
-
#scm_tag(*args) ⇒ Object
Tag current versoin of project.
-
#settings ⇒ Object
(also: #configuration)
Configuration data.
-
#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.
-
#svn_branch(options = nil) ⇒ Object
Branch current version.
-
#svn_log(options = nil) ⇒ Object
Create changelog.
-
#svn_tag(options = nil) ⇒ Object
Tag current version.
-
#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
- #unfold_paragraphs(string) ⇒ Object
- #verbose=(x) ⇒ Object
- #verbose? ⇒ Boolean
Methods included from Utilities
#ask, #bin?, #cd, #command_paths, #dir!, #dir?, directory!, directory?, #email, exist!, exist?, #exists!, #exists?, #file!, #file?, #fileutils, #glob, #multiglob, #multiglob_r, #out_of_date?, #password, path!, path?, #read, #rm_r, #safe?, #sh, #stage, #stage_manifest, #status, #tar_bzip, #tgz, #write, #zip, #ziputils
Constructor Details
#initialize(options = nil) ⇒ Project
New Project.
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/reap/project.rb', line 41 def initialize(=nil) @options = || {} begin @location = locate raise LoadError, "no .reap configuration file" unless @location @metadata = Metadata.read(location) @settings = Settings.read(location, @metadata) rescue LoadError => e abort e..capitalize + '.' end end |
Instance Method Details
#announce(options = nil) ⇒ Object
Make a release announcement. Generates and can email release announcements. The announcement if built from the README file unless another file is specified.
This will subsititue the first line mathing /please see notes/i for the notelog. And /please see change/i for the changelog.
The following settings apply:
title Project title.
subtitle Brief one-line description.
version Project version.
description Long description of project.
homepage Project homepage web address.
slogan Motto for you project.
memo File that contains announcement message.
template Announcement template file, rather then README.
mail_to Email address(es) to send announcemnt.
If mail_to 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?
A template file can be specified that uses “$setting” as substitutes for poject information.
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 |
# File 'lib/reap/project/announce.rb', line 38 def announce(=nil) = (, 'announce', 'mail') = () = .to_ostruct mail_to = .mail_to mail_from = .mail_from subject = .subject # Subject line (default is "ANN: project version"). server = .server # Email server port = .port # Emails server port (default is usually correct). account = .account # Email account name (defaults to mail_from). domain = .domain # User domain (not sure why SMTP requires this?) login = .login # Login type (plain, login) secure = .secure # Use TLS/SSL true or false? password = .password || ENV['EMAIL_PASSWORD'] title = .title || .title version = .versoin || .version # defaults subject ||= "%s, v%s release" account ||= mail_from subject = subject % [title, version] if dryrun? puts "email '#{subject}'" puts "\n#{}\n\n" if verbose? else puts "\n#{}\n\n" if mail_to ans = ask("Would you like to email this announcement?", "yN") case ans.downcase when 'y', 'yes' email(, :to => mail_to, :from => mail_from, :subject => subject, :server => server, :port => port, :domain => domain, :account => account, :login => login, :secure => secure, :password => password ) end end end end |
#announce_message(options = {}) ⇒ Object
Make a release announcement. Generates and can email a release announcements. These are nicely formated message and can email the message to the specified address(es).
The following settings apply:
template Announcement file/template.
cutoff Max number of lines of changelog to show.
A template file can be specified that uses “$setting” as substitutes for poject information.
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 |
# File 'lib/reap/project/announce.rb', line 103 def (={}) config = settings['announce'] || {} = config.merge().to_ostruct cutoff = .cutoff || 30 template = .template || "{ANNOUNCE}{,.txt}" #config['mail_to'] = nil if keys['mail_to'].empty? # Build message # template template = Dir.glob(.template.to_s, File::FNM_CASEFOLD).first if template readme = File.read(template) readme = unfold_paragraphs(readme) else readme = '' readme << "= #{.title} v#{.version}\n\n" readme << " #{.homepage}\n\n" readme << "#{.description}\n\n" readme << "Please see the NOTES file.\n\n" readme << "== CHANGES\n\n" readme << "Please see the CHANGES file.\n" end # changelog file = Dir.glob('change{s,log}{,.txt}', File::FNM_CASEFOLD)[0] changelog = file ? File.read(file).strip : '' #changelog = unfold_paragraphs(changelog) changelog = changelog.split("\n")[0..cutoff].join("\n") # noteslog file = Dir.glob('note{s,log}{,.txt}', File::FNM_CASEFOLD)[0] notelog = file ? File.read(file).strip : '' notelog = unfold_paragraphs(notelog) # Strip tiny version zero. #if keys['version'] =~ /[.].*?[.]/ # keys['version'] = keys['version'].chomp('.0') #end # Make announcement message = readme.dup #message.gsub!('$readme$', readme || '') .sub!(/^\s*please\ see(\ the)?\ notes(.*?)$/i, "\n" + notelog) if notelog .sub!(/^\s*please\ see(\ the)?\ change(.*?)$/i, "\n" + changelog) if changelog template = .dup template.scan(/\$(\w+?)\$/m) do |key| #key = key.strip name = $1.strip #key[1..-1] if .respond_to?(name.downcase) value = .send(name.downcase) .gsub!("$#{name}$", value.to_s.strip) else puts "Warning: Unknown project field -- #{name}." end end .gsub!(/(^|[ ])[$].*?(?=[ ]|$)/,'') # remove unused vars .gsub!(/\n\s*\n\s*\n/m,"\n\n") # remove any triple blank lines .rstrip! return 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.
117 118 119 120 121 122 123 |
# File 'lib/reap/project.rb', line 117 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.
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/reap/project/package.rb', line 9 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.
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/reap/project/rdoc.rb', line 78 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.
158 159 160 161 162 163 164 165 166 167 |
# File 'lib/reap/project/rdoc.rb', line 158 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 |
#debug=(x) ⇒ Object
85 |
# File 'lib/reap/project.rb', line 85 def debug=(x) ; ['debug'] = x ; end |
#debug? ⇒ Boolean
79 |
# File 'lib/reap/project.rb', line 79 def debug? ; ['debug'] ; end |
#display_location ⇒ Object
Display the project’s root location.
107 108 109 |
# File 'lib/reap/project.rb', line 107 def display_location puts "[#{location}]" end |
#document(options) ⇒ Object
Generate documentation. At this time it simply means generating rdocs.
8 9 10 |
# File 'lib/reap/project/rdoc.rb', line 8 def document() rdoc() end |
#dryrun=(x) ⇒ Object Also known as: noharm=
81 |
# File 'lib/reap/project.rb', line 81 def dryrun=(x) ; ['dryrun'] = x ; end |
#dryrun? ⇒ Boolean Also known as: noharm?
alias_method :init_options, :options # TODO: Improve me! (see stamp.rb)
75 |
# File 'lib/reap/project.rb', line 75 def dryrun? ; ['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
83 |
# File 'lib/reap/project.rb', line 83 def force=(x) ; ['force'] = x ; end |
#force? ⇒ Boolean
77 |
# File 'lib/reap/project.rb', line 77 def force? ; ['force'] ; end |
#gem_clobber(options = nil) ⇒ Object
Remove gem package products.
7 8 9 10 11 12 13 14 15 |
# File 'lib/reap/project/gem.rb', line 7 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?
81 82 83 84 |
# File 'lib/reap/project/gem.rb', line 81 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?
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/gem.rb', line 21 def gem_package(=nil) begin require 'rubygems/specification' Gem::manage_gems rescue LoadError #raise LoadError, "RubyGems is not installed?" end = (, 'package-gem', 'package') prepare() package = .clone package.update() abort "No name" unless package.name abort "No version" unless package.version store = 'pkg' #package.package_directory fname = package.stage_name files = package.filelist stage = File.join(store, fname) pfile = stage + ".gem" unless out_of_date?(pfile, *files) or force? report_package_already_built(pfile) return end rm_r(stage) if File.exist?(stage) # remove old stage stage(stage, files) # make new stage package_manifest(stage) # generate manifest if dryrun? status "gem build #{stage}" else file = nil cd(stage) do #status "vi #{metadata.name}.gemspec" builder = ::Gem::Builder.new(gemspec(package)) status "gem build #{stage}" unless dryrun? file = builder.build file = File.(file) end end # transfer gem package to package store mkdir_p(store) destination = File.join(store, File.basename(file)) mv(file, store) unless File.(file) == File.(destination) end return destination end |
#gem_uninstall ⇒ Object
Uninstall gem package.
TODO: Sepcify version?
90 91 92 93 94 |
# File 'lib/reap/project/gem.rb', line 90 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.
136 137 138 139 140 141 142 143 144 145 |
# File 'lib/reap/project.rb', line 136 def introspect() args = ['arguments'] if args args.each do |field| puts .send(field) end else y self end end |
#invoke(command, *args) ⇒ Object
Invoke a tool.
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/reap/project.rb', line 92 def invoke(command, *args) #display_location meth = method(command) chdir_to_project do case meth.arity when 0 meth.call else meth.call(*args) end end end |
#location ⇒ Object
Location of project.
56 |
# File 'lib/reap/project.rb', line 56 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 |
# 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 log_notes_save(output, notes, labels) puts counts.collect{|l,n| "#{n} #{l}s"}.join(', ') puts "Notes saved in #{output} folder." end end |
#make ⇒ Object
Compile extensions.
33 34 35 36 |
# File 'lib/reap/project/make.rb', line 33 def make make_config make_target end |
#make_clean ⇒ Object
Remove enouhg compile products for a clean compile.
47 48 49 |
# File 'lib/reap/project/make.rb', line 47 def make_clean make_target 'clean' end |
#make_config ⇒ Object
Create Makefile(s).
65 66 67 68 69 70 71 72 |
# File 'lib/reap/project/make.rb', line 65 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.
53 54 55 56 57 58 59 |
# File 'lib/reap/project/make.rb', line 53 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.
40 41 42 43 |
# File 'lib/reap/project/make.rb', line 40 def make_static make_config make_target 'static' end |
#manifest_file ⇒ Object
Project manifest file.
149 150 151 |
# File 'lib/reap/project.rb', line 149 def manifest_file Dir.glob('Manifest{,.txt}', File::FNM_CASEFOLD).first end |
#metadata ⇒ Object
Project metadata.
60 |
# File 'lib/reap/project.rb', line 60 def ; @metadata ; end |
#options ⇒ Object
Common options.
72 |
# File 'lib/reap/project.rb', line 72 def ; @options ; end |
#package(options = nil) ⇒ Object
General pack command.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/reap/project/package.rb', line 38 def package(=nil) packopts = (, 'package') formats = packopts['formats'] || ['zip'] formats = [formats].flatten prepare() puts unless dryrun? formats.each do |format| send("package_#{format}", ) puts unless dryrun? end end |
#package_docs(options = nil) ⇒ Object
Create off-line documentation package.
FIXME: package_docs is not yet ready for use.
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/reap/project/package.rb', line 145 def package_docs(=nil) = (, 'package-doc') dir = ['dir'] || 'doc' name = ['name'] || .name ver = ['version'] || .version cd(dir) do zip "-czhvf #{name}-docs-#{ver}.zip *" end end |
#package_gem(options = nil) ⇒ Object
Routes to $gem_package.
55 56 57 |
# File 'lib/reap/project/package.rb', line 55 def package_gem(=nil) gem_package() end |
#package_tgz(options = nil) ⇒ Object
Create a Tar’d Gzip package.
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 |
# File 'lib/reap/project/package.rb', line 61 def package_tgz(=nil) = (, 'package-tgz', 'package') prepare() package = .clone package.update() abort "No name" unless package.name abort "No version" unless package.version store = 'pkg' #package.package_directory fname = package.stage_name files = package.filelist stage = File.join(store, fname) pfile = stage + ".tgz" unless out_of_date?(pfile, *files) or force? report_package_already_built(pfile) return end rm_r(stage) if File.exist?(stage) # remove old stage stage(stage, files) # make new stage package_manifest(stage) # generate stage manifest if dryrun? status "tar -cxf #{fname}.tgz" else file = nil cd(store) do file = tgz(fname) # FIXME: Prefer .tgz as extensions. end transfer(file, store) report_package_built(file) end end |
#package_zip(options = nil) ⇒ Object
Create Zip package.
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 |
# File 'lib/reap/project/package.rb', line 102 def package_zip(=nil) = (, 'package-zip', 'package') prepare() package = .clone package.update() abort "No name" unless package.name abort "No version" unless package.version store = 'pkg' #package.package_directory fname = package.stage_name files = package.filelist stage = File.join(store, fname) pfile = stage + ".zip" unless out_of_date?(pfile, *files) or force? report_package_already_built(pfile) return end rm_r(stage) if File.exist?(stage) # remove old stage stage(stage, files) # make new stage package_manifest(stage) # generate manifest if dryrun? status "zip -r #{fname}.zip ." else file = nil cd(store) do file = zip(fname) end transfer(file, store) report_package_built(file) end end |
#prepare(options) ⇒ Object
Prepare for packaging (clean, distclean, stamp).
TODO: When we add support for binary packages distclean
should not be done for them.
27 28 29 30 31 32 33 34 |
# File 'lib/reap/project/package.rb', line 27 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
.
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 |
# File 'lib/reap/project/rdoc.rb', line 19 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'] #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 little rig 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 |
# File 'lib/reap/project/release.rb', line 11 def release(={}) package() rubyforge_release() end |
#ridoc(options = nil) ⇒ Object
generate local ri docs
Generate RI documentation. This utilizes rdoc to produce the appropriate files.
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 |
# File 'lib/reap/project/rdoc.rb', line 130 def ridoc(=nil) = (, 'doc-ri', 'ri') = DEFAULT['ri'].merge() cmdopts = {} cmdopts['op'] = ['output'] cmdopts['exclude'] = ['exclude'] output = ['output'] files = ['include'] # || ['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 #{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.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/reap/project/release.rb', line 21 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 = ask("Tag current version? ", "Yn") =~ /^(|y|yes)$/i 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 |
#rubyforge(options = nil) ⇒ Object
Returns Rubyforge system object.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/reap/project/rubyforge.rb', line 9 def rubyforge( = nil) = (, 'rubyforge') = {} [:dryrun] = dryrun? [:trace] = trace? [:project] = ['project'] || .project [:username] = ['username'] || ENV['RUBYFORGE_USERNAME'] [:group_id] = ['group'] [:password] = ['password'] || ENV['RUBYFORGE_PASSWORD'] unless [:password] abort "Please provide --password=xxxxxxx." end Rubyforge.new() end |
#rubyforge_release(options) ⇒ Object
Release packages to rubyforge.
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 |
# File 'lib/reap/project/rubyforge.rb', line 29 def rubyforge_release() = (, '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 File.exist?(changelog) ['notelog'] = notelog if 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 # Not going to do dryrun in Rubyforge class b/c it still requires logging in. if dryrun? files.each do |file| puts "release #{file}" end else host = rubyforge() host.release() end 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_branch(*args) ⇒ Object
Branch current version of project. This method routes to the appropriate method for the project’s source control manager.
55 56 57 58 59 60 61 |
# File 'lib/reap/project/scm.rb', line 55 def scm_branch(*args) if File.directory?('.svn') svn_branch(*args) else abort "Only Subversion is currently supported." end end |
#scm_log(options = {}) ⇒ Object
Generate ChangeLog. This method routes to the appropriate method for the project’s source control manager.
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 |
# File 'lib/reap/project/scm.rb', line 13 def scm_log(={}) create_txtlog = (['txtlog'] != false) create_xmllog = (['xmllog'] != false) xmlout = ['xmloutput'] || 'site/log' # TODO: How to set site/? if create_txtlog txtlog = apply_naming_policy('changelog', 'txt') 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?('/') if File.directory?('.svn') svn_log('txtlog' => txtlog, 'xmllog' => xmllog) else abort "Only Subversion is currently supported." end end |
#scm_tag(*args) ⇒ Object
Tag current versoin of project. This method routes to the appropriate method for the project’s source control manager.
43 44 45 46 47 48 49 |
# File 'lib/reap/project/scm.rb', line 43 def scm_tag(*args) if File.directory?('.svn') svn_tag(*args) else abort "Only Subversion is currently supported." end end |
#settings ⇒ Object Also known as: configuration
Configuration data.
64 |
# File 'lib/reap/project.rb', line 64 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 = (specs) loadpath = (loadpath) requires = (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 |
# 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(/[.]/).each_with_index do |x, i| points[i] = (bumps[i] ? x.to_i + 1 : x).to_s end version = points.join('.').sub(/[.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 |
#svn_branch(options = nil) ⇒ Object
Branch current version.
message Optional commit message. This is intended for commandline
usage. (Use -m for shorthand).
TODO: How should metadata.repository come into play here?
14 15 16 17 |
# File 'lib/reap/project/svn.rb', line 14 def svn_branch(=nil) = (, 'scm-branch', 'scm') svn_system.branch() end |
#svn_log(options = nil) ⇒ Object
Create changelog.
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.
38 39 40 41 42 43 44 |
# File 'lib/reap/project/svn.rb', line 38 def svn_log(=nil) txtlog = ['txtlog'] xmllog = ['xmllog'] svn_system.log(txtlog) svn_system.log_xml(xmllog) if xmllog end |
#svn_tag(options = nil) ⇒ Object
Tag current version.
message Optional commit message. This is intended for commandline
usage. (Use -m for shorthand).
TODO: How should metadata.repository come into play here?
26 27 28 29 |
# File 'lib/reap/project/svn.rb', line 26 def svn_tag(=nil) = (, 'scm-tag', 'scm') svn_system.tag() 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.
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 240 |
# File 'lib/reap/project/test.rb', line 198 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.
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/test.rb', line 93 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.
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 |
# File 'lib/reap/project/test.rb', line 143 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?
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 |
# File 'lib/reap/project/test.rb', line 40 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
82 |
# File 'lib/reap/project.rb', line 82 def trace=(x) ; ['trace'] = x ; end |
#trace? ⇒ Boolean
76 |
# File 'lib/reap/project.rb', line 76 def trace? ; ['trace'] ; end |
#unfold_paragraphs(string) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/reap/project/announce.rb', line 173 def unfold_paragraphs(string) blank = false text = '' string.split(/\n/).each do |line| if /\S/ !~ line text << "\n\n" blank = true else if /^(\s+|[*])/ =~ line text << (line.rstrip + "\n") else text << (line.rstrip + " ") end blank = false end end return text end |
#verbose=(x) ⇒ Object
84 |
# File 'lib/reap/project.rb', line 84 def verbose=(x) ; ['verbose'] = x ; end |
#verbose? ⇒ Boolean
78 |
# File 'lib/reap/project.rb', line 78 def verbose? ; ['verbose'] ; end |