sproutcore 1.0.1031 → 1.0.1035

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.
@@ -1,3 +1,15 @@
1
+ == 1.0.1034
2
+
3
+ - Fixed bug with the new proxy. HTTP method names were not capitalized, causing some servers to throw an exception
4
+
5
+ == 1.0.1033
6
+
7
+ - Updated SproutCore JS
8
+ - Build tools now work as a distribution. We can include resources from other projects as well
9
+
10
+ == 1.0.1009
11
+
12
+ First release of SproutCore 1.0 RC1
1
13
 
2
14
  == 1.0.0.a1 / 2009-04-04
3
15
 
@@ -1,7 +1,7 @@
1
1
  ---
2
- :patch: 1031
3
- :digest: a4a6ad7402d09a2424b632097d189cbe5249461e
2
+ :patch: 1035
3
+ :digest: 6adcb96d3bfd9d5a101f0ff1ae272a5044854a84
4
4
  :dist:
5
- frameworks/sproutcore: 8c54dc5a319e402e86319e5a98c21d16744200d8
5
+ frameworks/sproutcore: edcf66df94134f479ddad658d95b27e94b685c2a
6
6
  :major: 1
7
7
  :minor: 0
@@ -275,6 +275,8 @@ namespace :manifest do
275
275
  :build_task => 'build:bundle_loaded',
276
276
  :resource => 'javascript',
277
277
  :entry_type => :javascript,
278
+ :composite => true, # does not have a source
279
+ :source_entries => [],
278
280
  :target => TARGET
279
281
  end
280
282
 
@@ -210,6 +210,7 @@ SC.Record = SC.Object.extend(
210
210
  */
211
211
  destroy: function() {
212
212
  this.get('store').destroyRecord(null, null, this.get('storeKey'));
213
+ this.propertyDidChange('status');
213
214
  return this ;
214
215
  },
215
216
 
@@ -79,3 +79,14 @@ test("should return receiver", function() {
79
79
  equals(MyApp.foo.destroy(), MyApp.foo, 'should return receiver');
80
80
  });
81
81
 
82
+ test("destroy should update status cache", function() {
83
+ var st = MyApp.foo.get('status');
84
+ ok(st !== SC.Record.DESTROYED_CLEAN, 'precond - foo should not be destroyed');
85
+
86
+ SC.RunLoop.begin();
87
+ MyApp.foo.destroy();
88
+ equals(MyApp.foo.get('status'), SC.Record.DESTROYED_CLEAN, 'status should be DESTROYED_CLEAN immediately when destroyed directly by record');
89
+ SC.RunLoop.end();
90
+ });
91
+
92
+
@@ -39,6 +39,15 @@ SC.StackedView = SC.CollectionView.extend(
39
39
  adjust the height of the view.
40
40
  */
41
41
  layout: { top: 0, left: 0, right: 0, height: 1 },
42
+
43
+ /**
44
+ Return full range of its indexes for nowShowing
45
+
46
+ @returns {SC.IndexSet} full range of indexes
47
+ */
48
+ computeNowShowing: function(rect) {
49
+ return this.get('allContentIndexes');
50
+ },
42
51
 
43
52
  /**
44
53
  Updates the height of the stacked view to reflect the current content of
@@ -98,4 +107,4 @@ SC.StackedView = SC.CollectionView.extend(
98
107
  */
99
108
  didCreateLayer: function() { return this.updateHeight(); }
100
109
 
101
- });
110
+ });
@@ -148,6 +148,18 @@ module SC
148
148
  invoke_with_call_chain(task_args, InvocationChain::EMPTY)
149
149
  end
150
150
 
151
+ def self.log_indent
152
+ @task_indent ||= ''
153
+ end
154
+
155
+ def self.indent_logs
156
+ @task_indent = (@task_indent || '') + ' '
157
+ end
158
+
159
+ def self.outdent_logs
160
+ @task_indent = (@task_indent || '')[0..-3]
161
+ end
162
+
151
163
  # Same as invoke, but explicitly pass a call chain to detect
152
164
  # circular dependencies.
153
165
  def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
@@ -155,23 +167,37 @@ module SC
155
167
  invocation_chain = InvocationChain.append(self, invocation_chain)
156
168
  @lock.synchronize do
157
169
 
170
+ indent = self.class.indent_logs
171
+
158
172
  # Use logging options to decide what to output
159
173
  # one of :env, :name, :none
160
- log_opt = task_options[:log] || :env
174
+ log_opt = task_options[:log] || :none
161
175
  if [:name, :env].include?(log_opt)
162
- SC.logger.debug "invoke ~ #{name} #{format_trace_flags}"
176
+ SC.logger.debug "#{indent}invoke ~ #{name} #{format_trace_flags}"
163
177
  end
164
178
 
165
179
  if log_opt == :env
166
180
  TASK_ENV.each do |key, value|
167
181
  next if %w(config task_env).include?(key.to_s.downcase)
168
- SC.logger.debug " #{key} = #{value.inspect}"
182
+ SC.logger.debug "#{indent} #{key} = #{value.inspect}"
169
183
  end
170
184
  end
171
185
 
186
+ t_start = Time.now.to_f * 1000
187
+
172
188
  invocation_chain = invoke_prerequisites(task_args, invocation_chain)
173
189
  @invoke_count += 1
174
190
  execute(task_args) if needed?
191
+
192
+ t_end = Time.now.to_f * 1000
193
+ t_diff = t_end - t_start
194
+
195
+ # ignore short tasks
196
+ if t_diff > 10
197
+ SC.logger.debug "#{indent}long task ~ #{name}: #{t_diff.to_i} msec"
198
+ end
199
+ self.class.outdent_logs
200
+
175
201
  end
176
202
  end
177
203
  return invocation_chain
@@ -199,6 +225,7 @@ module SC
199
225
 
200
226
  # Execute the actions associated with this task.
201
227
  def execute(args=nil)
228
+
202
229
  @execute_count += 1
203
230
  args ||= EMPTY_TASK_ARGS
204
231
  return if SC.env.dryrun
@@ -211,6 +238,7 @@ module SC
211
238
  act.call(self, args)
212
239
  end
213
240
  end
241
+
214
242
  end
215
243
 
216
244
  # Is this task needed?
@@ -127,7 +127,8 @@ module SC
127
127
  end
128
128
  timestamps.max
129
129
  elsif composite?
130
- source_entries.map { |e| e.timestamp }.max
130
+
131
+ source_entries.map { |e| e.timestamp || 0 }.max || Time.now.to_i
131
132
  else
132
133
  File.exist?(source_path) ? File.mtime(source_path).to_i : 0
133
134
  end
@@ -158,11 +159,21 @@ module SC
158
159
  if paths = self.source_paths
159
160
  paths.each do |path|
160
161
  next unless File.exist?(path)
161
- File.readlines(path).each do |line|
162
- if (line.valid_encoding?)
163
- line.scan(regexp) { |result| yield(result) }
164
- end
165
- end
162
+
163
+ # fine all directives in the source. use file cache to make this
164
+ # fast later on.
165
+ results = target.file_attr('scan_source', path) do
166
+ ret = []
167
+ File.readlines(path).each do |line|
168
+ if (line.valid_encoding?)
169
+ line.scan(regexp) { |result| ret << result }
170
+ end
171
+ end
172
+ ret
173
+ end
174
+
175
+ results.each { |result| yield(result) }
176
+
166
177
  end
167
178
  end
168
179
  end
@@ -175,6 +186,9 @@ module SC
175
186
  # results on all other file types.
176
187
  #
177
188
  def discover_build_directives!
189
+
190
+ target.begin_attr_changes
191
+
178
192
  self.required = []
179
193
  entry = self.transform? ? self.source_entry : self
180
194
  entry.scan_source(BUILD_DIRECTIVES_REGEX) do |matches|
@@ -189,6 +203,9 @@ module SC
189
203
  self.resource = filename
190
204
  end
191
205
  end
206
+
207
+ target.end_attr_changes
208
+
192
209
  end
193
210
 
194
211
  ######################################################
@@ -218,8 +235,34 @@ module SC
218
235
  return self
219
236
  end
220
237
 
238
+ # Diagnostic function. Indicates what will happen if you called build
239
+ def inspect_build_state
240
+ inspect_build_to self.build_path
241
+ end
242
+
243
+ def inspect_staging_state
244
+ inspect_build_to self.staging_path
245
+ end
246
+
221
247
  private
222
248
 
249
+ def inspect_build_to(dst_path)
250
+ return "#{filename}: dst #{dst_path} not found" if !File.exist?(dst_path)
251
+ dst_mtime = File.mtime(dst_path).to_i
252
+ self.source_paths.each do |path|
253
+ if path.nil?
254
+ puts "WARN: nil path in #{filename}"
255
+ next
256
+ end
257
+
258
+ return "#{filename}: src #{path} not found" if !File.exist?(path)
259
+
260
+ src_mtime = File.mtime(path).to_i
261
+ return "#{filename}: src #{path} is newer [#{dst_mtime} < #{src_mtime}]" if dst_mtime < src_mtime
262
+ end
263
+ return "#{filename}: will not build"
264
+ end
265
+
223
266
  def build_to(dst_path)
224
267
  if self.build_task.nil?
225
268
  raise "no build task defined for #{self.filename}"
@@ -245,7 +288,8 @@ module SC
245
288
  :dst_path => dst_path
246
289
 
247
290
  return self
248
- end
291
+ end
292
+
249
293
 
250
294
  end
251
295
 
@@ -5,6 +5,9 @@
5
5
  # and contributors
6
6
  # ===========================================================================
7
7
 
8
+ require 'yaml'
9
+ require 'fileutils'
10
+
8
11
  module SC
9
12
 
10
13
  # Defines a build target in a project. A build target is a component that
@@ -286,6 +289,76 @@ module SC
286
289
  return false
287
290
  end
288
291
 
292
+ # path to attr_cache file
293
+ def file_attr_cache_path
294
+ @file_attr_cache_path ||= (self.cache_root / '__file_attr_cache.yml')
295
+ end
296
+
297
+ # suspend writing the file cache out if needed
298
+ def begin_attr_changes
299
+ @attr_change_level = (@attr_change_level || 0)+1
300
+ end
301
+
302
+ # resume writing file cache out if needed
303
+ def end_attr_changes
304
+ @attr_change_level = (@attr_change_level || 0) - 1
305
+ if @attr_change_level <= 0
306
+ @attr_change_level = 0
307
+ _write_file_attr_cache if @attr_cache_has_changes
308
+ end
309
+ end
310
+
311
+ def _write_file_attr_cache
312
+ if (@attr_change_level||0) > 0
313
+ @attr_cache_has_changes = true
314
+
315
+ else
316
+ @attr_cache_has_changes = false
317
+ if @file_attr_cache
318
+ FileUtils.mkdir_p(File.dirname(file_attr_cache_path))
319
+ fp = File.open(file_attr_cache_path, 'w+')
320
+ fp.write @file_attr_cache.to_yaml
321
+ fp.close
322
+ end
323
+ end
324
+
325
+ end
326
+
327
+
328
+ # returns or computes an attribute on a given file. this will keep the
329
+ # named attribute in a cache keyed against the mtime of the named path.
330
+ # if the mtime matches, the cached value is returned. otherwise, yields
331
+ # to the passed block to compute again.
332
+ def file_attr(attr_name, path, &block)
333
+
334
+ # read cache from disk if needed
335
+ if @file_attr_cache.nil?
336
+ if File.exists?(file_attr_cache_path)
337
+ require 'yaml'
338
+ @file_attr_cache = YAML.load File.read(file_attr_cache_path)
339
+ else
340
+ @file_attr_cache = {}
341
+ end
342
+ end
343
+
344
+ path_root = (@file_attr_cache[path] ||= {})
345
+ attr_info = (path_root[attr_name.to_s] ||= {})
346
+ attr_mtime = attr_info['mtime'].to_i
347
+ path_mtime = File.exists?(path) ? File.mtime(path).to_i : 0
348
+ if attr_mtime.nil? || (path_mtime != attr_mtime)
349
+ SC.logger.debug "MISS file_attr_cache:#{attr_name}: #{File.basename(path)} path_mtime=#{path_mtime} attr_mtime=#{attr_mtime}"
350
+
351
+ value = attr_info['value'] = yield
352
+ attr_info['mtime'] = path_mtime
353
+ _write_file_attr_cache
354
+
355
+ else
356
+ value = attr_info['value']
357
+ end
358
+
359
+ return value
360
+ end
361
+
289
362
  # Computes a unique build number for this target. The build number is
290
363
  # gauranteed to change anytime the contents of any source file changes
291
364
  # or anytime the build number of a required target changes. Although
@@ -321,11 +394,16 @@ module SC
321
394
  # files. It is not as fast as using an mtime, but it will remain
322
395
  # constant from one machine to the next so it can be used when
323
396
  # deploying across multiple build machines, etc.
397
+ begin_attr_changes
324
398
  digests = Dir.glob(File.join(source_root, '**', '*')).map do |path|
325
- allowed = File.exists?(path) && !File.directory?(path)
326
- allowed = allowed && !target_directory?(path)
327
- allowed ? Digest::SHA1.hexdigest(File.read(path)) : nil
399
+ file_attr(:digest, path) do
400
+ allowed = File.exists?(path) && !File.directory?(path)
401
+ allowed = allowed && !target_directory?(path)
402
+ allowed ? Digest::SHA1.hexdigest(File.read(path)) : nil
403
+ end
328
404
  end
405
+ end_attr_changes
406
+
329
407
  digests.compact!
330
408
 
331
409
  # Get all required targets and add in their build number.
@@ -69,7 +69,9 @@ module SC
69
69
  response = http.send(http_method, http_path, headers)
70
70
  else
71
71
  http_body = env['rack.input']
72
- some_request = Net::HTTPGenericRequest.new(http_method, '', '', http_path, headers)
72
+ some_request = Net::HTTPGenericRequest.new http_method.upcase,
73
+ true, true, http_path, headers
74
+
73
75
  some_request.body_stream = http_body
74
76
  response = http.request(some_request)
75
77
  end
@@ -138,6 +138,11 @@ module SC
138
138
  @project = a_project
139
139
  end
140
140
 
141
+ def set_test_project(a_project)
142
+ @project = a_project
143
+ @discovered_project = true
144
+ end
145
+
141
146
  # The current project. This is discovered based on the passed --project
142
147
  # option or based on the current working directory. If no project can
143
148
  # be found, this method will always return null.
@@ -50,7 +50,7 @@ describe SC::Target, 'compute_build_number' do
50
50
  describe "accurate method to compute build number" do
51
51
 
52
52
  before do
53
- @target = @project.target_for(:sproutcore)
53
+ @target = @project.target_for(:sproutcore).prepare!
54
54
  @target.config.build_numbers = nil #precondition
55
55
  @target.config.build_number = nil #precondition
56
56
  end
@@ -72,10 +72,10 @@ describe SC::Target, 'compute_build_number' do
72
72
  end
73
73
 
74
74
  it "changes generated build number if build number for a required target changes" do
75
- target = @project.target_for(:sproutcore)
75
+ target = @project.target_for(:sproutcore).prepare!
76
76
  target.should_not be_nil
77
77
 
78
- required = target.target_for(:desktop)
78
+ required = target.target_for(:desktop).prepare!
79
79
  required.should_not be_nil
80
80
  required.config.build_numbers = nil #precondition
81
81
  required.config.build_number = nil #precondition
@@ -95,10 +95,10 @@ describe SC::Target, 'compute_build_number' do
95
95
  end
96
96
 
97
97
  it "does not change generated build number if a nested target that is not required by target changes" do
98
- target = @project.target_for(:sproutcore)
98
+ target = @project.target_for(:sproutcore).prepare!
99
99
  target.should_not be_nil
100
100
 
101
- not_required = target.target_for(:mobile)
101
+ not_required = target.target_for(:mobile).prepare!
102
102
  not_required.should_not be_nil
103
103
 
104
104
  #precondition
@@ -5,8 +5,15 @@ describe SC::Target, 'required_targets' do
5
5
  include SC::SpecHelpers
6
6
 
7
7
  before do
8
+ @env = SC.build_mode # force debug mode
9
+ SC.build_mode = :debug
10
+
8
11
  @project = fixture_project(:real_world)
9
12
  end
13
+
14
+ after do
15
+ SC.build_mode = @env
16
+ end
10
17
 
11
18
  it "should resolve references to child targets" do
12
19
  target = @project.target_for :sproutcore
@@ -66,15 +73,18 @@ describe SC::Target, 'required_targets' do
66
73
  end
67
74
 
68
75
  it "should log a warning if a required test or debug target could not be found" do
76
+
69
77
  target = @project.target_for :sproutcore
70
78
  target.config.test_required = 'imaginary_foo'
71
79
  target.config.debug_required = 'imaginary_bar'
72
80
 
73
81
  capture('stderr') { target.required_targets(:test => true) }.size.should_not == 0
74
82
  capture('stderr') { target.required_targets(:debug => true) }.size.should_not == 0
83
+
75
84
  end
76
85
 
77
86
  it "should include any CONFIG.theme if passed :theme => true && target_type == :app" do
87
+
78
88
  expected = @project.target_for 'sproutcore/standard_theme'
79
89
 
80
90
  target = @project.target_for :contacts
@@ -5,9 +5,15 @@ describe SC::Tools, 'build-number' do
5
5
  include SC::SpecHelpers
6
6
 
7
7
  before do
8
+ save_env
9
+ SC.build_mode = :production
8
10
  @tool = SC::Tools.new('build_number')
9
11
  end
10
12
 
13
+ after do
14
+ restore_env
15
+ end
16
+
11
17
  it "should raise error if no target is passed" do
12
18
  lambda { @tool.build_number }.should raise_error
13
19
  end
@@ -17,11 +23,12 @@ describe SC::Tools, 'build-number' do
17
23
  end
18
24
 
19
25
  it "should write build number when passed target" do
20
- @tool.project = fixture_project(:real_world) # req...
21
- bn = capture('stdout') { @tool.build_number('sproutcore') }
22
-
23
26
  expected_target = fixture_project(:real_world).target_for(:sproutcore)
24
27
  expected = expected_target.prepare!.compute_build_number
28
+
29
+ @tool.set_test_project fixture_project(:real_world) # req...
30
+ bn = capture('stdout') { @tool.build_number('sproutcore') }
31
+
25
32
  bn.should eql(expected)
26
33
  end
27
34
 
@@ -13,6 +13,14 @@ describe SC::Tools do
13
13
 
14
14
  describe "logger options" do
15
15
 
16
+ before do
17
+ save_env
18
+ end
19
+
20
+ after do
21
+ restore_env
22
+ end
23
+
16
24
  it "should default to warn log level" do
17
25
  SC::Tools.start %w(dummy)
18
26
  SC.env.log_level.should == :warn
@@ -54,6 +62,14 @@ describe SC::Tools do
54
62
 
55
63
  describe "build mode options" do
56
64
 
65
+ before do
66
+ save_env
67
+ end
68
+
69
+ after do
70
+ restore_env
71
+ end
72
+
57
73
  it "should default to :production build mode" do
58
74
  SC::Tools.start %w(dummy)
59
75
  SC.build_mode.should eql(:production)
@@ -48,6 +48,18 @@ module SC
48
48
 
49
49
  module SpecHelpers
50
50
 
51
+ # env doesn't automatically reset
52
+ def save_env
53
+ @env ||= []
54
+ @env << { :env => SC.env.dup, :build_mode => SC.build_mode }
55
+ end
56
+
57
+ def restore_env
58
+ e = (@env || []).pop
59
+ SC.env = e[:env]
60
+ SC.build_mode = e[:build_mode]
61
+ end
62
+
51
63
  def fixture_path(*path_items)
52
64
  (path_items = path_items.flatten).unshift 'fixtures'
53
65
  path_items.map! { |pi| pi.to_s }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sproutcore
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1031
4
+ version: 1.0.1035
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sprout Systems, Inc. Apple Inc. and contributors
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-16 00:00:00 -08:00
12
+ date: 2009-11-19 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency