spinny_rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spinny.gemspec
4
+ gemspec
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
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
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,3 @@
1
+ #! /usr/bin/env sh
2
+
3
+ ps aux | grep spinny- | grep -v spinny-stop | grep -v grep | awk '{ print $2 }' | xargs kill -9
@@ -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
@@ -0,0 +1,3 @@
1
+ module Spinny
2
+ VERSION = "0.1.0"
3
+ 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: []