gina-conveyor 0.0.2

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 (87) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +49 -0
  4. data/LICENSE +25 -0
  5. data/README.md +24 -0
  6. data/Rakefile +2 -0
  7. data/bin/conveyor +4 -0
  8. data/conveyor.gemspec +30 -0
  9. data/lib/conveyor/belt.rb +59 -0
  10. data/lib/conveyor/foreman.rb +182 -0
  11. data/lib/conveyor/input/commands.rb +21 -0
  12. data/lib/conveyor/input/console.rb +39 -0
  13. data/lib/conveyor/input.rb +12 -0
  14. data/lib/conveyor/job_state.rb +2 -0
  15. data/lib/conveyor/output/channel.rb +22 -0
  16. data/lib/conveyor/output/console.rb +39 -0
  17. data/lib/conveyor/output/email.rb +36 -0
  18. data/lib/conveyor/output/logfile.rb +38 -0
  19. data/lib/conveyor/output.rb +76 -0
  20. data/lib/conveyor/queue.rb +80 -0
  21. data/lib/conveyor/status.rb +29 -0
  22. data/lib/conveyor/version.rb +3 -0
  23. data/lib/conveyor/websocket.rb +37 -0
  24. data/lib/conveyor/worker.rb +120 -0
  25. data/lib/conveyor/workers/syntax.rb +127 -0
  26. data/lib/conveyor.rb +62 -0
  27. data/webviewer/.gitignore +15 -0
  28. data/webviewer/Gemfile +39 -0
  29. data/webviewer/Gemfile.lock +119 -0
  30. data/webviewer/README.rdoc +261 -0
  31. data/webviewer/Rakefile +7 -0
  32. data/webviewer/app/assets/images/rails.png +0 -0
  33. data/webviewer/app/assets/javascripts/application.js +16 -0
  34. data/webviewer/app/assets/javascripts/welcome.js.coffee +61 -0
  35. data/webviewer/app/assets/stylesheets/application.css.scss +6 -0
  36. data/webviewer/app/assets/stylesheets/welcome.css.scss +3 -0
  37. data/webviewer/app/controllers/application_controller.rb +3 -0
  38. data/webviewer/app/controllers/welcome_controller.rb +4 -0
  39. data/webviewer/app/helpers/application_helper.rb +2 -0
  40. data/webviewer/app/helpers/welcome_helper.rb +2 -0
  41. data/webviewer/app/mailers/.gitkeep +0 -0
  42. data/webviewer/app/models/.gitkeep +0 -0
  43. data/webviewer/app/views/layouts/application.html.haml +14 -0
  44. data/webviewer/app/views/welcome/index.html.haml +3 -0
  45. data/webviewer/config/application.rb +59 -0
  46. data/webviewer/config/boot.rb +6 -0
  47. data/webviewer/config/database.yml +25 -0
  48. data/webviewer/config/environment.rb +5 -0
  49. data/webviewer/config/environments/development.rb +37 -0
  50. data/webviewer/config/environments/production.rb +67 -0
  51. data/webviewer/config/environments/test.rb +37 -0
  52. data/webviewer/config/initializers/backtrace_silencers.rb +7 -0
  53. data/webviewer/config/initializers/inflections.rb +15 -0
  54. data/webviewer/config/initializers/mime_types.rb +5 -0
  55. data/webviewer/config/initializers/secret_token.rb +7 -0
  56. data/webviewer/config/initializers/session_store.rb +8 -0
  57. data/webviewer/config/initializers/wrap_parameters.rb +14 -0
  58. data/webviewer/config/locales/en.yml +5 -0
  59. data/webviewer/config/routes.rb +58 -0
  60. data/webviewer/config.ru +4 -0
  61. data/webviewer/db/seeds.rb +7 -0
  62. data/webviewer/doc/README_FOR_APP +2 -0
  63. data/webviewer/lib/assets/.gitkeep +0 -0
  64. data/webviewer/lib/tasks/.gitkeep +0 -0
  65. data/webviewer/log/.gitkeep +0 -0
  66. data/webviewer/public/404.html +26 -0
  67. data/webviewer/public/422.html +26 -0
  68. data/webviewer/public/500.html +25 -0
  69. data/webviewer/public/favicon.ico +0 -0
  70. data/webviewer/public/robots.txt +5 -0
  71. data/webviewer/script/rails +6 -0
  72. data/webviewer/test/fixtures/.gitkeep +0 -0
  73. data/webviewer/test/functional/.gitkeep +0 -0
  74. data/webviewer/test/functional/welcome_controller_test.rb +7 -0
  75. data/webviewer/test/integration/.gitkeep +0 -0
  76. data/webviewer/test/performance/browsing_test.rb +12 -0
  77. data/webviewer/test/test_helper.rb +13 -0
  78. data/webviewer/test/unit/.gitkeep +0 -0
  79. data/webviewer/test/unit/helpers/welcome_helper_test.rb +4 -0
  80. data/webviewer/vendor/assets/javascripts/.gitkeep +0 -0
  81. data/webviewer/vendor/assets/stylesheets/.gitkeep +0 -0
  82. data/webviewer/vendor/plugins/.gitkeep +0 -0
  83. data/worker-examples/barrow_webcam.worker.disabled +19 -0
  84. data/worker-examples/barrow_webcam.worker.example +16 -0
  85. data/worker-examples/conveyor.worker.example +5 -0
  86. data/worker-examples/devel.worker +17 -0
  87. metadata +260 -0
@@ -0,0 +1,80 @@
1
+ module Conveyor
2
+ class Queue
3
+ def initialize
4
+ @mutex = Mutex.new
5
+ @queue = []
6
+ end
7
+
8
+ def count
9
+ @queue.count
10
+ end
11
+
12
+ def touch(file)
13
+ push(file)
14
+ end
15
+
16
+ def push(file)
17
+ @mutex.synchronize do
18
+ i = @queue.find_index { |j| j[:file] == file }
19
+ if i.nil?
20
+ @queue.push({ :file => file, :updated_at => Time.now })
21
+ else
22
+ @queue[i][:updated_at] = Time.now
23
+ end
24
+ @queue.sort! { |x,y| x[:updated_at] <=> y[:updated_at] }
25
+ end
26
+ end
27
+
28
+ def reserve(file = nil)
29
+ @mutex.synchronize do
30
+ # find first non-reserved job
31
+ i = @queue.find_index { |j| !j[:reserved] }
32
+ @queue[i][:reserved] = true unless i.nil?
33
+ @queue[i] unless i.nil?
34
+ end
35
+ end
36
+
37
+ def unreserve(file)
38
+ @mutex.synchronize do
39
+ i = find_index(file)
40
+ @queue[i][:reserved] = false unless i.nil?
41
+ @queue[i] unless i.nil?
42
+ end
43
+ end
44
+
45
+ def find_index(file = nil)
46
+ if file.nil?
47
+ @queue.empty? ? nil : 0
48
+ else
49
+ @queue.find_index { |j| j[:file] == file }
50
+ end
51
+ end
52
+
53
+ def find(file)
54
+ i = find_index(file)
55
+ @queue[i] unless i.nil?
56
+ end
57
+
58
+ def unpop(job)
59
+ @mutex.synchronize do
60
+ unless find(job[:file])
61
+ @queue.push(job)
62
+ @queue.sort! { |x,y| x[:updated_at] <=> y[:updated_at] }
63
+ end
64
+ end
65
+ end
66
+
67
+ def pop(file = nil)
68
+ if file.nil?
69
+ @mutex.synchronize do
70
+ @queue.shift
71
+ end
72
+ else
73
+ @mutex.synchronize do
74
+ j = find(file)
75
+ @queue.delete(j)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,29 @@
1
+ module Conveyor
2
+ class Status
3
+ attr_reader :success
4
+ attr_accessor :errors
5
+ attr_reader :path
6
+
7
+ def initialize(path = nil)
8
+ reset!(path)
9
+ end
10
+
11
+ def reset!(path = nil)
12
+ @path = path
13
+ @success = true
14
+ @errors = []
15
+ end
16
+
17
+ def fail!(v = false)
18
+ @success &= v
19
+ end
20
+
21
+ def success!(v=true)
22
+ @success &= v
23
+ end
24
+
25
+ def success?
26
+ @success
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Conveyor
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,37 @@
1
+ module Conveyor
2
+ class Websocket
3
+ class << self
4
+ def start
5
+ if config[:disable]
6
+ fm.info "Websocket disabled"
7
+ return
8
+ end
9
+
10
+ fm.info "Starting websocket on #{config[:host]}:#{config[:port]}", :color => :green
11
+
12
+ EventMachine::start_server(config[:host], config[:port],
13
+ EventMachine::WebSocket::Connection, config) do |ws|
14
+ ws.onopen {
15
+ sid = fm.channel.subscribe { |type,msg| ws.send msg }
16
+ fm.info "#{sid} connected to websocket!"
17
+ ws.onclose {
18
+ fm.channel.unsubscribe(sid)
19
+ }
20
+ }
21
+ end
22
+ end
23
+
24
+ def stop
25
+ # EM::WebSocket.stop unless config[:disable]
26
+ end
27
+
28
+ def fm
29
+ Conveyor::Foreman.instance
30
+ end
31
+
32
+ def config
33
+ fm.config[:websocket]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,120 @@
1
+ require 'rubygems'
2
+ require 'active_support/core_ext'
3
+ require 'open3'
4
+ require 'conveyor/workers/syntax'
5
+
6
+ module Conveyor
7
+ class Worker
8
+ include Conveyor::Output
9
+ include Conveyor::Workers::Syntax
10
+
11
+ attr_accessor :filename
12
+ attr_reader :status
13
+ attr_reader :worker_def
14
+
15
+ def initialize(file, worker_def, log = MSGLVLS[:debug])
16
+ @filename = file
17
+ @loglvl = log
18
+ @worker_def = worker_def
19
+ @notify = []
20
+ # @glob = escape_glob(glob)
21
+ end
22
+
23
+ # Return name to be used for logging purposes
24
+ def name(value=nil)
25
+ @name = value unless value.nil?
26
+ @name ||= File.basename(worker_def)
27
+ @name
28
+ end
29
+
30
+ # Default log file to be based on worker def name
31
+ def logfile
32
+ dir = File.dirname(worker_def)
33
+ File.expand_path(File.basename(worker_def, '.worker') + '.log', dir)
34
+ end
35
+
36
+ # Catch any calls to error and set the status fail flags
37
+ def error(*msg)
38
+ opts = msg.extract_options!
39
+ unless msg.flatten.empty?
40
+ @status.fail!
41
+ msg.unshift("Error encountered in #{worker_def}")
42
+ super(*msg, opts)
43
+ end
44
+ @status.success?
45
+ end
46
+
47
+ # Start the worker
48
+ def start
49
+ @status = Conveyor::Status.new(@filename)
50
+ info "Starting #{@filename}", :color => :green
51
+ @start = Time.now
52
+ begin
53
+ instance_eval(File.read(@worker_def), worker_def)
54
+ ensure
55
+ @elapsed = "%0.2f"%(Time.now - @start)
56
+
57
+ #Check status and send any errors we collected
58
+ if @status.success?
59
+ info "Completed #{@filename}, #{@elapsed}s elapsed", :color => :green
60
+ else
61
+ error "Error(s) encountered in #{@filename}", :color => :red
62
+ end
63
+ send_notifications
64
+ end
65
+ end
66
+
67
+ protected
68
+
69
+ def create_dirs_for_cmd(src, dest)
70
+ if src.is_a?(Array) || Array.wrap(src).count > 1 || dest.last == ?/
71
+ mkdir(dest)
72
+ else
73
+ mkdir(File.dirname(dest))
74
+ end
75
+ end
76
+
77
+ def verified_cmd(cmd, src, dest, &block)
78
+ create_dirs_for_cmd(src, dest)
79
+ dest = File.expand_path(dest)
80
+
81
+ Array.wrap(src).each do |s|
82
+ run "#{cmd} #{s} #{dest}"
83
+ sync
84
+
85
+ if block_given?
86
+ result = yield(s, dest)
87
+ @status.fail! unless result
88
+ end
89
+ end
90
+ end
91
+
92
+ def verified_move(src, dest)
93
+ verified_cmd(:mv, src, dest) do |src,dest|
94
+ verify_move(src,dest)
95
+ end
96
+ end
97
+
98
+ def verified_copy(src, dest)
99
+ verified_cmd(:cp, src, dest) do |src,dest|
100
+ verify_copy(src,dest)
101
+ end
102
+ end
103
+
104
+ def verify_copy(src, dest)
105
+ if File.directory? dest
106
+ File.exists?(File.join(dest, File.basename(src)))
107
+ else
108
+ File.exists?(dest)
109
+ end
110
+ end
111
+
112
+ def verify_move(src, dest)
113
+ if File.directory? dest
114
+ File.exists?(File.join(dest, File.basename(src))) && !File.exists?(src)
115
+ else
116
+ File.exists?(dest) && !File.exists?(src)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,127 @@
1
+ module Conveyor
2
+ module Workers
3
+ module Syntax
4
+
5
+ # Will return a string of any method returned that isn't handled
6
+ # ex: match extension txt => match(extension("foo"))
7
+ def method_missing(method, value = nil)
8
+ return method.to_s
9
+ end
10
+
11
+ # Returns a recursive file glob string for the passed in string
12
+ def file(glob)
13
+ "**/#{glob}"
14
+ end
15
+
16
+ # Returns an extension glob string for passed in string
17
+ def extension(glob)
18
+ "*.#{glob}"
19
+ end
20
+
21
+ # Returns a glob string that will match any file
22
+ def any
23
+ '*'
24
+ end
25
+
26
+ # Returns a list of files that have the same basename but different extension
27
+ # in the same directory
28
+ def like(name)
29
+ dir = File.dirname(name)
30
+ Dir.glob(File.join(dir, File.basename(name, '.*') + '.*'))
31
+ end
32
+
33
+ # Returns the filename of the file that triggered the job
34
+ def filename
35
+ @filename
36
+ end
37
+
38
+ # Which directories to watch for file change events.
39
+ def watch(*args, &block)
40
+ yield
41
+ end
42
+
43
+ # Match string/glob for the files that should trigger file change events
44
+ def match(glob, &block)
45
+ yield @filename
46
+ end
47
+
48
+ # Run the system sync command
49
+ def sync
50
+ run 'sync', :quiet => true
51
+ end
52
+
53
+ # Change current working directory, optionally takes a block
54
+ # NOTE: Consider removing this as it can cause problems with threaded workers
55
+ def chdir(dir, &block)
56
+ Dir.chdir(File.expand_path(dir), &block)
57
+ end
58
+
59
+ # Run the system command, and make sure that any errors are caught and returne
60
+ # up the status change
61
+ def run(*cmd)
62
+ opts = cmd.extract_options!
63
+ begin
64
+ info cmd.join(' ') unless opts[:quiet]
65
+ output,err,thr = Open3.capture3(Array.wrap(cmd).join(' '))
66
+ info output.chomp unless output.chomp.length == 0
67
+ if thr.success?
68
+ if err.chomp.length > 0
69
+ warning "Error output recieved, but no error code recieved"
70
+ warning err.chomp
71
+ end
72
+ else
73
+ error "Error running: `#{cmd.join(' ')}`", err.chomp
74
+ @status.fail!
75
+ end
76
+
77
+ return thr.success?
78
+ rescue => e
79
+ error e.class, e.message, e.backtrace.join("\n")
80
+ end
81
+ end
82
+
83
+ # Deletes passed in files
84
+ def delete(files)
85
+ # sync before we delete
86
+ sync
87
+ Array.wrap(files).each do |f|
88
+ info "removing #{f}"
89
+ FileUtils.rm(f)
90
+ error "#{f} wasn't removed" if File.exists?(f)
91
+ end
92
+ end
93
+
94
+ # Create a new directory
95
+ def mkdir(dir)
96
+ FileUtils.mkdir_p(File.expand_path(dir))
97
+ @status.fail! unless File.exists?(File.expand_path(dir))
98
+ end
99
+
100
+ # Copy files to destination
101
+ def copy(src = [], dest = nil)
102
+ destination = dest unless dest.nil?
103
+ source = src unless src.empty?
104
+
105
+ if source && destination
106
+ verified_copy(source, destination)
107
+ end
108
+ end
109
+
110
+ # Move files to destination
111
+ def move(src=[], dest = nil)
112
+ destination = dest unless dest.nil?
113
+ source = src unless src.empty?
114
+
115
+ if source && destination
116
+ verified_move(source, destination)
117
+ end
118
+ end
119
+
120
+ # Scp files to destination
121
+ # See: man scp
122
+ def scp(src, dest)
123
+ run "scp #{Array.wrap(src).join(' ')} #{dest}"
124
+ end
125
+ end
126
+ end
127
+ end
data/lib/conveyor.rb ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
3
+
4
+ require 'rubygems'
5
+ require 'active_support/core_ext'
6
+ require 'singleton'
7
+ require 'listen'
8
+ require 'yaml'
9
+ require 'rainbow'
10
+ require 'rb-readline'
11
+ require 'fileutils'
12
+ require 'eventmachine'
13
+ require 'em-websocket'
14
+ require "conveyor/version"
15
+
16
+ module Conveyor
17
+ autoload :Output, 'conveyor/output'
18
+ autoload :Foreman, 'conveyor/foreman'
19
+ autoload :Belt, 'conveyor/belt'
20
+ autoload :Worker, 'conveyor/worker'
21
+ autoload :Status, 'conveyor/status'
22
+ autoload :Input, 'conveyor/input'
23
+ autoload :Queue, 'conveyor/queue'
24
+ autoload :Websocket, 'conveyor/websocket'
25
+
26
+ def self.stop
27
+ Foreman.instance.stop!
28
+ EventMachine.stop
29
+ exit
30
+ end
31
+
32
+ def self.fm
33
+ Foreman.instance
34
+ end
35
+
36
+ def self.start
37
+ EventMachine.run do
38
+ trap("TERM") { stop }
39
+ trap("INT") { stop }
40
+
41
+ EventMachine.threadpool_size = fm.config[:threadpool] || 20
42
+
43
+ fm.info "Starting Conveyor v#{Conveyor::VERSION}"
44
+ fm.start
45
+ fm.info "Waiting for files", :color => :green
46
+ fm.info "Press CTRL-C to stop"
47
+ Conveyor::Websocket.start
48
+
49
+ EventMachine::PeriodicTimer.new(1) do
50
+ fm.output_status
51
+ end
52
+
53
+ EventMachine::PeriodicTimer.new(1) do
54
+ fm.check
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def watch(*args, &block)
61
+ fm.watch(*args, &block)
62
+ end
@@ -0,0 +1,15 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
data/webviewer/Gemfile ADDED
@@ -0,0 +1,39 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '3.2.3'
4
+
5
+ # Bundle edge Rails instead:
6
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
+
8
+ gem 'sqlite3'
9
+ gem 'haml'
10
+ gem 'bootstrap-sass', '~> 2.0.2'
11
+
12
+ # Gems used only for assets and not required
13
+ # in production environments by default.
14
+ group :assets do
15
+ gem 'sass-rails', '~> 3.2.3'
16
+ gem 'coffee-rails', '~> 3.2.1'
17
+
18
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19
+ gem 'therubyracer', :platform => :ruby
20
+
21
+ gem 'uglifier', '>= 1.0.3'
22
+ end
23
+
24
+ gem 'jquery-rails'
25
+
26
+ # To use ActiveModel has_secure_password
27
+ # gem 'bcrypt-ruby', '~> 3.0.0'
28
+
29
+ # To use Jbuilder templates for JSON
30
+ # gem 'jbuilder'
31
+
32
+ # Use unicorn as the app server
33
+ # gem 'unicorn'
34
+
35
+ # Deploy with Capistrano
36
+ # gem 'capistrano'
37
+
38
+ # To use debugger
39
+ # gem 'ruby-debug19', :require => 'ruby-debug'
@@ -0,0 +1,119 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ actionmailer (3.2.3)
5
+ actionpack (= 3.2.3)
6
+ mail (~> 2.4.4)
7
+ actionpack (3.2.3)
8
+ activemodel (= 3.2.3)
9
+ activesupport (= 3.2.3)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ journey (~> 1.0.1)
13
+ rack (~> 1.4.0)
14
+ rack-cache (~> 1.2)
15
+ rack-test (~> 0.6.1)
16
+ sprockets (~> 2.1.2)
17
+ activemodel (3.2.3)
18
+ activesupport (= 3.2.3)
19
+ builder (~> 3.0.0)
20
+ activerecord (3.2.3)
21
+ activemodel (= 3.2.3)
22
+ activesupport (= 3.2.3)
23
+ arel (~> 3.0.2)
24
+ tzinfo (~> 0.3.29)
25
+ activeresource (3.2.3)
26
+ activemodel (= 3.2.3)
27
+ activesupport (= 3.2.3)
28
+ activesupport (3.2.3)
29
+ i18n (~> 0.6)
30
+ multi_json (~> 1.0)
31
+ arel (3.0.2)
32
+ bootstrap-sass (2.0.2)
33
+ builder (3.0.0)
34
+ coffee-rails (3.2.2)
35
+ coffee-script (>= 2.2.0)
36
+ railties (~> 3.2.0)
37
+ coffee-script (2.2.0)
38
+ coffee-script-source
39
+ execjs
40
+ coffee-script-source (1.3.1)
41
+ erubis (2.7.0)
42
+ execjs (1.3.1)
43
+ multi_json (~> 1.0)
44
+ haml (3.1.4)
45
+ hike (1.2.1)
46
+ i18n (0.6.0)
47
+ journey (1.0.3)
48
+ jquery-rails (2.0.2)
49
+ railties (>= 3.2.0, < 5.0)
50
+ thor (~> 0.14)
51
+ json (1.7.0)
52
+ libv8 (3.3.10.4)
53
+ mail (2.4.4)
54
+ i18n (>= 0.4.0)
55
+ mime-types (~> 1.16)
56
+ treetop (~> 1.4.8)
57
+ mime-types (1.18)
58
+ multi_json (1.3.4)
59
+ polyglot (0.3.3)
60
+ rack (1.4.1)
61
+ rack-cache (1.2)
62
+ rack (>= 0.4)
63
+ rack-ssl (1.3.2)
64
+ rack
65
+ rack-test (0.6.1)
66
+ rack (>= 1.0)
67
+ rails (3.2.3)
68
+ actionmailer (= 3.2.3)
69
+ actionpack (= 3.2.3)
70
+ activerecord (= 3.2.3)
71
+ activeresource (= 3.2.3)
72
+ activesupport (= 3.2.3)
73
+ bundler (~> 1.0)
74
+ railties (= 3.2.3)
75
+ railties (3.2.3)
76
+ actionpack (= 3.2.3)
77
+ activesupport (= 3.2.3)
78
+ rack-ssl (~> 1.3.2)
79
+ rake (>= 0.8.7)
80
+ rdoc (~> 3.4)
81
+ thor (~> 0.14.6)
82
+ rake (0.9.2.2)
83
+ rdoc (3.12)
84
+ json (~> 1.4)
85
+ sass (3.1.16)
86
+ sass-rails (3.2.5)
87
+ railties (~> 3.2.0)
88
+ sass (>= 3.1.10)
89
+ tilt (~> 1.3)
90
+ sprockets (2.1.3)
91
+ hike (~> 1.2)
92
+ rack (~> 1.0)
93
+ tilt (~> 1.1, != 1.3.0)
94
+ sqlite3 (1.3.6)
95
+ therubyracer (0.10.1)
96
+ libv8 (~> 3.3.10)
97
+ thor (0.14.6)
98
+ tilt (1.3.3)
99
+ treetop (1.4.10)
100
+ polyglot
101
+ polyglot (>= 0.3.1)
102
+ tzinfo (0.3.33)
103
+ uglifier (1.2.4)
104
+ execjs (>= 0.3.0)
105
+ multi_json (>= 1.0.2)
106
+
107
+ PLATFORMS
108
+ ruby
109
+
110
+ DEPENDENCIES
111
+ bootstrap-sass (~> 2.0.2)
112
+ coffee-rails (~> 3.2.1)
113
+ haml
114
+ jquery-rails
115
+ rails (= 3.2.3)
116
+ sass-rails (~> 3.2.3)
117
+ sqlite3
118
+ therubyracer
119
+ uglifier (>= 1.0.3)