rabal 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/CHANGES +13 -0
  2. data/README.PLUGIN +8 -8
  3. data/Rakefile +79 -0
  4. data/lib/rabal.rb +26 -28
  5. data/lib/rabal/application.rb +53 -15
  6. data/lib/rabal/directory_tree.rb +3 -3
  7. data/lib/rabal/error.rb +2 -0
  8. data/lib/rabal/file_tree.rb +9 -4
  9. data/lib/rabal/gemspec.rb +50 -0
  10. data/lib/rabal/logger.rb +15 -6
  11. data/lib/rabal/plugin.rb +9 -5
  12. data/lib/rabal/plugin/core.rb +4 -3
  13. data/lib/rabal/plugin/ext.rb +17 -0
  14. data/lib/rabal/plugin/foundation.rb +21 -10
  15. data/lib/rabal/plugin/license.rb +8 -13
  16. data/lib/rabal/plugin/rubyforge.rb +22 -0
  17. data/lib/rabal/plugin/spec.rb +6 -0
  18. data/lib/rabal/plugin/test.rb +7 -0
  19. data/lib/rabal/plugin_tree.rb +1 -2
  20. data/lib/rabal/project_tree.rb +7 -2
  21. data/lib/rabal/specification.rb +128 -0
  22. data/lib/rabal/tree.rb +19 -5
  23. data/lib/rabal/usage.rb +8 -5
  24. data/lib/rabal/util.rb +2 -2
  25. data/lib/rabal/version.rb +6 -3
  26. data/resources/trees/bin/rabal.project +3 -3
  27. data/resources/trees/core/{CHANGES → CHANGES.erb} +1 -1
  28. data/resources/trees/core/{README → README.erb} +1 -1
  29. data/resources/trees/core/Rakefile.erb +67 -0
  30. data/resources/trees/core/lib/rabal.project.rb.erb +0 -2
  31. data/resources/trees/core/lib/rabal.project/gemspec.rb.erb +51 -0
  32. data/resources/trees/core/lib/rabal.project/specification.rb.erb +128 -0
  33. data/resources/trees/core/lib/rabal.project/version.rb.erb +2 -1
  34. data/resources/trees/ext/ext/rabal.project/ext/mkrf_conf.rb.erb +7 -0
  35. data/resources/trees/ext/tasks/extension.rb.erb +15 -0
  36. data/resources/trees/rubyforge/tasks/rubyforge.rb.erb +105 -0
  37. data/resources/trees/spec/{rabal.project_spec.rb.erb → spec/rabal.project_spec.rb.erb} +0 -0
  38. data/resources/trees/spec/{spec_helper.rb.erb → spec/spec_helper.rb.erb} +0 -0
  39. data/resources/trees/spec/tasks/rspec.rb.erb +20 -0
  40. data/resources/trees/test/tasks/testunit.rb.erb +14 -0
  41. data/resources/trees/test/{rabal.project_test.rb.erb → test/rabal.project_test.rb.erb} +1 -1
  42. data/resources/trees/test/{test_helper.rb.erb → test/test_helper.rb.erb} +1 -1
  43. data/spec/application_spec.rb +47 -0
  44. data/spec/bin_plugin_spec.rb +1 -1
  45. data/spec/core_plugin_spec.rb +10 -3
  46. data/spec/license_plugin_spec.rb +10 -8
  47. data/spec/plugin_tree_spec.rb +4 -4
  48. data/spec/spec_plugin_spec.rb +1 -1
  49. data/spec/test_plugin_spec.rb +1 -1
  50. data/spec/version_spec.rb +1 -1
  51. metadata +73 -24
  52. data/resources/trees/core/Rakefile +0 -0
data/CHANGES ADDED
@@ -0,0 +1,13 @@
1
+ = rabal Changelog
2
+ === Version 0.1.0
3
+
4
+ * Support for building ruby C extensions
5
+ * Highline prompting for arguments missed on the commandline
6
+ * logfile and verbosity options works
7
+ * Refactored generated rakefile tasks into namespaces
8
+ ** rubyforge support
9
+ ** rspec and ruby unit templates
10
+
11
+ === Version 0.0.1
12
+
13
+ * Initial public release
@@ -168,7 +168,7 @@ happening.
168
168
  validate that all of a plugins +parameters+ have a non-nil value.
169
169
  9. Access the directory within the plugin containing the files that this
170
170
  plugin will use. In this case that directory happens to be
171
- +gem_directory/resources/trees/license/+
171
+ <tt>gem_directory/resources/trees/license/</tt>
172
172
  10. Every Plugin is required to have a +@tree+ instance variable. This
173
173
  creates a new DirectoryTree instance and associates it with the "."
174
174
  directory within the resulting project structure. This in effect
@@ -212,7 +212,7 @@ options.
212
212
 
213
213
  At the core of rabal are the resource trees utilized by the plugins to
214
214
  generate an output directory/file structure. These tree _templates_ are
215
- stored within your gem under the +resources/trees+ directory from
215
+ stored within your gem under the <tt>resources/trees</tt> directory from
216
216
  withing your gem.
217
217
 
218
218
  You can get a jump start on your plugin project with:
@@ -236,8 +236,8 @@ returned from the nested calls:
236
236
 
237
237
  resource_by_name(my_main_tree_name)
238
238
 
239
- +my_main_tree_name+ returns +trees/xyzzy+ and +resource_by_name+ will
240
- return +/path/to/gem/resources/trees/xyzzy+.
239
+ +my_main_tree_name+ returns <tt>trees/xyzzy</tt> and +resource_by_name+ will
240
+ return <tt>/path/to/gem/resources/trees/xyzzy</tt>.
241
241
 
242
242
  A later release of rabal will include a rabal plugin generation plugin
243
243
  to simplify the creation of rabal plugins.
@@ -247,7 +247,7 @@ to simplify the creation of rabal plugins.
247
247
  The internal mechanisms of rabal use a Tree data structure to represent
248
248
  the directories and files that are created by rabal. Each node in the
249
249
  tree is represented by a Tree or child class such as DirectoryTree or
250
- FileTree. Each Tree has a +@parameters+ instance variable, which is
250
+ FileTree. Each Tree has a +parameters+ instance variable, which is
251
251
  by convention an instance of OpenStruct. It can be any object though.
252
252
 
253
253
  Any Tree instance or erb template when it is evaluated has access to any
@@ -257,7 +257,7 @@ the *root* of the Tree which is created by Rabal::Plugin::Core.
257
257
  Essentially, in a Tree instance or in an ERB template +method_missing+
258
258
  is defined such that the method call cascades up the Tree data structure
259
259
  until a Tree node is found that either responds to that method or has a
260
- +@parameters+ instance variable that responds to the method call.
260
+ +parameters+ instance variable that responds to the method call.
261
261
 
262
262
  If the call cascades all the way to the *root* and nothing responds to
263
263
  it, then NoMethodError is raised.
@@ -265,10 +265,10 @@ it, then NoMethodError is raised.
265
265
  === Core Parameters
266
266
 
267
267
  Since Rabal::Plugin::Core is the plugin that creates the root of the
268
- entire tree, its +@parameters+ are available. Currently these are
268
+ entire tree, its +parameters+ are available. Currently these are
269
269
  available during tree generation as:
270
270
 
271
- * *root.name* - the name of the project from the command line
271
+ * <b>root.name</b> - the name of the project from the command line
272
272
  * *author* - the author of the project from the <tt>--core-author</tt> option
273
273
  * *email* - the email address of the author from the <tt>--core-email</tt> option
274
274
 
@@ -0,0 +1,79 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/clean'
4
+ require 'rake/rdoctask'
5
+
6
+ # since we have directories named 'core' remove that from CLEAN
7
+ CLEAN.exclude("**/core")
8
+
9
+ $: << File.join(File.dirname(__FILE__),"lib")
10
+ require 'rabal'
11
+
12
+ # load all the extra tasks for the project
13
+ TASK_DIR = File.join(File.dirname(__FILE__),"tasks")
14
+ FileList[File.join(TASK_DIR,"*.rb")].each do |tasklib|
15
+ require "tasks/#{File.basename(tasklib)}"
16
+ end
17
+
18
+ task :default => 'test:default'
19
+
20
+ #-----------------------------------------------------------------------
21
+ # Documentation
22
+ #-----------------------------------------------------------------------
23
+ namespace :doc do |ns|
24
+
25
+ # generating documentation locally
26
+ Rake::RDocTask.new do |rdoc|
27
+ rdoc.rdoc_dir = Rabal::SPEC.local_rdoc_dir
28
+ rdoc.options = Rabal::SPEC.rdoc_options
29
+ rdoc.rdoc_files = Rabal::SPEC.rdoc_files
30
+ end
31
+
32
+ #desc "View the RDoc documentation locally"
33
+ task :view => :rdoc do
34
+ show_files Rabal::SPEC.local_rdoc_dir
35
+ end
36
+ end
37
+
38
+ #-----------------------------------------------------------------------
39
+ # Packaging and Distribution
40
+ #-----------------------------------------------------------------------
41
+ namespace :dist do
42
+
43
+ GEM_SPEC = eval(Rabal::SPEC.to_ruby)
44
+
45
+ Rake::GemPackageTask.new(GEM_SPEC) do |pkg|
46
+ pkg.need_tar = Rabal::SPEC.need_tar
47
+ pkg.need_zip = Rabal::SPEC.need_zip
48
+ end
49
+
50
+ desc "Install as a gem"
51
+ task :install => [:clobber_package, :package] do
52
+ sh "sudo gem install pkg/#{Rabal::SPEC.full_name}.gem"
53
+ end
54
+
55
+ # uninstall the gem and all executables
56
+ desc "Uninstall gem"
57
+ task :uninstall do
58
+ sh "sudo gem uninstall #{Rabal::SPEC.name} -x"
59
+ end
60
+
61
+ desc "dump gemspec"
62
+ task :gemspec do
63
+ puts Rabal::SPEC.to_ruby
64
+ end
65
+
66
+ desc "reinstall gem"
67
+ task :reinstall => [:install, :uninstall]
68
+
69
+ end
70
+
71
+ #-----------------------------------------------------------------------
72
+ # update the top level clobber task to depend on all possible sub-level
73
+ # tasks that have a name like ':clobber' in other namespaces
74
+ #-----------------------------------------------------------------------
75
+ Rake.application.tasks.each do |t|
76
+ if t.name =~ /:clobber/ then
77
+ task :clobber => [t.name]
78
+ end
79
+ end
@@ -1,37 +1,19 @@
1
- module Rabal
2
- AUTHOR = "Jeremy Hinegardner".freeze
3
- AUTHOR_EMAIL = "jeremy@hinegardner.org".freeze
4
- HOMEPAGE = "http://copiousfreetime.rubyforge.org/rabal/"
5
- COPYRIGHT = "2007 #{AUTHOR}".freeze
6
- DESCRIPTION = <<DESC
7
- Ruby Architecture for Building Applications and Libraries.
1
+ require 'find'
2
+ require 'erb'
3
+ require 'logger'
4
+ require 'ostruct'
5
+
6
+ require 'rubygems'
7
+ require 'main'
8
8
 
9
- Rabal is a commandline application for bootstrapping, packaging and
10
- distributing ruby projects.
11
- DESC
9
+ module Rabal
12
10
 
13
11
  ROOT_DIR = File.expand_path(File.join(File.dirname(__FILE__),".."))
14
12
  LIB_DIR = File.join(ROOT_DIR,"lib").freeze
15
13
  KNOWN_WORDS = {
16
- "rabal.project" => lambda { |tree| tree.root.name }
14
+ "rabal.project" => lambda { |tree| tree.root.project_name }
17
15
  }
18
16
 
19
- #
20
- # Utility method to require all files ending in .rb that lie in the
21
- # directory below this file that has the same name as the filename
22
- # passed in.
23
- #
24
- def require_all_libs_relative_to(fname)
25
- search_me = File.join(File.dirname(fname),File.basename(fname,".*"))
26
-
27
- Dir.entries(search_me).each do |rb|
28
- if File.extname(rb) == ".rb" then
29
- require File.join(search_me,rb)
30
- end
31
- end
32
- end
33
- module_function :require_all_libs_relative_to
34
-
35
17
  #
36
18
  # Module singleton methods, allow for accessing a single rabal
37
19
  # application from anywhere
@@ -46,4 +28,20 @@ DESC
46
28
  end
47
29
  end
48
30
  end
49
- Rabal.require_all_libs_relative_to(__FILE__)
31
+
32
+ # require all the files
33
+ require 'rabal/action_tree'
34
+ require 'rabal/application'
35
+ require 'rabal/directory_tree'
36
+ require 'rabal/error'
37
+ require 'rabal/file_tree'
38
+ require 'rabal/gemspec'
39
+ require 'rabal/logger'
40
+ require 'rabal/plugin'
41
+ require 'rabal/plugin_tree'
42
+ require 'rabal/project_tree'
43
+ require 'rabal/specification'
44
+ require 'rabal/tree'
45
+ require 'rabal/usage'
46
+ require 'rabal/util'
47
+ require 'rabal/version'
@@ -1,4 +1,4 @@
1
- require 'main'
1
+ require 'rabal/logger'
2
2
 
3
3
  module Rabal
4
4
  #
@@ -6,6 +6,8 @@ module Rabal
6
6
  #
7
7
  class Application
8
8
 
9
+ include Log
10
+
9
11
  attr_accessor :main
10
12
  attr_accessor :plugin_manager
11
13
  attr_accessor :plugin_load_option_names
@@ -13,7 +15,17 @@ module Rabal
13
15
  attr_accessor :global_option_names
14
16
  attr_accessor :app_argv
15
17
 
16
- def initialize
18
+ # used for testing mainly
19
+ attr_reader :stdin
20
+ attr_reader :stdout
21
+ attr_reader :stderr
22
+
23
+
24
+ def initialize(stdin = $stdin, stdout = $stdout, stderr = $stderr)
25
+ @stdin = stdin
26
+ @stdout = stdout
27
+ @stderr = stderr
28
+
17
29
  @main = nil
18
30
  @plugin_manager = GemPlugin::Manager.instance
19
31
  @plugin_option_names = []
@@ -65,9 +77,9 @@ module Rabal
65
77
  # present in the global main, they won't
66
78
  # actually get displayed in the --help
67
79
  plugin.parameters.each do |pname,pconf|
68
- p_option_name = "#{plugin_load_name}-#{pconf[0]}=[p]"
80
+ p_option_name = "#{plugin_load_name}-#{pconf[:name]}=[p]"
69
81
  pons << p_option_name
70
- option(p_option_name) { description pconf[1] }
82
+ option(p_option_name) { description pconf[:desc] }
71
83
  end
72
84
  }
73
85
  plugin_option_names.concat(pons)
@@ -81,8 +93,8 @@ module Rabal
81
93
  def main
82
94
  return @main if @main
83
95
  @main = Main.new(app_argv) {
84
- description Rabal::DESCRIPTION
85
- author Rabal::AUTHOR
96
+ description Rabal::SPEC.description
97
+ author Rabal::SPEC.author
86
98
  version Rabal::VERSION
87
99
 
88
100
  # Project, the whole reason rabal exists
@@ -104,8 +116,9 @@ module Rabal
104
116
  }
105
117
 
106
118
  option("verbosity=v","v") {
107
- validate { |p| Logger::SEV_LABEL.include?(p.upcase) }
108
- description "One of : #{Logger::SEV_LABEL.join(", ")}"
119
+ validate { |p| ::Logger::SEV_LABEL.include?(p.upcase) }
120
+ description "One of : #{::Logger::SEV_LABEL.join(", ")}"
121
+ default "INFO"
109
122
 
110
123
  }
111
124
 
@@ -136,8 +149,8 @@ module Rabal
136
149
  main.usage u
137
150
  main.run
138
151
  rescue ::Main::Parameter::Error => mpe
139
- puts "Parameter Error: #{File.basename($0)}: #{mpe.message}"
140
- puts "Try `#{File.basename($0)} --help' for more information."
152
+ stderr.puts "Parameter Error: #{File.basename($0)}: #{mpe.message}"
153
+ stderr.puts "Try `#{File.basename($0)} --help' for more information."
141
154
  exit 1
142
155
  end
143
156
  end
@@ -147,24 +160,38 @@ module Rabal
147
160
  # parsed, plugins loaded, some activate, etc.
148
161
  #
149
162
  def rabalize
150
- # create the core plugin to start things off
163
+ logfile_and_level_if_necessary
164
+
165
+ # save our current directory for returning
151
166
  pwd = Dir.pwd
152
167
  begin
153
- core_params = params_for_plugin(Rabal::Plugin::Core)
154
- core_params[:project] = main.params[:project].value
155
- core = Rabal::Plugin::Core.new(core_params)
168
+ Log.debug("Loading plugins")
169
+
170
+ # create the core plugin to start things off
171
+ core_params = params_for_plugin(Rabal::Plugin::Core)
172
+ core_params[:project] = main.params[:project].value
173
+ core = Rabal::Plugin::Core.new(core_params)
174
+
156
175
  using_plugins.each do |p|
157
176
  next if p == Rabal::Plugin::Core
177
+ Log.debug("processing #{p.name} plugin")
158
178
  pi = p.new(params_for_plugin(p))
179
+ Log.debug("getting tree #{pi.tree.inspect}")
159
180
  core.tree << pi.tree
160
181
  end
161
182
 
162
183
  # not using chdir blocks, as that raises
163
184
  # warning: conflicting chdir during another chdir block
185
+ # hence our saving of pwd before begin
164
186
  Dir.chdir(File.expand_path(main.params[:directory].value))
187
+
165
188
  core.tree.process
166
189
  rescue ::Rabal::StandardError => rse
167
- puts "Application Error: #{rse.message}"
190
+ stderr.puts "Application Error: #{rse.message}"
191
+ exit 1
192
+ rescue Interrupt => ie
193
+ stderr.puts
194
+ stderr.puts "Interrupted"
168
195
  exit 1
169
196
  ensure
170
197
  Dir.chdir(pwd)
@@ -205,5 +232,16 @@ module Rabal
205
232
  end
206
233
  plugin_hash
207
234
  end
235
+
236
+ #
237
+ # if the params for the logfile were given then open them up and
238
+ #
239
+ def logfile_and_level_if_necessary
240
+ if main.params["logfile"].given? then
241
+ Log.logger = main.params["logfile"].value
242
+ end
243
+ Log.logger.level = ::Logger::SEV_LABEL.index(main.params["verbosity"].value)
244
+ Log.info "Logger initialized"
245
+ end
208
246
  end
209
247
  end
@@ -1,5 +1,6 @@
1
- require 'rabal/action_tree'
2
1
  require 'rabal/util'
2
+ require 'rabal/tree'
3
+ require 'rabal/logger'
3
4
 
4
5
  module Rabal
5
6
  include Util
@@ -9,7 +10,7 @@ module Rabal
9
10
  # parent of the directory this DirectoryTree represents.
10
11
  #
11
12
  class DirectoryTree < ActionTree
12
-
13
+
13
14
  # basename of the directory this Tree represents
14
15
  attr_accessor :dir_name
15
16
 
@@ -17,7 +18,6 @@ module Rabal
17
18
  # this DirectoryTree represents.
18
19
  attr_accessor :parent_dir
19
20
 
20
-
21
21
  # Create a DirectoryTree based up a name, or another directory.
22
22
  # Only the last portion of the directory is used. That is
23
23
  # +File.basename+ is called upon name.
@@ -1,3 +1,5 @@
1
+ require 'rabal'
2
+
1
3
  module Rabal
2
4
  class StandardError < ::StandardError; end
3
5
  class TemplateNotFoundError < Rabal::StandardError ; end
@@ -1,6 +1,4 @@
1
- require 'rabal/action_tree'
2
- require 'rabal/util'
3
- require 'erb'
1
+ require 'rabal'
4
2
 
5
3
  module Rabal
6
4
  include Util
@@ -67,7 +65,14 @@ module Rabal
67
65
  #
68
66
  def before_action
69
67
  info("creating content for #{file_name}")
70
- @file_contents = ERB.new(template).result(binding)
68
+ begin
69
+ @file_contents = ERB.new(template).result(binding)
70
+ rescue Exception => e
71
+ error("Error evaluating template #{file_name}")
72
+ e.message.split("\n").each do |m|
73
+ error(m)
74
+ end
75
+ end
71
76
  end
72
77
 
73
78
  #
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rabal/specification'
3
+ require 'rabal/version'
4
+ require 'rake'
5
+
6
+ module Rabal
7
+ SPEC = Rabal::Specification.new do |spec|
8
+ spec.name = "rabal"
9
+ spec.version = Rabal::VERSION
10
+ spec.rubyforge_project = "copiousfreetime"
11
+ spec.author = "Jeremy Hinegardner"
12
+ spec.email = "jeremy@hinegardner.org"
13
+ spec.homepage = "http://copiousfreetime.rubyforge.org/rabal/"
14
+
15
+ spec.summary = "A tool for bootstrapping project development"
16
+ spec.description = <<-DESC
17
+ Ruby Architecture for Building Applications and
18
+ Libraries.
19
+
20
+ Rabal is a commandline application for bootstrapping,
21
+ packaging and distributing ruby projects.
22
+ DESC
23
+
24
+ spec.extra_rdoc_files = FileList["[A-Z]*"] - FileList["TODO"]
25
+ spec.has_rdoc = true
26
+ spec.rdoc_main = "README"
27
+ spec.rdoc_options = [ "--line-numbers" , "--inline-source" ]
28
+
29
+ spec.test_files = FileList["spec/**/*.rb"]
30
+ spec.executable = spec.name
31
+ spec.files = spec.test_files + spec.extra_rdoc_files +
32
+ FileList["lib/**/*.rb", "resources/**/*"]
33
+
34
+ spec.add_dependency("main", ">= 0.0.2")
35
+ spec.add_dependency("gem_plugin", ">= 0.2.1")
36
+ spec.add_dependency("highline", ">= 1.2.9")
37
+
38
+ spec.platform = Gem::Platform::RUBY
39
+
40
+ spec.local_rdoc_dir = "doc/rdoc"
41
+ spec.remote_rdoc_dir = "#{spec.name}/rdoc"
42
+ spec.local_coverage_dir = "doc/coverage"
43
+ spec.remote_coverage_dir= "#{spec.name}/coverage"
44
+
45
+ spec.remote_site_dir = "#{spec.name}/"
46
+
47
+ end
48
+ end
49
+
50
+