sproutcore 1.0.1031 → 1.0.1035

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