rucola 0.0.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. data/ChangeLog +468 -0
  2. data/History.txt +25 -0
  3. data/License.txt +1 -1
  4. data/Manifest.txt +32 -0
  5. data/README.txt +9 -67
  6. data/Rakefile +39 -31
  7. data/TODO +10 -18
  8. data/app_generators/rucola/rucola_generator.rb +15 -8
  9. data/app_generators/rucola/templates/Rakefile.erb +35 -7
  10. data/app_generators/rucola/templates/config/boot.rb +0 -1
  11. data/app_generators/rucola/templates/config/dependencies.rb +31 -0
  12. data/app_generators/rucola/templates/config/environment.rb +0 -1
  13. data/app_generators/rucola/templates/config/environments/debug.rb +13 -1
  14. data/app_generators/rucola/templates/config/environments/release.rb +15 -1
  15. data/app_generators/rucola/templates/config/environments/test.rb +7 -1
  16. data/app_generators/rucola/templates/misc/rb_main.rb.erb +12 -1
  17. data/app_generators/rucola/templates/project.pbxproj.erb +4 -0
  18. data/app_generators/rucola/templates/script/console +10 -0
  19. data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +22 -10
  20. data/app_generators/rucola/templates/test/test_helper.rb +1 -0
  21. data/bin/rucola +4 -2
  22. data/lib/rucola/dependencies.rb +241 -0
  23. data/lib/rucola/dependencies/exclusions.rb +20 -0
  24. data/lib/rucola/dependencies/override_require_and_gem.rb +30 -0
  25. data/lib/rucola/dependencies/resolver.rb +68 -0
  26. data/lib/rucola/fsevents.rb +108 -0
  27. data/lib/rucola/initializer.rb +149 -117
  28. data/lib/rucola/log.rb +61 -0
  29. data/lib/rucola/nib.rb +3 -3
  30. data/lib/rucola/reloader.rb +39 -0
  31. data/lib/rucola/ruby_debug.rb +27 -0
  32. data/lib/rucola/rucola_support.rb +1 -2
  33. data/lib/rucola/rucola_support/core_ext.rb +4 -2
  34. data/lib/rucola/rucola_support/core_ext/objc.rb +9 -4
  35. data/lib/rucola/rucola_support/core_ext/objc/nsimage.rb +22 -0
  36. data/lib/rucola/rucola_support/core_ext/ruby.rb +11 -4
  37. data/lib/rucola/rucola_support/core_ext/ruby/file.rb +11 -0
  38. data/lib/rucola/rucola_support/core_ext/ruby/kernel.rb +16 -0
  39. data/lib/rucola/rucola_support/core_ext/ruby/object.rb +47 -0
  40. data/lib/rucola/rucola_support/core_ext/ruby/string.rb +8 -0
  41. data/lib/rucola/rucola_support/notifications/notifications.rb +26 -28
  42. data/lib/rucola/rucola_support/rc_app.rb +18 -0
  43. data/lib/rucola/tasks/dependencies.rake +49 -0
  44. data/lib/rucola/tasks/deploy.rake +131 -0
  45. data/lib/rucola/tasks/main.rake +39 -6
  46. data/lib/rucola/tasks/xcode.rake +54 -11
  47. data/lib/rucola/test_case.rb +138 -0
  48. data/lib/rucola/test_helper.rb +11 -5
  49. data/lib/rucola/version.rb +2 -2
  50. data/lib/rucola/xcode.rb +39 -9
  51. data/rucola_generators/controller/templates/test_controller_template.rb.erb +19 -7
  52. data/rucola_generators/simple_model/USAGE +5 -0
  53. data/rucola_generators/simple_model/simple_model_generator.rb +54 -0
  54. data/rucola_generators/simple_model/templates/simple_model.rb.erb +2 -0
  55. data/rucola_generators/simple_model/templates/test_simple_model.rb.erb +11 -0
  56. data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +24 -13
  57. data/test/fixtures/dependencies/foo.rb +2 -0
  58. data/test/fixtures/dependencies/foo/bar.rb +0 -0
  59. data/test/fixtures/dependencies/foo/baz.rb +0 -0
  60. data/test/fixtures/dependencies/requires_fileutils.rb +1 -0
  61. data/test/fixtures/some_reloadable_class.rb +4 -0
  62. data/test/test_core_ext.rb +80 -0
  63. data/test/test_dependencies.rb +205 -0
  64. data/test/test_fsevents.rb +152 -0
  65. data/test/test_helper.rb +30 -1
  66. data/test/test_initializer.rb +56 -23
  67. data/test/test_log.rb +44 -0
  68. data/test/test_objc_core_ext.rb +23 -0
  69. data/test/test_rc_app.rb +5 -0
  70. data/test/test_reloader.rb +28 -0
  71. data/test/test_rucola_generator.rb +7 -0
  72. data/test/test_simple_model_generator.rb +48 -0
  73. data/test/test_xcode.rb +85 -5
  74. data/website/index.html +17 -91
  75. data/website/index.txt +14 -81
  76. data/website/template.rhtml +1 -1
  77. metadata +120 -76
@@ -1,2 +1 @@
1
1
  require File.dirname(__FILE__) + '/environment.rb'
2
- Rucola::Initializer.run(:set_load_path)
@@ -0,0 +1,31 @@
1
+ Rucola::Dependencies.run do
2
+ # Specify dependencies of your application.
3
+ # Eg:
4
+ #
5
+ # dependency 'net/http'
6
+ #
7
+ # Or if it's a gem you can also specify a specific version.
8
+ # (See the gem documentation about the possibilities).
9
+ # Eg:
10
+ #
11
+ # dependency 'daemons', '1.0.7'
12
+ #
13
+ # Sometimes there will be some libraries that just can't be resolved. For these you can add exceptions:
14
+ # Eg:
15
+ #
16
+ # # when "require 'xml-simple'" is called it will be replaced with "require 'xmlsimple'"
17
+ # exception 'xml-simple', 'xmlsimple'
18
+ #
19
+ # Or you can pass these in a block for grouping,
20
+ # but note that it's exaclty the same as defining the exception outside of the block.
21
+ # Eg:
22
+ #
23
+ # dependency 'activesupport' do
24
+ # # there's a problem with the gem being named 'xml-simple',
25
+ # # but the file's called 'xmlsimple'.
26
+ # exception 'xml-simple', 'xmlsimple'
27
+ # end
28
+
29
+ # We'll assume that you'll want to bundle rucola by default.
30
+ dependency 'rucola'
31
+ end
@@ -7,5 +7,4 @@ Rucola::Initializer.run do |config|
7
7
  #
8
8
  # Use active_record bindings
9
9
  # config.use_active_record = true
10
- #
11
10
  end
@@ -1,3 +1,15 @@
1
1
  # Perform any debug specific task here.
2
2
 
3
- puts 'Debugging'
3
+ Rucola::Initializer.run do |config|
4
+ # The debugger allows you to easily set breakpoints and debug them.
5
+ # See the documentation from ruby-debug for its usage:
6
+ # http://www.datanoise.com/ruby-debug/
7
+
8
+ config.use_debugger = true
9
+
10
+ # Turning on the reloader will start a fsevent loop which watches the files in app/ for changes
11
+ # and try to reload any classes that have been saved while the app is running.
12
+ # It could however lead to erratic behaviour and it's therefor turned off by default.
13
+ #
14
+ # config.use_reloader = true
15
+ end
@@ -1,3 +1,17 @@
1
1
  # Perform any release specific tasks here.
2
2
 
3
- puts 'Releasing'
3
+ Rucola::Initializer.run do |config|
4
+ # Declare which dependency types should be bundled with a release build.
5
+ # Most of the times you would probably only bundle gems if you're targeting
6
+ # a ruby which is compatible and contains the right site libs.
7
+ #
8
+ # config.dependency_types = :gem, :standard, :other
9
+ #
10
+ # You can completely disable the usage of rubygems by setting this to false.
11
+ # Unless you're using gems which are installed on a system by default, it's
12
+ # better to set it to false. This will enable you to debug wether or not your
13
+ # application has been bundled succesfully, PLUS not using rubygems will improve
14
+ # the performance of your application.
15
+ #
16
+ # config.use_rubygems = false
17
+ end
@@ -1,3 +1,9 @@
1
1
  # Perform any test specific task here.
2
2
 
3
- puts 'Testing'
3
+ Rucola::Initializer.run do |config|
4
+ # The debugger allows you to easily set breakpoints and debug them.
5
+ # See the documentation from ruby-debug for its usage:
6
+ # http://www.datanoise.com/ruby-debug/
7
+
8
+ # config.use_debugger = true
9
+ end
@@ -6,7 +6,18 @@
6
6
  # Copyright (c) 2007 <%= author %>. All rights reserved.
7
7
  #
8
8
 
9
- require 'rubygems'
9
+ # First check if we might be running a bundled release build.
10
+ # Otherwise load rubygems.
11
+
12
+ third_party_dir = File.expand_path('../vendor/third_party/', __FILE__)
13
+ if File.exist?(File.join(third_party_dir, 'rucola/dependencies/override_require_and_gem.rb'))
14
+ $LOAD_PATH.unshift(third_party_dir)
15
+ require 'rucola/dependencies/override_require_and_gem'
16
+ Rucola::Dependencies.override_require_and_gem!
17
+ else
18
+ require 'rubygems'
19
+ end
20
+
10
21
  require 'rucola'
11
22
 
12
23
  # Start the application
@@ -18,6 +18,7 @@
18
18
  514292D10CC66CDC00F9CEEF /* test in Resources */ = {isa = PBXBuildFile; fileRef = 514292CA0CC66CDC00F9CEEF /* test */; };
19
19
  514292D20CC66CDC00F9CEEF /* vendor in Resources */ = {isa = PBXBuildFile; fileRef = 514292CC0CC66CDC00F9CEEF /* vendor */; };
20
20
  514292EF0CC6823A00F9CEEF /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 514292ED0CC6823A00F9CEEF /* MainMenu.nib */; };
21
+ 51E0DC4F0D8175CF00C898A2 /* lib in Resources */ = {isa = PBXBuildFile; fileRef = 51E0DC4D0D8175CF00C898A2 /* lib */; };
21
22
  /* End PBXBuildFile section */
22
23
 
23
24
  /* Begin PBXFileReference section */
@@ -34,6 +35,7 @@
34
35
  514292CA0CC66CDC00F9CEEF /* test */ = {isa = PBXFileReference; lastKnownFileType = folder; path = test; sourceTree = "<group>"; };
35
36
  514292CC0CC66CDC00F9CEEF /* vendor */ = {isa = PBXFileReference; lastKnownFileType = folder; path = vendor; sourceTree = "<group>"; };
36
37
  514292EE0CC6823A00F9CEEF /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = misc/English.lproj/MainMenu.nib; sourceTree = "<group>"; };
38
+ 51E0DC4D0D8175CF00C898A2 /* lib */ = {isa = PBXFileReference; lastKnownFileType = folder; path = lib; sourceTree = "<group>"; };
37
39
  E8F5E24E03AEB6EC03A81C6F /* RubyCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RubyCocoa.framework; path = /Library/Frameworks/RubyCocoa.framework; sourceTree = "<absolute>"; };
38
40
  E8F5E25803AEB7C803A81C6F /* rb_main.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; name = rb_main.rb; path = misc/rb_main.rb; sourceTree = "<group>"; };
39
41
  /* End PBXFileReference section */
@@ -110,6 +112,7 @@
110
112
  29B97317FDCFA39411CA2CEA /* Resources */ = {
111
113
  isa = PBXGroup;
112
114
  children = (
115
+ 51E0DC4D0D8175CF00C898A2 /* lib */,
113
116
  514292B90CC66CDC00F9CEEF /* app */,
114
117
  514292C10CC66CDC00F9CEEF /* config */,
115
118
  514292C40CC66CDC00F9CEEF /* misc */,
@@ -190,6 +193,7 @@
190
193
  514292D10CC66CDC00F9CEEF /* test in Resources */,
191
194
  514292D20CC66CDC00F9CEEF /* vendor in Resources */,
192
195
  514292EF0CC6823A00F9CEEF /* MainMenu.nib in Resources */,
196
+ 51E0DC4F0D8175CF00C898A2 /* lib in Resources */,
193
197
  );
194
198
  runOnlyForDeploymentPostprocessing = 0;
195
199
  };
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV['RUBYCOCOA_ROOT'] = File.join(File.dirname(__FILE__), '..')
4
+ ENV['RUBYCOCOA_ENV'] = 'debug'
5
+ ENV['DONT_START_RUBYCOCOA_APP'] = 'true'
6
+
7
+ libs = "-r rubygems"
8
+ libs << " -r rucola"
9
+ libs << " -r #{ENV['RUBYCOCOA_ROOT']}/config/boot"
10
+ exec "irb #{libs}"
@@ -1,27 +1,39 @@
1
1
  require File.expand_path('../../test_helper', __FILE__)
2
2
 
3
3
  describe 'ApplicationController' do
4
- before do
5
- @controller = ApplicationController.alloc.init
6
- end
4
+ tests ApplicationController
5
+
6
+ # If necessary, you can setup custom objects for the ib_outlets defined in the class.
7
+ # Note however that by using 'tests ApplicationController' all the outlets will get stubbed
8
+ # with stubs that respond to every message with nil.
9
+ #
10
+ # def after_setup
11
+ # ib_outlets :window => mock("Main Window"),
12
+ # :tableView => OSX::NSTableView.alloc.init,
13
+ # :searchField => OSX::NSSearchField.alloc.init
14
+ #
15
+ # window.stubs(:title => 'Main Window')
16
+ # tableView.addTableColumn OSX::NSTableColumn.alloc.init
17
+ # searchField.stringValue = "foo"
18
+ # end
7
19
 
8
20
  it "should initialize" do
9
- @controller.should.be.an.instance_of ApplicationController
21
+ controller.should.be.an.instance_of ApplicationController
10
22
  end
11
23
 
12
24
  it "should set itself as the application delegate" do
13
- OSX::NSApp.expects(:delegate=).with(@controller)
14
- @controller.ib_outlet(:main_window).expects(:inspect)
15
- @controller.awakeFromNib
25
+ OSX::NSApp.expects(:delegate=).with(controller)
26
+ controller.ib_outlet(:main_window).expects(:inspect)
27
+ controller.awakeFromNib
16
28
  end
17
29
 
18
30
  it "should do some stuff when the application has finished launching" do
19
31
  Kernel.expects(:puts)
20
- @controller.applicationDidFinishLaunching(nil)
32
+ controller.applicationDidFinishLaunching(nil)
21
33
  end
22
34
 
23
35
  it "should do some stuff when the application will terminate" do
24
36
  Kernel.expects(:puts)
25
- @controller.applicationWillTerminate(nil)
37
+ controller.applicationWillTerminate(nil)
26
38
  end
27
- end
39
+ end
@@ -7,5 +7,6 @@ require 'test/spec'
7
7
  require 'mocha'
8
8
  require 'rucola'
9
9
  require 'rucola/test_helper'
10
+ require 'rucola/test_case'
10
11
 
11
12
  require File.expand_path('../../config/boot', __FILE__)
data/bin/rucola CHANGED
@@ -1,9 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
1
3
  require 'rubygems'
2
4
  require 'rubigen'
3
5
 
4
6
  if %w(-v --version).include? ARGV.first
5
- require 'newgem/version'
6
- puts "#{File.basename($0)} #{Newgem::VERSION::STRING}"
7
+ require 'rucola/version'
8
+ puts "#{File.basename($0)} #{Rucola::VERSION::STRING}"
7
9
  exit(0)
8
10
  end
9
11
 
@@ -0,0 +1,241 @@
1
+ require 'rbconfig'
2
+ require 'yaml'
3
+
4
+ require 'rucola/dependencies/exclusions'
5
+
6
+ module Rucola
7
+ class Dependencies
8
+ class RequiredFile
9
+ class UnableToResolveFullPathError < StandardError; end
10
+
11
+ attr_reader :relative_path, :full_path
12
+
13
+ def initialize(relative_path)
14
+ @relative_path, @full_path = resolve_relative_and_full_path(relative_path)
15
+ end
16
+
17
+ def gem_lib?
18
+ Gem.path.any? {|load_path| @full_path =~ /^#{load_path}/ }
19
+ end
20
+
21
+ def standard_lib?
22
+ @full_path =~ /^#{Config::CONFIG['rubylibdir']}/
23
+ end
24
+
25
+ def other_lib?
26
+ !gem_lib? && !standard_lib?
27
+ end
28
+
29
+ def copy_to(path)
30
+ dest_dir = File.join(path, File.dirname(@relative_path))
31
+ dest_path = File.expand_path(File.join(dest_dir, File.basename(@relative_path)))
32
+ return if File.exist?(dest_path)
33
+ FileUtils.mkdir_p(dest_dir) unless File.exist?(dest_dir)
34
+
35
+ puts " #{@full_path}" if Dependencies.verbose
36
+ FileUtils.cp(@full_path, dest_dir)
37
+ end
38
+
39
+ def ==(other)
40
+ @full_path == other.full_path
41
+ end
42
+
43
+ private
44
+
45
+ # If the `relative_path` doesn't start with a slash then we only need to find the `full_path`,
46
+ # otherwise we also need to get the `relative_path`.
47
+ def resolve_relative_and_full_path(relative_path)
48
+ relative_path =~ /^\// ? find_relative_and_full_path(relative_path) : [relative_path, find_full_path(relative_path)]
49
+ end
50
+
51
+ def find_full_path(relative_path)
52
+ $LOAD_PATH.each do |load_path|
53
+ full_path = File.join(load_path, relative_path)
54
+ return full_path if File.exist?(full_path)
55
+ end
56
+ raise UnableToResolveFullPathError, "Unable to resolve the full path for: #{relative_path}"
57
+ end
58
+
59
+ def find_relative_and_full_path(relative_path)
60
+ $LOAD_PATH.each do |load_path|
61
+ if relative_path =~ /^#{load_path}/
62
+ res_full_path = relative_path
63
+ res_relative_path = relative_path[load_path.length..-1]
64
+ puts "WARNING: Not a relative path '#{relative_path}', assuming '#{res_relative_path}'" if Dependencies.verbose
65
+ return [res_relative_path, res_full_path]
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ class Dependency
72
+ attr_reader :name, :version
73
+
74
+ def initialize(name, version = '>=0')
75
+ @name, @version, @required_files = name, version, []
76
+ end
77
+
78
+ def require!
79
+ activate_gem! unless Rucola::RCApp.release?
80
+ Kernel.require(@name)
81
+ end
82
+
83
+ RUBY_BIN = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
84
+ RESOLVER_BIN = File.expand_path("../dependencies/resolver.rb", __FILE__)
85
+ def resolve!
86
+ unless Dependencies.exclude?(@name)
87
+ without_changing_loaded_features do
88
+ cmd = "'#{RUBY_BIN}' '#{RESOLVER_BIN}' '#{@name}' '#{@version}' '#{YAML.dump($LOAD_PATH)}'"
89
+ files = YAML.load(`#{cmd}`)
90
+ require!
91
+ files.each { |file| @required_files << RequiredFile.new(file) }
92
+ end
93
+ end
94
+ end
95
+
96
+ def gem_lib?
97
+ @required_files.first.gem_lib?
98
+ end
99
+
100
+ def standard_lib?
101
+ @required_files.first.standard_lib?
102
+ end
103
+
104
+ def other_lib?
105
+ @required_files.first.other_lib?
106
+ end
107
+
108
+ def copy_to(path, options = {})
109
+ puts "\nCopying dependency '#{pretty_print_name}':\n\n" if Dependencies.verbose
110
+ required_files_of_types(options[:types]).each {|file| file.copy_to(path) }
111
+ end
112
+
113
+ # Returns an array of required files sorted by their full_path.
114
+ def required_files
115
+ @required_files.sort_by {|f| f.full_path }
116
+ end
117
+
118
+ def required_files_of_types(*types)
119
+ sorted_types = types.flatten.compact
120
+ return required_files if sorted_types.empty?
121
+ required_files.select do |file|
122
+ sorted_types.any? {|type| file.send "#{type}_lib?" }
123
+ end
124
+ end
125
+
126
+ def pretty_print_name
127
+ "#{@name}#{' (' + @version + ')' unless @version == '>=0'}"
128
+ end
129
+
130
+ private
131
+
132
+ def without_changing_loaded_features
133
+ loaded_features_before = $LOADED_FEATURES.dup
134
+ yield
135
+ $LOADED_FEATURES.replace(loaded_features_before)
136
+ end
137
+
138
+ def activate_gem!
139
+ begin
140
+ Gem.activate(@name, @version)
141
+ rescue Gem::LoadError
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ class Dependencies
148
+ class << self
149
+ @@verbose = true
150
+ def verbose
151
+ @@verbose
152
+ end
153
+ def verbose=(value)
154
+ if value
155
+ $VERBOSE = true
156
+ else
157
+ $VERBOSE = nil
158
+ end
159
+ @@verbose = value
160
+ end
161
+
162
+ # Loads dependencies from a file which uses 'Rucola::Dependencies.run do ... end' to define dependencies.
163
+ def load(dependencies_file)
164
+ require dependencies_file
165
+ instance
166
+ end
167
+
168
+ def run(&block)
169
+ instance.instance_eval(&block)
170
+ end
171
+
172
+ def instance
173
+ @instance ||= new
174
+ end
175
+ end
176
+
177
+ attr_reader :dependencies
178
+ attr_reader :exceptions
179
+
180
+ def initialize
181
+ @dependencies = []
182
+ @exceptions = {}
183
+ end
184
+
185
+ # Specify dependencies of your application.
186
+ # Eg:
187
+ #
188
+ # dependency 'net/http'
189
+ #
190
+ # Or if it's a gem you can also specify a specific version.
191
+ # (See the gem documentation about the possibilities).
192
+ # Eg:
193
+ #
194
+ # dependency 'daemons', '1.0.7'
195
+ def dependency(name, version = '>=0')
196
+ @dependencies << Dependency.new(name, version)
197
+ yield self if block_given?
198
+ end
199
+
200
+ # Sometimes there will be some libraries that just can't be resolved. For these you can add exceptions:
201
+ # Eg:
202
+ #
203
+ # # when "require 'xml-simple'" is called it will be replaced with "require 'xmlsimple'"
204
+ # exception 'xml-simple', 'xmlsimple'
205
+ #
206
+ # Or you can pass these in a block for grouping,
207
+ # but note that it's exaclty the same as defining the exception outside of the block.
208
+ # Eg:
209
+ #
210
+ # dependency 'activesupport' do
211
+ # # there's a problem with the gem being named 'xml-simple',
212
+ # # but the file is actually called 'xmlsimple'.
213
+ # exception 'xml-simple', 'xmlsimple'
214
+ # end
215
+ def exception(required_name, file_name)
216
+ @exceptions[required_name] = file_name
217
+ end
218
+
219
+ def require!
220
+ @dependencies.each {|dep| dep.require! }
221
+ end
222
+
223
+ def resolve!
224
+ @dependencies.each {|dep| dep.resolve! }
225
+ end
226
+
227
+ # Requires an array of all the required files with any duplicates removed.
228
+ # TODO: Check if using this will save a lot of time while copying,
229
+ # because atm files might be copied multiple times.
230
+ def required_files(*types)
231
+ files = @dependencies.collect {|dep| dep.required_files_of_types(types) }.flatten
232
+ unique_files = []
233
+ files.each { |file| unique_files << file unless unique_files.include?(file) }
234
+ unique_files
235
+ end
236
+
237
+ def copy_to(path, options = {})
238
+ @dependencies.each {|dep| dep.copy_to(path, options) }
239
+ end
240
+ end
241
+ end