rrails 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes.md +14 -2
- data/LICENSE.txt +1 -0
- data/README.md +80 -0
- data/VERSION +1 -1
- data/lib/rrails/client.rb +68 -16
- data/lib/rrails/server.rb +102 -46
- data/rrails.gemspec +4 -4
- metadata +5 -5
- data/README.rdoc +0 -51
data/Changes.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
|
-
v0.
|
1
|
+
v0.4.0 2012-10-15 09:56:00 +0900
|
2
2
|
------------------------------------------------------------------------
|
3
|
-
-
|
3
|
+
- MOD: pty support. So you can use rails console/server from rrails. (thanks quark-zju)
|
4
|
+
- MOD: pry support. (thansk quark-zju)
|
5
|
+
- MOD: add --host option. (thanks quark-zju)
|
6
|
+
- MOD: Change UNIXDomainSocket to IO.pipe. (thanks quark-zju)
|
7
|
+
|
8
|
+
v0.3.1 2012-10-13 18:22:08 +0900
|
9
|
+
------------------------------------------------------------------------
|
10
|
+
- (tag: v0.3.1) Regenerate gemspec for version 0.3.1
|
11
|
+
- Version bump to 0.3.1
|
12
|
+
- update changes.
|
13
|
+
- it should not define constants outside RemoteRails::Server namespace.
|
14
|
+
- restyle again.
|
15
|
+
- use markdown style.
|
4
16
|
- update doc.
|
5
17
|
|
6
18
|
v0.3.0 2012-10-13 14:58:02 +0900
|
data/LICENSE.txt
CHANGED
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# rrails
|
2
|
+
|
3
|
+
Preload rails environment in Remote server to make rails/rake commands faster.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* non-Windows OS
|
8
|
+
* Ruby 1.9.3
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
Start server:
|
13
|
+
|
14
|
+
$ cd ~/rails_project
|
15
|
+
$ export RAILS_ENV=development # optionally
|
16
|
+
$ bundle exec rrails-server
|
17
|
+
|
18
|
+
Run rails/rake commands using rrails:
|
19
|
+
|
20
|
+
$ export RAILS_ENV=development # optionally
|
21
|
+
$ rrails -- rails generate model Yakiniku
|
22
|
+
$ rrails -- rake db:migrate
|
23
|
+
$ rrails -- rake routes
|
24
|
+
$ rrails -- rails server
|
25
|
+
$ rrails -- rails console
|
26
|
+
$ rrails -- pry # start pry as rails console
|
27
|
+
|
28
|
+
# If you need an interactive console for non rails *console
|
29
|
+
# commands, you may want to add '--pty' option.
|
30
|
+
# This makes sure that interactive things (like line editing)
|
31
|
+
# work correctly, but it also redirect all STDERR to STDOUT
|
32
|
+
# and keys like ^C may not work correctly.
|
33
|
+
$ rrails --pty -- rails server # use debugger
|
34
|
+
|
35
|
+
You may want to add following code to your shell rc file:
|
36
|
+
|
37
|
+
rrails-exec() {
|
38
|
+
if pgrep -f rrails-server >/dev/null && grep -q rrails Gemfile.lock &>/dev/null; then
|
39
|
+
rrails -- "$@"
|
40
|
+
else
|
41
|
+
command "$@"
|
42
|
+
fi
|
43
|
+
}
|
44
|
+
alias rails='rrails-exec rails'
|
45
|
+
alias rake='rrails-exec rake'
|
46
|
+
|
47
|
+
## Description
|
48
|
+
|
49
|
+
rails command is too slow. and rake command is too slow under rails environment.
|
50
|
+
So, rrails can run rails/rake commands by preloaded daemon.
|
51
|
+
|
52
|
+
rails-sh is very good solution for this issue. But
|
53
|
+
|
54
|
+
* it can't run "rake -T"
|
55
|
+
* it can't use zsh's histroy.
|
56
|
+
|
57
|
+
So I wrote rrails.
|
58
|
+
|
59
|
+
## See Also
|
60
|
+
|
61
|
+
* guard-rrails: https://github.com/walf443/guard-rrails
|
62
|
+
* rails-sh: https://github.com/jugyo/rails-sh
|
63
|
+
|
64
|
+
## Contributing to rrails
|
65
|
+
|
66
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
67
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
68
|
+
* Fork the project.
|
69
|
+
* Start a feature/bugfix branch.
|
70
|
+
* Commit and push until you are happy with your contribution.
|
71
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
72
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
73
|
+
|
74
|
+
## Copyright
|
75
|
+
|
76
|
+
Copyright (c) 2012 Keiji, Yoshimi. <br>
|
77
|
+
Copyright (c) 2012 Wu Jun.
|
78
|
+
|
79
|
+
See LICENSE.txt for further details.
|
80
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/rrails/client.rb
CHANGED
@@ -2,6 +2,8 @@ require 'socket'
|
|
2
2
|
require 'rrails'
|
3
3
|
require 'shellwords'
|
4
4
|
require 'optparse'
|
5
|
+
require 'io/console'
|
6
|
+
|
5
7
|
module RemoteRails
|
6
8
|
#
|
7
9
|
# client for RemoteRails::Server.
|
@@ -9,17 +11,26 @@ module RemoteRails
|
|
9
11
|
# @example
|
10
12
|
# client = RemoteRails::Client.new({
|
11
13
|
# :cmd => "rails generate model Sushi",
|
12
|
-
# :
|
14
|
+
# :port => 5656,
|
15
|
+
# :host => 'localhost'
|
13
16
|
# })
|
14
17
|
# client.run
|
15
18
|
#
|
16
19
|
class Client
|
17
|
-
def self.
|
18
|
-
options = {}
|
20
|
+
def self.opts_parser(options = {})
|
19
21
|
opts = OptionParser.new
|
22
|
+
opts.banner = 'Usage: rrails [options] [[--] commands]'
|
23
|
+
opts.on('-h', '--help', 'This help.') {|v| options[:help] = v }
|
24
|
+
opts.on('--host=s', 'RRails server hostname. Default value is "localhost".') {|v| options[:host] = v }
|
20
25
|
opts.on('-E', '--rails_env=s') {|v| options[:rails_env] = v }
|
21
|
-
opts.on('-p', '--port=i') {|v| options[:port] = v }
|
22
|
-
opts.
|
26
|
+
opts.on('-p', '--port=i', 'RRails server port. Default value is decided from RAILS_ENV.') {|v| options[:port] = v }
|
27
|
+
opts.on('-t', '--[no-]pty', "Prepare a PTY. Default value is decided by commands.") {|v| options[:pty] = v }
|
28
|
+
return opts
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.new_with_options(argv)
|
32
|
+
options = {}
|
33
|
+
opts_parser(options).parse!(argv)
|
23
34
|
|
24
35
|
cmd = Shellwords.join(argv)
|
25
36
|
options[:cmd] = cmd == "" ? nil : cmd
|
@@ -27,25 +38,66 @@ module RemoteRails
|
|
27
38
|
end
|
28
39
|
|
29
40
|
def initialize(options={})
|
30
|
-
@cmd = options[:cmd] || "
|
31
|
-
@rails_env = options[:rails_env] || 'development'
|
41
|
+
@cmd = options[:cmd] || ""
|
32
42
|
@host = options[:host] || 'localhost'
|
43
|
+
@rails_env = options[:rails_env] || ENV['RAILS_ENV'] || 'development'
|
33
44
|
@port = options[:port] || DEFAULT_PORT[@rails_env]
|
45
|
+
@use_pty = options[:pty]
|
46
|
+
if @use_pty.nil?
|
47
|
+
# decide use_pty from cmd
|
48
|
+
case @cmd
|
49
|
+
when /^rails (?:c(?:onsole)?|db(?:console)?)$/, 'pry'
|
50
|
+
@use_pty = true
|
51
|
+
end
|
52
|
+
end
|
34
53
|
end
|
35
54
|
|
36
55
|
def run
|
56
|
+
if @cmd.empty?
|
57
|
+
STDERR.puts Client.opts_parser
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
37
61
|
sock = TCPSocket.open(@host, @port)
|
38
|
-
sock.puts(@cmd)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
62
|
+
sock.puts("#{@use_pty ? 'P' : ' '}#@cmd")
|
63
|
+
running = true
|
64
|
+
|
65
|
+
begin
|
66
|
+
# input thread
|
67
|
+
thread = Thread.start do
|
68
|
+
while running do
|
69
|
+
begin
|
70
|
+
input = @use_pty ? STDIN.getch : STDIN.gets
|
71
|
+
sock.write(input)
|
72
|
+
sock.flush
|
73
|
+
rescue
|
74
|
+
running = false
|
75
|
+
sock.close unless sock.closed?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
while running && line = sock.gets
|
81
|
+
case line.chomp
|
82
|
+
when /^EXIT\t(.+)$/
|
83
|
+
exit($1.to_i)
|
84
|
+
when /^OUT\t(.+)$/
|
85
|
+
STDOUT.write($1.split(',').map(&:to_i).pack('c*'))
|
86
|
+
when /^ERR\t(.+)$/
|
87
|
+
STDERR.write($1.split(',').map(&:to_i).pack('c*'))
|
88
|
+
end
|
47
89
|
end
|
90
|
+
|
91
|
+
rescue EOFError
|
92
|
+
running = false
|
93
|
+
rescue Interrupt
|
94
|
+
running = false
|
95
|
+
exit 130
|
48
96
|
end
|
97
|
+
|
98
|
+
STDERR.puts "\nERROR: RRails server disconnected"
|
99
|
+
exit -1
|
49
100
|
end
|
101
|
+
|
50
102
|
end
|
51
103
|
end
|
data/lib/rrails/server.rb
CHANGED
@@ -4,6 +4,8 @@ require 'logger'
|
|
4
4
|
require 'rake'
|
5
5
|
require 'stringio'
|
6
6
|
require 'shellwords'
|
7
|
+
require 'pty'
|
8
|
+
require 'benchmark'
|
7
9
|
|
8
10
|
# FIXME: rails command require APP_PATH constants.
|
9
11
|
APP_PATH = File.expand_path('./config/application')
|
@@ -18,7 +20,7 @@ module RemoteRails
|
|
18
20
|
PAGE_SIZE = 4096
|
19
21
|
|
20
22
|
def initialize(options={})
|
21
|
-
@rails_env = options[:rails_env] || "development"
|
23
|
+
@rails_env = options[:rails_env] || ENV['RAILS_ENV'] || "development"
|
22
24
|
@app_path = File.expand_path('./config/application')
|
23
25
|
# should not access to outside
|
24
26
|
@host = 'localhost'
|
@@ -30,14 +32,14 @@ module RemoteRails
|
|
30
32
|
self.boot_rails
|
31
33
|
server = TCPServer.open(@host, @port)
|
32
34
|
@logger.info("starting rrails server on #{@host}:#{@port}")
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
exit
|
35
|
+
|
36
|
+
[:INT, :TERM].each do |sig|
|
37
|
+
trap(sig) do
|
38
|
+
@logger.info("SIG#{sig} recieved. shutdown...")
|
39
|
+
exit
|
40
|
+
end
|
40
41
|
end
|
42
|
+
|
41
43
|
trap(:HUP) do
|
42
44
|
@logger.info("SIGHUP recieved. reload...")
|
43
45
|
ActionDispatch::Callbacks.new(Proc.new {}).call({})
|
@@ -46,31 +48,29 @@ module RemoteRails
|
|
46
48
|
Thread.abort_on_exception = true
|
47
49
|
loop do
|
48
50
|
Thread.start(server.accept) do |s|
|
49
|
-
childpids = []
|
50
51
|
begin
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
s.puts("FINISHED\t#{ finish - start }")
|
58
|
-
@logger.info("finished: #{line}")
|
52
|
+
line = s.gets.chomp
|
53
|
+
pty, line = (line[0] == 'P'), line[1..-1]
|
54
|
+
@logger.info("invoke: #{line} (pty=#{pty})")
|
55
|
+
status = nil
|
56
|
+
time = Benchmark.realtime do
|
57
|
+
status = dispatch(s, line, pty)
|
59
58
|
end
|
60
|
-
|
61
|
-
|
62
|
-
@logger.
|
59
|
+
exitcode = status ? status.exitstatus || (status.termsig + 128) : 0
|
60
|
+
s.puts("EXIT\t#{exitcode}")
|
61
|
+
@logger.info("finished: #{line} (#{time} seconds)")
|
62
|
+
rescue Errno::EPIPE
|
63
|
+
@logger.info("disconnected: #{line}")
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
67
68
|
|
68
69
|
def boot_rails
|
69
|
-
@logger.info("prepare rails environment")
|
70
|
+
@logger.info("prepare rails environment (#{@rails_env})")
|
70
71
|
ENV["RAILS_ENV"] = @rails_env
|
71
|
-
require File.expand_path('./config/
|
72
|
-
|
73
|
-
Rails.application.require_environment!
|
72
|
+
require File.expand_path('./config/environment')
|
73
|
+
|
74
74
|
unless Rails.application.config.cache_classes
|
75
75
|
ActionDispatch::Reloader.cleanup!
|
76
76
|
ActionDispatch::Reloader.prepare!
|
@@ -78,38 +78,89 @@ module RemoteRails
|
|
78
78
|
@logger.info("finished preparing rails environment")
|
79
79
|
end
|
80
80
|
|
81
|
-
def dispatch(sock, line)
|
82
|
-
|
83
|
-
|
81
|
+
def dispatch(sock, line, pty=false)
|
82
|
+
|
83
|
+
if pty
|
84
|
+
m_out, c_out = PTY.open
|
85
|
+
c_in = c_err = c_out
|
86
|
+
m_fds = [m_out, c_out]
|
87
|
+
c_fds = [c_out]
|
88
|
+
clisocks = {in: m_out, out: m_out}
|
89
|
+
else
|
90
|
+
c_in, m_in = IO.pipe
|
91
|
+
m_out, c_out = IO.pipe
|
92
|
+
m_err, c_err = IO.pipe
|
93
|
+
m_fds = [m_in, m_out, m_err]
|
94
|
+
c_fds = [c_in, c_out, c_err]
|
95
|
+
clisocks = {in: m_in, out: m_out, err: m_err}
|
96
|
+
end
|
97
|
+
|
98
|
+
running = true
|
84
99
|
pid = fork do
|
85
|
-
|
86
|
-
|
100
|
+
m_fds.map(&:close) if not pty
|
101
|
+
STDIN.reopen(c_in)
|
102
|
+
STDOUT.reopen(c_out)
|
103
|
+
STDERR.reopen(c_err)
|
87
104
|
ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
|
88
|
-
STDOUT.reopen(servsock_out)
|
89
|
-
STDERR.reopen(servsock_err)
|
90
105
|
execute *Shellwords.shellsplit(line)
|
91
106
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
107
|
+
|
108
|
+
c_fds.map(&:close) if not pty
|
109
|
+
|
110
|
+
# pump input. since it will block, make it in another thread
|
111
|
+
thread = Thread.start do
|
112
|
+
while running do
|
113
|
+
begin
|
114
|
+
input = sock.__send__(pty ? :getc : :gets)
|
115
|
+
rescue => ex
|
116
|
+
@logger.debug "input thread got #{ex}"
|
117
|
+
running = false
|
118
|
+
end
|
119
|
+
clisocks[:in].write(input) rescue nil
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
97
123
|
loop do
|
98
|
-
[:out, :
|
124
|
+
[:out, :err].each do |channel|
|
125
|
+
next if not clisocks[channel]
|
99
126
|
begin
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
sock.
|
127
|
+
loop do
|
128
|
+
response = clisocks[channel].read_nonblock(PAGE_SIZE)
|
129
|
+
sock.puts("#{channel.upcase}\t#{response.bytes.to_a.join(',')}")
|
130
|
+
sock.flush
|
104
131
|
end
|
105
132
|
rescue Errno::EAGAIN, EOFError => ex
|
106
|
-
|
133
|
+
next
|
107
134
|
end
|
108
135
|
end
|
109
|
-
|
110
|
-
|
136
|
+
|
137
|
+
if running
|
138
|
+
_, stat = Process.waitpid2(pid, Process::WNOHANG)
|
139
|
+
if stat
|
140
|
+
@logger.debug "child exits. #{stat}"
|
141
|
+
return stat
|
142
|
+
end
|
111
143
|
end
|
144
|
+
|
145
|
+
# send heartbeat so that we got EPIPE immediately when client dies
|
146
|
+
sock.puts("PING")
|
147
|
+
sock.flush
|
148
|
+
|
149
|
+
# do not make CPU hot
|
150
|
+
sleep 0.1
|
112
151
|
end
|
152
|
+
ensure
|
153
|
+
running = false
|
154
|
+
[*c_fds, *m_fds].each {|io| io.close unless io.closed?}
|
155
|
+
if pid
|
156
|
+
begin
|
157
|
+
Process.kill 0, pid
|
158
|
+
@logger.debug "killing pid #{pid}"
|
159
|
+
Process.kill 'TERM', pid rescue nil
|
160
|
+
rescue Errno::ESRCH
|
161
|
+
end
|
162
|
+
end
|
163
|
+
thread.kill if thread
|
113
164
|
end
|
114
165
|
|
115
166
|
def execute(cmd, *args)
|
@@ -120,9 +171,14 @@ module RemoteRails
|
|
120
171
|
require 'rails/commands'
|
121
172
|
when 'rake'
|
122
173
|
::Rake.application.run
|
174
|
+
when 'pry'
|
175
|
+
begin
|
176
|
+
::Pry::CLI.parse_options
|
177
|
+
rescue NameError
|
178
|
+
STDERR.puts "if you want to use pry. you should add 'pry' to Gemfile."
|
179
|
+
end
|
123
180
|
else
|
124
|
-
|
125
|
-
raise RuntimeError.new("#{cmd} is not supported in rrails.")
|
181
|
+
STDERR.puts "#{cmd} is not supported in RRails."
|
126
182
|
end
|
127
183
|
end
|
128
184
|
|
data/rrails.gemspec
CHANGED
@@ -5,17 +5,17 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "rrails"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Keiji, Yoshimi"]
|
12
|
-
s.date = "2012-10-
|
12
|
+
s.date = "2012-10-15"
|
13
13
|
s.description = "remote run rails/rake command"
|
14
14
|
s.email = "walf443@gmail.com"
|
15
15
|
s.executables = ["rrails", "rrails-server"]
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE.txt",
|
18
|
-
"README.
|
18
|
+
"README.md"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".document",
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
"Gemfile",
|
24
24
|
"Gemfile.lock",
|
25
25
|
"LICENSE.txt",
|
26
|
-
"README.
|
26
|
+
"README.md",
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
29
|
"bin/rrails",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rrails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|
@@ -99,14 +99,14 @@ executables:
|
|
99
99
|
extensions: []
|
100
100
|
extra_rdoc_files:
|
101
101
|
- LICENSE.txt
|
102
|
-
- README.
|
102
|
+
- README.md
|
103
103
|
files:
|
104
104
|
- .document
|
105
105
|
- Changes.md
|
106
106
|
- Gemfile
|
107
107
|
- Gemfile.lock
|
108
108
|
- LICENSE.txt
|
109
|
-
- README.
|
109
|
+
- README.md
|
110
110
|
- Rakefile
|
111
111
|
- VERSION
|
112
112
|
- bin/rrails
|
@@ -132,7 +132,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
132
|
version: '0'
|
133
133
|
segments:
|
134
134
|
- 0
|
135
|
-
hash:
|
135
|
+
hash: 3003535707070342098
|
136
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
137
|
none: false
|
138
138
|
requirements:
|
data/README.rdoc
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
= rrails
|
2
|
-
|
3
|
-
remote run rails/rake command.
|
4
|
-
|
5
|
-
== Usage
|
6
|
-
|
7
|
-
# run server
|
8
|
-
$ cd ~/rails_project
|
9
|
-
$ bundle exec rrails-server
|
10
|
-
|
11
|
-
# on another console.
|
12
|
-
$ rrails -- rails generate model Yakiniku
|
13
|
-
$ rrails -E test -- rake db:migrate
|
14
|
-
|
15
|
-
== Description
|
16
|
-
|
17
|
-
rails command is too slow. and rake command is too slow under rails environment.
|
18
|
-
So, rrails can run rails/rake commands by preloaded daemon.
|
19
|
-
|
20
|
-
rails-sh is very good solution for this issue. But
|
21
|
-
* it can't run "rake -T"
|
22
|
-
* it can't use zsh's histroy.
|
23
|
-
|
24
|
-
So I wrote rrails.
|
25
|
-
|
26
|
-
== Problem
|
27
|
-
|
28
|
-
rrails can't work folloing commands:
|
29
|
-
* rake (console|dbconsole): please use rails-sh
|
30
|
-
* rake server
|
31
|
-
|
32
|
-
== SEE ALSO
|
33
|
-
|
34
|
-
* guard-rrails: https://github.com/walf443/guard-rrails
|
35
|
-
* rails-sh: https://github.com/jugyo/rails-sh
|
36
|
-
|
37
|
-
== Contributing to rrails
|
38
|
-
|
39
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
40
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
41
|
-
* Fork the project.
|
42
|
-
* Start a feature/bugfix branch.
|
43
|
-
* Commit and push until you are happy with your contribution.
|
44
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
45
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
46
|
-
|
47
|
-
== Copyright
|
48
|
-
|
49
|
-
Copyright (c) 2012 Keiji, Yoshimi. See LICENSE.txt for
|
50
|
-
further details.
|
51
|
-
|