spin 0.1.0
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.
- 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
|
+
|