spin 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/spin +120 -0
- metadata +71 -0
data/bin/spin
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Spin will speed up your autotest(ish) workflow for Rails.
|
4
|
+
|
5
|
+
# Spin preloads your Rails environment for testing, so you don't load the same code over and over and over... Spin works best with an autotest(ish) workflow.
|
6
|
+
|
7
|
+
require 'socket'
|
8
|
+
# This brings in `Dir.tmpdir`
|
9
|
+
require 'tempfile'
|
10
|
+
# This lets us hash the parameters we want to include in the filename
|
11
|
+
# without having to worry about subdirectories, special chars, etc.
|
12
|
+
require 'digest/md5'
|
13
|
+
# So we can tell users how much time they're saving by preloading their
|
14
|
+
# environment.
|
15
|
+
require 'benchmark'
|
16
|
+
|
17
|
+
def usage(stream = $stderr)
|
18
|
+
stream.puts <<-USAGE
|
19
|
+
Usage: spin serve
|
20
|
+
spin push <file>...
|
21
|
+
Spin preloads your Rails environment to speed up your autotest(ish) workflow.
|
22
|
+
USAGE
|
23
|
+
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def socket_file
|
28
|
+
key = Digest::MD5.hexdigest [Dir.pwd, 'spin-gem'].join
|
29
|
+
[Dir.tmpdir, key].join('-')
|
30
|
+
end
|
31
|
+
|
32
|
+
def require_relative?
|
33
|
+
@require_relative ||= respond_to?(:require_relative)
|
34
|
+
end
|
35
|
+
|
36
|
+
# ## spin serve
|
37
|
+
def serve
|
38
|
+
file = socket_file
|
39
|
+
# We delete the tmp file for the Unix socket if it already exists. The file
|
40
|
+
# is scoped to the `pwd`, so if it already exists then it must be from an
|
41
|
+
# old run of `spin serve` and can be cleaned up.
|
42
|
+
File.delete(file) if File.exist?(file)
|
43
|
+
# This socket is how we communicate with `spin push`.
|
44
|
+
socket = UNIXServer.open(file)
|
45
|
+
|
46
|
+
ENV['RAILS_ENV'] = 'test' unless ENV['RAILS_ENV']
|
47
|
+
|
48
|
+
if File.exist? 'config/application.rb'
|
49
|
+
sec = Benchmark.realtime {
|
50
|
+
# We require config/application because that file (typically) loads Rails
|
51
|
+
# and any Bundler deps, as well as loading the initialization code for
|
52
|
+
# the app, but it doesn't actually perform the initialization. That happens
|
53
|
+
# in config/environment.
|
54
|
+
#
|
55
|
+
# In my experience that's the best we can do in terms of preloading. Rails
|
56
|
+
# and the gem dependencies rarely change and so don't need to be reloaded.
|
57
|
+
# But you can't initialize the application because any non-trivial app will
|
58
|
+
# involve it's models/controllers, etc. in its initialization, which you
|
59
|
+
# definitely don't want to preload.
|
60
|
+
require File.expand_path 'config/application'
|
61
|
+
}
|
62
|
+
# This is the amount of time that you'll save on each subsequent test run.
|
63
|
+
puts "Preloaded Rails env in #{sec}s..."
|
64
|
+
else
|
65
|
+
warn "Could not find config/application.rb. Are you running this from the root of a Rails project?"
|
66
|
+
end
|
67
|
+
|
68
|
+
loop do
|
69
|
+
# Since `spin push` reconnects each time it has a new file for us we just
|
70
|
+
# need to accept(2) connections from it.
|
71
|
+
conn = socket.accept
|
72
|
+
# This should be a relative path to a file.
|
73
|
+
file = conn.gets.chomp
|
74
|
+
|
75
|
+
# We fork(2) before loading the file so that our pristine preloaded
|
76
|
+
# environment is untouched. The child process will load whatever code it
|
77
|
+
# needs to, then it exits and we're back to the baseline preloaded app.
|
78
|
+
fork do
|
79
|
+
puts
|
80
|
+
puts "Loading #{file}"
|
81
|
+
|
82
|
+
# We require the full path of the file here in the child process.
|
83
|
+
require File.expand_path file
|
84
|
+
end
|
85
|
+
|
86
|
+
# We don't want the parent process handling multiple test runs at the same
|
87
|
+
# time because then we'd need to deal with multiple test databases, and
|
88
|
+
# that destroys the idea of being simple to use. So we wait(2) until the
|
89
|
+
# child process has finished running the test.
|
90
|
+
Process.wait
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# ## spin push
|
95
|
+
def push
|
96
|
+
# This is the other end of the socket that `spin serve` opens. At this point
|
97
|
+
# `spin serve` will accept(2) our connection.
|
98
|
+
socket = UNIXSocket.open(socket_file)
|
99
|
+
# The filenames that we will spin up to `spin serve` are passed in as
|
100
|
+
# arguments.
|
101
|
+
files_to_load = ARGV
|
102
|
+
|
103
|
+
# We reject anything in ARGV that isn't a file that exists. This takes
|
104
|
+
# care of scripts that specify files like `spin push -r file.rb`. The `-r`
|
105
|
+
# bit will just be ignored.
|
106
|
+
files_to_load.select { |f| File.exist?(f) }.each do |f|
|
107
|
+
puts "Spinning up #{f}"
|
108
|
+
# We put the filename on the socket for the server to read and then load.
|
109
|
+
socket.puts f
|
110
|
+
end
|
111
|
+
rescue Errno::ECONNREFUSED
|
112
|
+
abort "Connection was refused. Have you started up `spin serve` yet?"
|
113
|
+
end
|
114
|
+
|
115
|
+
subcommand = ARGV.shift
|
116
|
+
case subcommand
|
117
|
+
when 'serve' then serve
|
118
|
+
when 'push' then push
|
119
|
+
else usage
|
120
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jesse Storimer
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-10-28 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: |-
|
23
|
+
Spin preloads your Rails environment to speed up your autotest(ish) workflow.
|
24
|
+
|
25
|
+
By preloading your Rails environment for testing you don't load the same code over and over and over... Spin works best for an autotest(ish) workflow.
|
26
|
+
email:
|
27
|
+
- jstorimer@gmail.com
|
28
|
+
executables:
|
29
|
+
- spin
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- bin/spin
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://jstorimer.github.com/spin
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.6.2
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Spin preloads your Rails environment to speed up your autotest(ish) workflow.
|
70
|
+
test_files: []
|
71
|
+
|