spinny_rb 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +87 -0
- data/Rakefile +10 -0
- data/bin/spinny-guard +31 -0
- data/bin/spinny-listen +24 -0
- data/bin/spinny-push +13 -0
- data/bin/spinny-serve +16 -0
- data/bin/spinny-stop +3 -0
- data/lib/spinny/connection.rb +16 -0
- data/lib/spinny/interactive_client.rb +17 -0
- data/lib/spinny/listen_client.rb +18 -0
- data/lib/spinny/load_client.rb +14 -0
- data/lib/spinny/server.rb +42 -0
- data/lib/spinny/version.rb +3 -0
- data/lib/spinny.rb +16 -0
- data/spinny_rb.gemspec +30 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c9f0c42c9c22056403200244f6fca682a2bec1cf
|
4
|
+
data.tar.gz: e2d6005d1e1d783090b18225d227e86d25b3c6e5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b73983a3e5eff331ff9934f49f3e07fc0c6e913d2ef67927f6bc3d8bb0db0cec6f54ddb3848430625fbf4a1ae7396800a23e0ba4784bb6f959b60fcf5bae56de
|
7
|
+
data.tar.gz: b5d15799f5b0a7b40df787cc4dbc1b223113762c7bc6e2445f1029736c9e05322a0bfd89a1c8809ba68348bacd8af30b794b3978f2f5bd68b59abf9c0f60e801
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Spinny
|
2
|
+
|
3
|
+
a lightweight, unopinionated ruby application pre-loader
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Spinny is influenced by projects like Spring and Spin and tries to make your workflow more efficient.
|
8
|
+
It differs from those projects in the sense that it is designed to be lighter and does not try to
|
9
|
+
create special cases for certain technologies like Rails or particular test runners.
|
10
|
+
Small, light, and modular is the name of the game.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
```sh
|
15
|
+
gem install spinny_rb
|
16
|
+
```
|
17
|
+
|
18
|
+
## How It Works
|
19
|
+
|
20
|
+
Spinny works using a client-server model.
|
21
|
+
The server will pre-load some code that you give it and then start listening on a TCP port.
|
22
|
+
When it receives a connection it will fork off new process and run the code passed in the TCP message.
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
First, you'll need to start your server.
|
27
|
+
In this example, we spin up a `Spinny::Server` using the `spinny-serve` executable.
|
28
|
+
|
29
|
+
```sh
|
30
|
+
# Add the 'test' directory to the $LOAD_PATH and pre-load 'test_helper'
|
31
|
+
spinny-serve -Itest test_helper
|
32
|
+
|
33
|
+
# Pre-loading your typical Rails app
|
34
|
+
spinny-serve config/environment
|
35
|
+
```
|
36
|
+
|
37
|
+
Now we need a client to push code to our running server.
|
38
|
+
Spinny comes with several clients out of the box:
|
39
|
+
|
40
|
+
* `Spinny::InteractiveClient` is a REPL that will push arbitrary code to the server
|
41
|
+
* `Spinny::LoadClient` takes a bunch of files and pushes them to the server to be loaded (e.g. running tests)
|
42
|
+
* `Spinny::ListenClient` is inspired by Guard. It takes a bunch of filepaths and listens for OS file change events and then loads the changed files on the server
|
43
|
+
|
44
|
+
All of these can be used by loading the respective client into an IRB shell.
|
45
|
+
Spinny also provides some executables to make it easier to work with common use cases.
|
46
|
+
|
47
|
+
### spinny-push
|
48
|
+
|
49
|
+
`spinny-push` will read a list of filenames from ARGV or STDIN and use `Spinny::LoadClient` to push them to the server:
|
50
|
+
|
51
|
+
```sh
|
52
|
+
# Read from ARGV
|
53
|
+
spinny-push file_one.rb file_two.rb
|
54
|
+
|
55
|
+
# Read from STDIN
|
56
|
+
ls test/*_test.rb | spinny-push
|
57
|
+
```
|
58
|
+
|
59
|
+
### spinny-listen
|
60
|
+
|
61
|
+
`spinny-listen` will read a list of directories from ARGV or STDIN and use `Spinny::ListenClient` to watch for file changes and then will push them to the server via `Spinny::LoadClient`
|
62
|
+
|
63
|
+
```sh
|
64
|
+
spinny-listen test
|
65
|
+
```
|
66
|
+
|
67
|
+
### spinny-guard
|
68
|
+
|
69
|
+
`spinny-guard` gives you [guard](https://github.com/guard/guard)-like functionality. This spins up `Spinny::ListenClient` and a `Spinny::Server` for you in one convenient command
|
70
|
+
|
71
|
+
```sh
|
72
|
+
spinny-guard
|
73
|
+
```
|
74
|
+
|
75
|
+
### spinny-stop
|
76
|
+
|
77
|
+
Finally, there is `spinny-stop` for killing all of your Spinny processes:
|
78
|
+
|
79
|
+
```sh
|
80
|
+
spinny-stop
|
81
|
+
```
|
82
|
+
|
83
|
+
## TODO
|
84
|
+
|
85
|
+
* Add regexp for spinny-listen
|
86
|
+
* Add spinny-reload for reloading the server
|
87
|
+
* Add spinny-reload for listening and reloading the server when certain things happen
|
data/Rakefile
ADDED
data/bin/spinny-guard
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
bin_path = File.expand_path('../', __FILE__)
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = 'Usage: spinny-guard [options]'
|
10
|
+
|
11
|
+
# Defaults
|
12
|
+
options[:listen] = 'test'
|
13
|
+
options[:load_paths] = 'test'
|
14
|
+
options[:env] = 'test_helper'
|
15
|
+
|
16
|
+
opts.on('--listen DIR', "Listen to the given directory (default: #{options[:listen]})") do |dir|
|
17
|
+
options[:listen] = dir
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('--env ENV_FILE', "Pre-load the given file (default: #{options[:env]})") do |file|
|
21
|
+
options[:env] = file
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on('-I[PATHS]', '--include=[PATHS]', "Colon-separated list of directories to add to the $LOAD_PATH (default: #{options[:load_paths]})") do |paths|
|
25
|
+
options[:load_paths] = paths
|
26
|
+
end
|
27
|
+
end.parse!
|
28
|
+
|
29
|
+
system "#{bin_path}/spinny-listen -d #{options[:listen]}"
|
30
|
+
puts "#{bin_path}/spinny-serve -I#{options[:load_paths]} #{options[:env]}"
|
31
|
+
system "#{bin_path}/spinny-serve -I#{options[:load_paths]} #{options[:env]}"
|
data/bin/spinny-listen
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << File.expand_path('../../lib', __FILE__)
|
4
|
+
require 'spinny'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = 'Usage: spinny-listen DIR1 DIR2 ...'
|
10
|
+
|
11
|
+
opts.on('-d', '--daemonize', 'Run the process in the background') do
|
12
|
+
options[:daemonize] = true
|
13
|
+
end
|
14
|
+
end.parse!
|
15
|
+
|
16
|
+
dirs = ARGV.empty? ? STDIN.read.split("\n") : ARGV
|
17
|
+
|
18
|
+
start_listener = proc { Spinny::ListenClient.new(dirs).start! }
|
19
|
+
|
20
|
+
if options[:daemonize]
|
21
|
+
Process.detach fork(&start_listener)
|
22
|
+
else
|
23
|
+
start_listener.call
|
24
|
+
end
|
data/bin/spinny-push
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << File.expand_path('../../lib', __FILE__)
|
4
|
+
require 'spinny'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = 'Usage: spinny-push FILE1 FILE2 ...'
|
10
|
+
end.parse!
|
11
|
+
|
12
|
+
filepaths = ARGV.empty? ? STDIN.read.split("\n") : ARGV
|
13
|
+
Spinny::LoadClient.new(filepaths).start!
|
data/bin/spinny-serve
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << File.expand_path('../../lib', __FILE__)
|
4
|
+
require 'spinny'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = 'Usage: spinny-serve [options] ENV_FILE'
|
10
|
+
|
11
|
+
opts.on('-I[PATHS]', '--include=[PATHS]', 'Colon-separated list of directories to add to the $LOAD_PATH') do |paths|
|
12
|
+
options[:load_paths] = paths.split(':')
|
13
|
+
end
|
14
|
+
end.parse!
|
15
|
+
|
16
|
+
Spinny.serve! ARGV[0], options[:load_paths]
|
data/bin/spinny-stop
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Spinny
|
5
|
+
class Connection
|
6
|
+
def initialize(port = Server::DEFAULT_PORT)
|
7
|
+
@port = port
|
8
|
+
end
|
9
|
+
|
10
|
+
def push(code)
|
11
|
+
# connect to port, send code over port
|
12
|
+
uri = URI("http://localhost:#{@port}/enqueue")
|
13
|
+
Net::HTTP.post_form(uri, "code" => code)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Spinny
|
2
|
+
# An simple REPL that will allow you to push code to
|
3
|
+
# run on a Spinny::Server
|
4
|
+
class InteractiveClient
|
5
|
+
def initialize
|
6
|
+
@connection = Server.connect
|
7
|
+
end
|
8
|
+
|
9
|
+
def start!
|
10
|
+
loop do
|
11
|
+
puts "Type code to eval in fork then hit enter..."
|
12
|
+
code = gets
|
13
|
+
@connection.push(code)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'listen'
|
2
|
+
require 'spinny/load_client'
|
3
|
+
|
4
|
+
module Spinny
|
5
|
+
class ListenClient
|
6
|
+
def initialize(dirs)
|
7
|
+
@listener = Listen.to(*dirs, only: /\.rb$/) do |modified, added, removed|
|
8
|
+
changed = modified + added
|
9
|
+
Spinny::LoadClient.new(changed).start!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def start!
|
14
|
+
@listener.start
|
15
|
+
sleep
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Spinny
|
2
|
+
# A simple client that just loads files
|
3
|
+
# Can be used to run Minitest tests
|
4
|
+
class LoadClient
|
5
|
+
def initialize(filepaths)
|
6
|
+
@code = filepaths.map {|fp| "load '#{fp}'"}.join(';')
|
7
|
+
@connection = Server.connect
|
8
|
+
end
|
9
|
+
|
10
|
+
def start!
|
11
|
+
@connection.push(@code)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
Thread.abort_on_exception = true
|
5
|
+
|
6
|
+
module Spinny
|
7
|
+
# Responsible for forking off new code runs
|
8
|
+
class Server
|
9
|
+
DEFAULT_PORT = 8080
|
10
|
+
|
11
|
+
def self.connect(port = DEFAULT_PORT)
|
12
|
+
Connection.new(port)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(filepath)
|
16
|
+
@filepath = filepath
|
17
|
+
end
|
18
|
+
|
19
|
+
def start!
|
20
|
+
require @filepath
|
21
|
+
queue = Queue.new
|
22
|
+
start_http_listener(queue)
|
23
|
+
loop do
|
24
|
+
fork_code = queue.deq
|
25
|
+
pid = fork { eval fork_code }
|
26
|
+
Process.wait pid
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def start_http_listener(queue)
|
31
|
+
Thread.new do
|
32
|
+
server = WEBrick::HTTPServer.new(:Port => DEFAULT_PORT)
|
33
|
+
server.mount_proc '/enqueue' do |req, res|
|
34
|
+
code = CGI.parse(req.body)['code'].first
|
35
|
+
queue.enq(code)
|
36
|
+
end
|
37
|
+
server.start
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/spinny.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spinny/version'
|
2
|
+
require 'spinny/server'
|
3
|
+
require 'spinny/connection'
|
4
|
+
require 'spinny/interactive_client'
|
5
|
+
require 'spinny/load_client'
|
6
|
+
require 'spinny/listen_client'
|
7
|
+
|
8
|
+
# A lighter, less opinionated Ruby pre-loader
|
9
|
+
module Spinny
|
10
|
+
# Block the current thread and boot up a server
|
11
|
+
def self.serve!(filepath, load_paths = [])
|
12
|
+
puts "Starting Spinny::Server..."
|
13
|
+
load_paths.each { |p| $: << p }
|
14
|
+
Server.new(filepath).start!
|
15
|
+
end
|
16
|
+
end
|
data/spinny_rb.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'spinny/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "spinny_rb"
|
8
|
+
spec.version = Spinny::VERSION
|
9
|
+
spec.authors = ["Josh Bodah"]
|
10
|
+
spec.email = ["jb3689@yahoo.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{a lightweight, unopinionated ruby application pre-loader}
|
13
|
+
spec.description = %q{
|
14
|
+
Spinny is influenced by projects like Spring and Spin and tries to make your workflow more efficient.
|
15
|
+
It differs from those projects in the sense that it is designed to be lighter and does not try to
|
16
|
+
create special cases for certain technologies like Rails or particular test runners.
|
17
|
+
}
|
18
|
+
spec.homepage = "https://github.com/jbodah/spinny_rb"
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "listen", "~> 3.0"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "minitest"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spinny_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Josh Bodah
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: listen
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: |2
|
70
|
+
|
71
|
+
Spinny is influenced by projects like Spring and Spin and tries to make your workflow more efficient.
|
72
|
+
It differs from those projects in the sense that it is designed to be lighter and does not try to
|
73
|
+
create special cases for certain technologies like Rails or particular test runners.
|
74
|
+
email:
|
75
|
+
- jb3689@yahoo.com
|
76
|
+
executables: []
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- ".gitignore"
|
81
|
+
- ".travis.yml"
|
82
|
+
- Gemfile
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- bin/spinny-guard
|
86
|
+
- bin/spinny-listen
|
87
|
+
- bin/spinny-push
|
88
|
+
- bin/spinny-serve
|
89
|
+
- bin/spinny-stop
|
90
|
+
- lib/spinny.rb
|
91
|
+
- lib/spinny/connection.rb
|
92
|
+
- lib/spinny/interactive_client.rb
|
93
|
+
- lib/spinny/listen_client.rb
|
94
|
+
- lib/spinny/load_client.rb
|
95
|
+
- lib/spinny/server.rb
|
96
|
+
- lib/spinny/version.rb
|
97
|
+
- spinny_rb.gemspec
|
98
|
+
homepage: https://github.com/jbodah/spinny_rb
|
99
|
+
licenses: []
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.4.8
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: a lightweight, unopinionated ruby application pre-loader
|
121
|
+
test_files: []
|