spiderfw 0.6.20 → 0.6.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG +13 -0
  2. data/README.rdoc +8 -2
  3. data/Rakefile +49 -24
  4. data/VERSION +1 -1
  5. data/apps/app_server/controllers/app_server_controller.rb +3 -2
  6. data/apps/app_server/lib/git_app.rb +11 -2
  7. data/apps/config_editor/_init.rb +2 -1
  8. data/apps/config_editor/controllers/config_editor_controller.rb +7 -1
  9. data/apps/drb_server/script/start_server.rb +1 -1
  10. data/apps/servant/bin/spider-servant.rb +1 -1
  11. data/blueprints/home/{spider.gemfile → Gemfile} +18 -3
  12. data/blueprints/install/config.ru +1 -1
  13. data/lib/spiderfw/app.rb +7 -0
  14. data/lib/spiderfw/cmd/cmd.rb +1 -1
  15. data/lib/spiderfw/cmd/commands/app.rb +6 -2
  16. data/lib/spiderfw/cmd/commands/cert.rb +1 -0
  17. data/lib/spiderfw/cmd/commands/console.rb +1 -1
  18. data/lib/spiderfw/cmd/commands/content.rb +2 -2
  19. data/lib/spiderfw/cmd/commands/create.rb +1 -1
  20. data/lib/spiderfw/cmd/commands/model.rb +2 -2
  21. data/lib/spiderfw/cmd/commands/setup.rb +1 -1
  22. data/lib/spiderfw/cmd/commands/test.rb +1 -1
  23. data/lib/spiderfw/config/options/spider.rb +2 -1
  24. data/lib/spiderfw/controller/controller.rb +15 -4
  25. data/lib/spiderfw/controller/mixins/visual.rb +2 -0
  26. data/lib/spiderfw/http/adapters/cgi.rb +3 -3
  27. data/lib/spiderfw/http/adapters/mongrel.rb +2 -2
  28. data/lib/spiderfw/http/adapters/rack.rb +2 -2
  29. data/lib/spiderfw/http/adapters/webrick.rb +2 -2
  30. data/lib/spiderfw/http/server.rb +26 -11
  31. data/lib/spiderfw/i18n/cldr.rb +8 -6
  32. data/lib/spiderfw/i18n/javascript_parser.rb +1 -0
  33. data/lib/spiderfw/init.rb +2 -0
  34. data/lib/spiderfw/model/base_model.rb +13 -3
  35. data/lib/spiderfw/model/condition.rb +4 -0
  36. data/lib/spiderfw/model/mappers/db_mapper.rb +9 -8
  37. data/lib/spiderfw/model/mappers/mapper.rb +18 -10
  38. data/lib/spiderfw/model/migrations/drop_table.rb +20 -0
  39. data/lib/spiderfw/model/migrations/replace.rb +18 -13
  40. data/lib/spiderfw/model/migrations.rb +5 -0
  41. data/lib/spiderfw/model/mixins/tree.rb +1 -1
  42. data/lib/spiderfw/model/model.rb +3 -0
  43. data/lib/spiderfw/model/storage/db/adapters/oracle.rb +1 -1
  44. data/lib/spiderfw/model/storage/db/adapters/sqlite.rb +1 -1
  45. data/lib/spiderfw/model/storage/db/connectors/jdbc_oracle.rb +1 -1
  46. data/lib/spiderfw/model/storage/db/connectors/oci8.rb +1 -1
  47. data/lib/spiderfw/model/storage/db/db_schema.rb +4 -1
  48. data/lib/spiderfw/model/storage/db/dialects/no_total_rows.rb +1 -1
  49. data/lib/spiderfw/setup/app_manager.rb +11 -3
  50. data/lib/spiderfw/setup/app_server_client.rb +13 -7
  51. data/lib/spiderfw/setup/setup_task.rb +43 -0
  52. data/lib/spiderfw/setup/spider_setup_wizard.rb +1 -1
  53. data/lib/spiderfw/spider.rb +16 -3
  54. data/lib/spiderfw/templates/blocks/html.rb +2 -0
  55. data/lib/spiderfw/templates/layout.rb +10 -5
  56. data/lib/spiderfw/templates/resources/less.rb +11 -8
  57. data/lib/spiderfw/templates/template_blocks.rb +1 -1
  58. data/lib/spiderfw/test/capybara.rb +2 -1
  59. data/lib/spiderfw/test.rb +2 -1
  60. data/lib/spiderfw.rb +1 -4
  61. data/spider.gemspec +5 -2
  62. metadata +47 -18
  63. data/blueprints/home/Gemfile.disabled +0 -3
@@ -43,7 +43,12 @@ module Spider; module HTTP
43
43
 
44
44
  start = lambda{
45
45
  $SPIDER_WEB_SERVER = true
46
- require 'spiderfw'
46
+ begin
47
+ require 'spiderfw/init'
48
+ rescue Exception => exc
49
+ Spider.logger.error(exc)
50
+ return
51
+ end
47
52
  require 'spiderfw/controller/http_controller'
48
53
 
49
54
  port ||= Spider.conf.get('webserver.port')
@@ -54,11 +59,15 @@ module Spider; module HTTP
54
59
  server = Spider::HTTP.const_get(servers[server_name]).new
55
60
  ssl_server = nil
56
61
  Spider.startup
57
- if Spider.conf.get('devel.trace.extended')
58
- require 'ruby-debug'
59
- require 'spiderfw/utils/monkey/debugger'
60
- Debugger.start
61
- Debugger.post_mortem
62
+ begin
63
+ if Spider.conf.get('devel.trace.extended')
64
+ require 'ruby-debug'
65
+ require 'spiderfw/utils/monkey/debugger'
66
+ Debugger.start
67
+ Debugger.post_mortem
68
+ end
69
+ rescue Exception => exc
70
+ Spider.logger.warn "Unable to start debugger"
62
71
  end
63
72
 
64
73
  thread = Thread.new do
@@ -79,7 +88,7 @@ module Spider; module HTTP
79
88
  end
80
89
  end
81
90
  do_shutdown = lambda{
82
- Debugger.post_mortem = false
91
+ Debugger.post_mortem = false if defined?(Debugger)
83
92
  # debugger
84
93
  server.shutdown
85
94
  ssl_server.shutdown if ssl_server
@@ -95,7 +104,7 @@ module Spider; module HTTP
95
104
  ssl_thread.join if ssl_thread
96
105
  }
97
106
  if options[:daemonize]
98
- require 'spiderfw'
107
+ require 'spiderfw/init'
99
108
  require 'spiderfw/utils/fork'
100
109
  pid_file = File.join(Spider.paths[:var], 'run/server.pid')
101
110
  process_name = (options[:daemonize] == true) ? 'spider-server' : options[:daemonize]
@@ -117,9 +126,11 @@ module Spider; module HTTP
117
126
  if Spider.conf.get('webserver.respawn_on_change')
118
127
  Spider.start_loggers
119
128
  begin
120
- begin
129
+ gemfile = File.join(Spider.paths[:root], 'Gemfile')
130
+ gemfile_lock = File.join(Spider.paths[:root], 'Gemfile.lock')
131
+ if File.file?(gemfile) && File.file?(gemfile_lock)
132
+ require 'bundler'
121
133
  Bundler.require :default, Spider.runmode.to_sym
122
- rescue
123
134
  end
124
135
  spawner = Spawner.new({'spawn' => start})
125
136
  spawner.run('spawn')
@@ -132,7 +143,11 @@ module Spider; module HTTP
132
143
  unless spawner_started
133
144
  Spider.main_process_startup
134
145
  Spider.startup
135
- start.call
146
+ begin
147
+ start.call
148
+ rescue Exception => exc
149
+ Spider.logger.error(exc)
150
+ end
136
151
  end
137
152
  end
138
153
  end
@@ -40,8 +40,8 @@ module Spider; module I18n
40
40
  # FIXME: handle more efficiently
41
41
  d = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
42
42
  obj_d = d[object.wday]
43
- days = @cldr.calendar.days[options[:calendar].to_sym]
44
- months = @cldr.calendar.months[options[:calendar].to_sym]
43
+ days = @cldr.calendar.days[options[:calendar].to_sym][:format] || @cldr.calendar.days[options[:calendar].to_sym]
44
+ months = @cldr.calendar.months[options[:calendar].to_sym][:format] || @cldr.calendar.months[options[:calendar].to_sym]
45
45
  replacements = [
46
46
  [/y{1,4}/, '%Y'], # year don't use two digits year, they cause confusion [/y{1,2}/, '%y']
47
47
  [/M{5}/, months[:narrow][object.month.to_s]], [/M{4}/, months[:wide][object.month.to_s]], #month
@@ -115,9 +115,9 @@ module Spider; module I18n
115
115
  end
116
116
  end
117
117
 
118
- def day_names(format = :wide, calendar = self.default_calendar)
118
+ def day_names(format = :wide, context = :stand_alone, calendar = self.default_calendar)
119
119
  begin
120
- days = @cldr.calendar.days[calendar][format]
120
+ days = @cldr.calendar.days[calendar][format] || @cldr.calendar.days[calendar][context][format]
121
121
  return [days['sun'], days['mon'], days['tue'], days['wed'], days['thu'], days['fri'], days['sat']]
122
122
  rescue NoMethodError
123
123
  raise ArgumentError, "Calendar #{calendar} not found" unless @cldr.days[calendar]
@@ -126,10 +126,12 @@ module Spider; module I18n
126
126
 
127
127
  end
128
128
 
129
- def month_names(format = :wide, calendar = self.default_calendar)
129
+ def month_names(format = :wide, context = :stand_alone, calendar = self.default_calendar)
130
130
  months = []
131
131
  begin
132
- @cldr.calendar.months[calendar][format].each do |k, v|
132
+ # CLDR 1 doesn't have context, CLDR 2 does
133
+ months = @cldr.calendar.months[calendar][format] || @cldr.calendar.months[calendar][context][format]
134
+ months.each do |k, v|
133
135
  months[k.to_i] = v
134
136
  end
135
137
  rescue NoMethodError
@@ -1,5 +1,6 @@
1
1
  require 'gettext/tools'
2
2
  require 'spiderfw/templates/blocks/text'
3
+ require 'json'
3
4
 
4
5
  module Spider; module I18n
5
6
 
@@ -0,0 +1,2 @@
1
+ require 'spiderfw/spider'
2
+ Spider.init
@@ -957,6 +957,11 @@ module Spider; module Model
957
957
  def self.elements
958
958
  @elements
959
959
  end
960
+
961
+ # An array of non-integrated elements
962
+ def self.own_elements
963
+ elements_array.reject{ |el| el.integrated? }
964
+ end
960
965
 
961
966
  # An array of the model's Elements.
962
967
  def self.elements_array
@@ -1251,8 +1256,8 @@ module Spider; module Model
1251
1256
  self.load(values) || self.create(values)
1252
1257
  end
1253
1258
 
1254
- def self.get(values)
1255
- return self.new(values) unless Spider::Model.identity_mapper
1259
+ def self.get(values, static=false)
1260
+ return static ? self.static(values) : self.new(values) unless Spider::Model.identity_mapper
1256
1261
  values = [values] unless values.is_a?(Hash) || values.is_a?(Array)
1257
1262
  if values.is_a?(Array)
1258
1263
  vals = {}
@@ -1262,11 +1267,16 @@ module Spider; module Model
1262
1267
  values = vals
1263
1268
  end
1264
1269
  curr = Spider::Model.identity_mapper.get(self, values)
1270
+ curr.autoload = false if static
1265
1271
  return curr if curr
1266
- obj = self.new(values)
1272
+ obj = static ? self.static(values) : self.new(values)
1267
1273
  Spider::Model.identity_mapper.put(obj)
1268
1274
  obj
1269
1275
  end
1276
+
1277
+ def self.get_static(values)
1278
+ self.get(values, true)
1279
+ end
1270
1280
 
1271
1281
  def set_values(values)
1272
1282
  if (values.is_a? Hash)
@@ -144,6 +144,10 @@ module Spider; module Model
144
144
  sub.all_each_with_comparison{ |k, v, c| yield k, v, c }
145
145
  end
146
146
  end
147
+
148
+ def primary_keys_only?(model)
149
+ self.select{ |key, value| !model.elements[key] || !model.elements[key].primary_key? }.empty?
150
+ end
147
151
 
148
152
  # Returns the result of merging the condition with another one (does not modify the original condition).
149
153
  def +(condition)
@@ -595,8 +595,7 @@ module Spider; module Model; module Mappers
595
595
  el_join_info[jk[k.to_s.length+1..-1]] = jv
596
596
  end
597
597
  end
598
- if (v && model.mapper.have_references?(element.name) && v.select{ |key, value|
599
- !element.model.elements[key] || !element.model.elements[key].primary_key? }.empty?)
598
+ if v && model.mapper.have_references?(element.name) && v.primary_keys_only?(element.model)
600
599
  # 1/n <-> 1 with only primary keys
601
600
  element_cond = {:conj => 'AND', :values => [], :is_having => is_having}
602
601
  v.each_with_comparison do |el_k, el_v, el_comp|
@@ -781,20 +780,23 @@ module Spider; module Model; module Mappers
781
780
  joins = []
782
781
  el = nil
783
782
  # Spider::Logger.debug("GETTING DEEP JOIN TO #{dotted_element} (#{@model})")
783
+ cnt = 0
784
784
  parts.each do |part|
785
+ cnt += 1
785
786
  el = current_model.elements[part]
786
787
  raise "Can't find element #{part} in model #{current_model}" unless el
787
- if (el.integrated?)
788
+ next if have_references?(el) && cnt == parts.length
789
+ if el.integrated?
788
790
  joins << current_model.mapper.get_join(el.integrated_from)
789
791
  current_model = el.integrated_from.type
790
792
  el = current_model.elements[el.integrated_from_element]
791
793
  end
792
- if (el.model? && can_join?(el))
794
+ if el.model? && can_join?(el)
793
795
  joins << current_model.mapper.get_join(el)
794
796
  current_model = el.model
795
797
  end
796
798
  end
797
- while (el.integrated?)
799
+ while el.integrated? && !have_references?(el)
798
800
  joins << current_model.mapper.get_join(el.integrated_from)
799
801
  # joins << current_model.integrated_from.mapper.get_join(el.integrated_from_element)
800
802
  current_model = el.integrated_from.type
@@ -845,9 +847,8 @@ module Spider; module Model; module Mappers
845
847
  fields << [field, direction]
846
848
  else
847
849
  el_joins, el_model, el = get_deep_join(order_element)
848
- if (el.model?)
849
- # FIXME: integrated elements
850
- if el.model.storage != storage
850
+ if el.model?
851
+ if el_model.mapper.have_references?(el) || el.model.storage != storage
851
852
  el.model.primary_keys.each do |pk|
852
853
  fields << [el_model.mapper.schema.foreign_key_field(el.name, pk.name), direction]
853
854
  end
@@ -20,7 +20,6 @@ module Spider; module Model
20
20
  def initialize(model, storage)
21
21
  @model = model
22
22
  @storage = storage
23
- @raw_data = {}
24
23
  @options = {}
25
24
  @no_map_elements = {}
26
25
  @sequences = []
@@ -416,7 +415,10 @@ module Spider; module Model
416
415
 
417
416
  # Deletes an object, or objects according to a condition.
418
417
  # Will not delete with null condition (i.e. all objects) unless force is true
419
- def delete(obj_or_condition, force=false)
418
+ # Options can be:
419
+ # :keep_single_reverse: don't delete associations that have a single reverse.
420
+ # Useful when an object will be re-inserted with the same keys.
421
+ def delete(obj_or_condition, force=false, options={})
420
422
 
421
423
  def prepare_delete_condition(obj)
422
424
  condition = Condition.and
@@ -459,6 +461,7 @@ module Spider; module Model
459
461
  end
460
462
  vals << obj_vals
461
463
  assocs.each do |el|
464
+ next if el.has_single_reverse? && options[:keep_single_reverse]
462
465
  delete_element_associations(curr_obj, el)
463
466
  end
464
467
  end
@@ -580,7 +583,6 @@ module Spider; module Model
580
583
  @model.primary_keys.each{ |key| query.request[key] = true}
581
584
  expand_request(query.request, set) unless options[:no_expand_request] || !query.request.expandable?
582
585
  query = prepare_query(query, query_set)
583
- query.request.total_rows = true unless query.request.total_rows == false
584
586
  result = fetch(query)
585
587
  if !result || result.empty?
586
588
  set.each_current do |obj|
@@ -600,7 +602,6 @@ module Spider; module Model
600
602
  next unless obj
601
603
  merged_obj = merge_object(set, obj, query.request)
602
604
  merged[merged_obj.object_id] = true
603
- @raw_data[obj.object_id] = row
604
605
  end
605
606
  query.request.keys.each do |k, v|
606
607
  set.element_loaded(k) if have_references?(k)
@@ -932,8 +933,7 @@ module Spider; module Model
932
933
  next if k.is_a?(Spider::QueryFuncs::Function)
933
934
  next unless element = model.elements[k]
934
935
  changed_v = false
935
- if element.type < Spider::DataType && !v.is_a?(element.type)
936
- condition.delete(k)
936
+ if element.type < Spider::DataType && !v.is_a?(element.type) && element.type.force_wrap?
937
937
  begin
938
938
  v = element.type.from_value(v)
939
939
  changed_v = true
@@ -944,8 +944,10 @@ module Spider; module Model
944
944
  v = DateTime.parse(v)
945
945
  changed_v = true
946
946
  elsif element.model? && v.is_a?(Spider::Model::Condition)
947
- v = element.mapper.preprocess_condition(v)
948
- changed_v = true
947
+ unless v.primary_keys_only?(element.model)
948
+ v = element.mapper.preprocess_condition(v)
949
+ changed_v = true
950
+ end
949
951
  end
950
952
  if element.integrated?
951
953
  condition.delete(k)
@@ -953,15 +955,21 @@ module Spider; module Model
953
955
  integrated_from_element = element.integrated_from_element
954
956
  sub = condition.get_deep_obj
955
957
  sub.set(integrated_from_element, c, v)
956
- condition[integrated_from.name] = integrated_from.model.mapper.preprocess_condition(sub)
958
+ unless sub.primary_keys_only?(integrated_from.model)
959
+ sub = integrated_from.model.mapper.preprocess_condition(sub)
960
+ end
961
+ condition[integrated_from.name] = sub
957
962
  elsif element.junction? && !v.is_a?(BaseModel) && !v.is_a?(Hash) && !v.nil? # conditions on junction id don't make sense
958
963
  condition.delete(k)
959
- condition.set("#{k}.#{element.attributes[:junction_their_element]}", c, v)
964
+ sub = condition.get_deep_obj
965
+ sub.set(element.attributes[:junction_their_element], c, v)
966
+ condition[k] = element.model.mapper.preprocess_condition(sub)
960
967
  elsif changed_v
961
968
  condition.delete(k)
962
969
  condition.set(k, c, v)
963
970
  end
964
971
  end
972
+ condition
965
973
  end
966
974
 
967
975
  basic_preprocess(condition)
@@ -0,0 +1,20 @@
1
+ module Spider; module Migrations
2
+
3
+ class DropTable < IrreversibleMigration
4
+
5
+ def initialize(model, options={})
6
+ @model = model
7
+ @options = options
8
+ end
9
+
10
+ def run
11
+ table = @options[:table_name]
12
+ if !table
13
+ table = @model.mapper.schema.table.name
14
+ end
15
+ @model.mapper.storage.drop_table(table)
16
+ end
17
+
18
+ end
19
+
20
+ end; end
@@ -3,28 +3,33 @@ module Spider; module Migrations
3
3
  class Replace < Migration
4
4
 
5
5
  def initialize(model, element, values)
6
- @model = model
6
+ @models = model
7
+ @models = [@models] unless @models.is_a?(Enumerable)
7
8
  @element = element
8
9
  @values = values
9
10
  end
10
11
 
11
12
  def run
12
- field = @model.mapper.schema.field(@model.get_element(@element).name)
13
- table = @model.mapper.schema.table
14
- raise "Table #{table} does not have a field #{field}" unless field
15
- @values.each do |from, to|
16
- save = {
17
- :table => table,
18
- :values => {field => to},
19
- :condition => {:values => [[field, '=', from]]}
20
- }
21
- sql, bind_vars = @model.storage.sql_update(save)
22
- return @model.storage.execute(sql, *bind_vars)
13
+ @models.each do |model|
14
+ field = model.mapper.schema.field(model.get_element(@element).name)
15
+ table = model.mapper.schema.table
16
+ raise "Table #{table} does not have a field #{field}" unless field
17
+ @values.each do |from, to|
18
+ save = {
19
+ :table => table,
20
+ :values => {field => to},
21
+ :condition => {:values => [[field, '=', from]]}
22
+ }
23
+ sql, bind_vars = model.storage.sql_update(save)
24
+ model.storage.execute(sql, *bind_vars)
25
+ end
23
26
  end
24
27
  end
25
28
 
26
29
  def undo
27
- Replace.new(@model, @element, @values.invert).run
30
+ @models.each do |model|
31
+ Replace.new(model, @element, @values.invert).run
32
+ end
28
33
  end
29
34
 
30
35
  end
@@ -2,6 +2,7 @@ require 'spiderfw/model/migrations/migration'
2
2
  require 'spiderfw/model/migrations/irreversible_migration'
3
3
  require 'spiderfw/model/migrations/replace'
4
4
  require 'spiderfw/model/migrations/drop_element'
5
+ require 'spiderfw/model/migrations/drop_table'
5
6
 
6
7
  module Spider
7
8
 
@@ -14,6 +15,10 @@ module Spider
14
15
  def self.drop_element!(model, element, options={})
15
16
  Spider::Migrations::DropElement.new(model, element, options={})
16
17
  end
18
+
19
+ def self.drop_table!(model, options={})
20
+ Spider::Migrations::DropTable.new(model, element, options={})
21
+ end
17
22
 
18
23
 
19
24
  end
@@ -165,7 +165,7 @@ module Spider; module Model
165
165
  cnt += 1
166
166
  break if sub == self
167
167
  end
168
- cnt = nil if cnt = 0
168
+ cnt = nil if cnt == 0
169
169
  cnt
170
170
  end
171
171
 
@@ -230,6 +230,7 @@ module Spider
230
230
  end
231
231
  # Ruby 1.9: steps are not needed with ordered hashes
232
232
  data = [data] unless data.is_a?(Array)
233
+ loaded = []
233
234
  data.each do |step|
234
235
  step.each do |mod_name, mod_data|
235
236
  mod = const_get_full(mod_name)
@@ -248,9 +249,11 @@ module Spider
248
249
  end
249
250
  obj = mod.new(h)
250
251
  obj.insert
252
+ loaded << obj
251
253
  end
252
254
  end
253
255
  end
256
+ loaded
254
257
  end
255
258
 
256
259
  # Generic Model error.
@@ -67,7 +67,7 @@ module Spider; module Model; module Storage; module Db
67
67
  return nil unless curr[:last_executed]
68
68
  q = curr[:last_query].clone
69
69
  unless (q[:offset] || q[:limit])
70
- return curr[:last_result] ? curr[:last_result].length : nil
70
+ return curr[:last_result_length] ? curr[:last_result_length] : nil
71
71
  end
72
72
  q.delete(:offset); q.delete(:limit)
73
73
  q[:query_type] = :count
@@ -121,7 +121,7 @@ module Spider; module Model; module Storage; module Db
121
121
  return nil unless curr[:last_query]
122
122
  q = curr[:last_query]
123
123
  unless (q[:offset] || q[:limit])
124
- return curr[:last_result] ? curr[:last_result].length : nil
124
+ return curr[:last_result_length] ? curr[:last_result_length] : nil
125
125
  end
126
126
  q[:offset] = q[:limit] = nil
127
127
  q[:keys] = ["COUNT(*) AS N"]
@@ -257,8 +257,8 @@ module Spider; module Model; module Storage; module Db; module Connectors
257
257
  end
258
258
  if (res)
259
259
  unless block_given?
260
+ curr[:last_result_length] = result.length
260
261
  result.extend(StorageResult)
261
- curr[:last_result] = result
262
262
  return result
263
263
  end
264
264
  else
@@ -125,8 +125,8 @@ module Spider; module Model; module Storage; module Db; module Connectors
125
125
  end
126
126
  if (have_result)
127
127
  unless block_given?
128
+ curr[:last_result_length] = result.length
128
129
  result.extend(StorageResult)
129
- curr[:last_result] = result
130
130
  return result
131
131
  end
132
132
  else
@@ -267,7 +267,10 @@ module Spider; module Model; module Storage; module Db
267
267
  attr_reader :expression
268
268
 
269
269
  def initialize(table, name, type, attributes={})
270
- super
270
+ @table = table
271
+ @name = name.to_s
272
+ @type = type
273
+ @attributes = attributes
271
274
  @expression = attributes[:expression]
272
275
  end
273
276
 
@@ -6,7 +6,7 @@ module Spider; module Model; module Storage; module Db; module Dialects
6
6
  return nil unless @last_executed
7
7
  q = @last_query.clone
8
8
  unless (q[:offset] || q[:limit])
9
- return @last_result ? @last_result.length : nil
9
+ return @last_result_length ? @last_result_length : nil
10
10
  end
11
11
  q.delete(:offset); q.delete(:limit); q[:order]= []
12
12
  q[:query_type] = :count
@@ -4,6 +4,10 @@ require 'fileutils'
4
4
  module Spider
5
5
 
6
6
  class AppManager
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ end
7
11
 
8
12
  def self.installed?(app)
9
13
  require 'spiderfw/home'
@@ -269,7 +273,8 @@ module Spider
269
273
  require 'rubygems/package'
270
274
  client = AppServerClient.new(spec.app_server)
271
275
  print _("Fetching %s from server... ") % spec.app_id
272
- tmp_path = client.fetch_app(spec.app_id)
276
+ options[:branch] ||= 'master'
277
+ tmp_path = client.fetch_app(spec.app_id, options[:branch])
273
278
  Spider.output _("Fetched.")
274
279
  dest = File.join(@home_path, "apps/#{spec.app_id}")
275
280
  FileUtils.mkdir_p(dest)
@@ -307,8 +312,9 @@ module Spider
307
312
  app_path = File.join(@home_path, "apps", spec.id)
308
313
  app_repo = Git.open(app_path)
309
314
  Spider.output _("Updating %s from %s") % [spec.app_id, spec.git_repo]
315
+ options[:branch] ||= 'master'
310
316
  Dir.chdir(app_path) do
311
- app_repo.branch('master').checkout
317
+ app_repo.branch(options[:branch]).checkout
312
318
  end
313
319
  response = err = nil
314
320
  Dir.chdir(app_path) do
@@ -321,7 +327,7 @@ module Spider
321
327
  end
322
328
  Dir.chdir(app_path) do
323
329
  app_repo.reset('HEAD', :hard => true)
324
- app_repo.branch('master').checkout
330
+ app_repo.branch(options[:branch]).checkout
325
331
  end
326
332
 
327
333
  home_repo.add("apps/#{spec.id}")
@@ -401,11 +407,13 @@ module Spider
401
407
  end
402
408
  end
403
409
  done_tasks = []
410
+
404
411
 
405
412
  tasks.each do |task|
406
413
  Spider.output _("Running setup task #{path+'/'+task}...")
407
414
  t = Spider::SetupTask.load("#{path}/#{task}")
408
415
  t.app = app
416
+ raise "Can't run interactive task" if t.interactive? && !@options[:interactive]
409
417
  begin
410
418
  done_tasks << t
411
419
  t.do_sync
@@ -12,8 +12,8 @@ module Spider
12
12
  @url = url
13
13
  end
14
14
 
15
- def specs
16
- load_specs unless @specs
15
+ def specs(branch=nil)
16
+ load_specs(branch) unless @specs
17
17
  @specs
18
18
  end
19
19
 
@@ -34,29 +34,35 @@ module Spider
34
34
  end
35
35
 
36
36
  def load_specs
37
- result = http_get(@url+'/list.json')
37
+ url = @url+'/list.json'
38
+ result = http_get(url)
38
39
  list = JSON.parse(result)
39
40
  @specs = list.map{ |app| Spider::App::AppSpec.parse_hash(app) }
40
41
  end
41
42
 
42
43
  def get_specs(app_ids)
43
44
  app_ids = [app_ids] unless app_ids.is_a?(Array)
44
- result = http_get(@url+"/list/#{app_ids.join('+')}.json")
45
+ url = @url+"/list/#{app_ids.join('+')}.json"
46
+ result = http_get(url)
45
47
  JSON.parse(result).map{ |app| Spider::App::AppSpec.parse_hash(app) }
46
48
  end
47
49
 
48
50
  def get_deps(app_ids, options={})
49
51
  app_ids = [app_ids] unless app_ids.is_a?(Array)
50
52
  url = "#{@url}/deps/#{app_ids.join('+')}.json"
51
- url += "?no_optional=true" if options[:no_optional]
53
+ params = []
54
+ params << 'no_optional=true' if options[:no_optional]
55
+ url += '?'+params.join('&') unless params.empty?
52
56
  result = http_get(url)
53
57
  JSON.parse(result).map{ |app| Spider::App::AppSpec.parse_hash(app) }
54
58
  end
55
59
 
56
- def fetch_app(app_id)
60
+ def fetch_app(app_id, branch=nil)
57
61
  tmp = Tempfile.new("spider-app-archive")
58
62
  tmp.binmode
59
- res = http_get(@url+"/pack/#{app_id}")
63
+ url = @url+"/pack/#{app_id}"
64
+ url += "?branch=#{branch}" if branch
65
+ res = http_get(url)
60
66
  tmp << res
61
67
  tmp.flush
62
68
  tmp.path