rucola 0.0.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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