ftp_service 0.1.1 → 0.2.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/.gitignore +2 -0
- data/CHANGELOG.markdown +10 -0
- data/README.markdown +37 -0
- data/Rakefile +18 -8
- data/VERSION +1 -1
- data/ftp_service.gemspec +14 -8
- data/lib/ftp_service.rb +35 -11
- data/lib/tempfile_helper.rb +20 -0
- data/spec/ftp_service_spec.rb +42 -7
- data/spec/tempfile_helper_spec.rb +62 -0
- metadata +22 -7
- data/.document +0 -5
- data/README.rdoc +0 -40
data/.gitignore
CHANGED
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# v0.2.0 (2010-03-08)
|
2
|
+
|
3
|
+
* Add `FtpService#write_request` and `FtpService#read_response` methods,
|
4
|
+
making this thing actually usable.
|
5
|
+
|
6
|
+
* Switch to Markdown + Yardoc for rdocs.
|
7
|
+
|
8
|
+
# v0.1.1 (2010-03-08)
|
9
|
+
|
10
|
+
* First version. Opens a connection but that's it. Useful, huh?
|
data/README.markdown
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# FTP Service
|
2
|
+
|
3
|
+
An FTP Service is like a web service except stupid. You send your
|
4
|
+
request by uploading an xml file and get your response by downloading
|
5
|
+
another xml file. Have you ever had to deal with something like that? I
|
6
|
+
have.
|
7
|
+
|
8
|
+
RDocs on [rdoc.info](http://rdoc.info/projects/blaix/ftp_service).
|
9
|
+
|
10
|
+
Source code on [github](http://github.com/blaix/ftp_service).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
gem install ftp_service
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
require 'ftp_service'
|
19
|
+
|
20
|
+
FtpService.open('host', 'user', 'pass') do |service|
|
21
|
+
path = '/the/remote/path'
|
22
|
+
service.write_request("#{path}/request.xml", '<foo>bar</foo>')
|
23
|
+
response = service.read_response("#{path}/response.xml")
|
24
|
+
end
|
25
|
+
|
26
|
+
* `read_response` will block while it polls the server waiting for a
|
27
|
+
response.
|
28
|
+
* Temp files are created for the local request and response files and
|
29
|
+
deleted when no longer needed.
|
30
|
+
|
31
|
+
For more details, see the
|
32
|
+
[RDocs](http://rdoc.info/projects/blaix/ftp_service) (sike they are
|
33
|
+
really yardocs!).
|
34
|
+
|
35
|
+
## Copyright
|
36
|
+
|
37
|
+
Copyright (c) 2010 Justin Blake. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -12,6 +12,7 @@ begin
|
|
12
12
|
gem.authors = ["Justin Blake"]
|
13
13
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
14
|
gem.add_development_dependency "mocha", ">= 0.9.8"
|
15
|
+
gem.add_development_dependency "yard", ">= 0"
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
17
|
end
|
17
18
|
Jeweler::GemcutterTasks.new
|
@@ -25,6 +26,14 @@ Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
25
26
|
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
27
|
end
|
27
28
|
|
29
|
+
namespace :spec do
|
30
|
+
Spec::Rake::SpecTask.new(:doc) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
33
|
+
spec.spec_opts << '--format specdoc'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
28
37
|
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
38
|
spec.libs << 'lib' << 'spec'
|
30
39
|
spec.pattern = 'spec/**/*_spec.rb'
|
@@ -35,12 +44,13 @@ task :spec => :check_dependencies
|
|
35
44
|
|
36
45
|
task :default => :spec
|
37
46
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
begin
|
48
|
+
require 'yard'
|
49
|
+
YARD::Rake::YardocTask.new do |y|
|
50
|
+
y.files << '-' << 'CHANGELOG.*'
|
51
|
+
end
|
52
|
+
rescue LoadError
|
53
|
+
task :yardoc do
|
54
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
55
|
+
end
|
46
56
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/ftp_service.gemspec
CHANGED
@@ -5,29 +5,31 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ftp_service}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Blake"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-08}
|
13
13
|
s.description = %q{An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.}
|
14
14
|
s.email = %q{justin@megablaix.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.markdown"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
-
".
|
21
|
-
".
|
20
|
+
".gitignore",
|
21
|
+
"CHANGELOG.markdown",
|
22
22
|
"LICENSE",
|
23
|
-
"README.
|
23
|
+
"README.markdown",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"ftp_service.gemspec",
|
27
27
|
"lib/ftp_service.rb",
|
28
|
+
"lib/tempfile_helper.rb",
|
28
29
|
"spec/ftp_service_spec.rb",
|
29
30
|
"spec/spec.opts",
|
30
|
-
"spec/spec_helper.rb"
|
31
|
+
"spec/spec_helper.rb",
|
32
|
+
"spec/tempfile_helper_spec.rb"
|
31
33
|
]
|
32
34
|
s.homepage = %q{http://github.com/blaix/ftp_service}
|
33
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -36,7 +38,8 @@ Gem::Specification.new do |s|
|
|
36
38
|
s.summary = %q{A class for dealing with the worst possible type of "web" service.}
|
37
39
|
s.test_files = [
|
38
40
|
"spec/ftp_service_spec.rb",
|
39
|
-
"spec/spec_helper.rb"
|
41
|
+
"spec/spec_helper.rb",
|
42
|
+
"spec/tempfile_helper_spec.rb"
|
40
43
|
]
|
41
44
|
|
42
45
|
if s.respond_to? :specification_version then
|
@@ -46,13 +49,16 @@ Gem::Specification.new do |s|
|
|
46
49
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
50
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
48
51
|
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
52
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
49
53
|
else
|
50
54
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
51
55
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
56
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
52
57
|
end
|
53
58
|
else
|
54
59
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
55
60
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
61
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
data/lib/ftp_service.rb
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
require 'net/ftp'
|
2
|
+
require 'tempfile_helper'
|
2
3
|
|
3
4
|
# Class for dealing with a service that acts like a web service, except
|
4
5
|
# over FTP. Meaning an xml request is uploaded as a file, and the
|
5
6
|
# response xml is downloaded as another file.
|
7
|
+
#
|
8
|
+
# Typical usage:
|
9
|
+
#
|
10
|
+
# FtpService.open('host', 'user', 'pass') do |service|
|
11
|
+
# path = '/the/remote/path'
|
12
|
+
# service.write_request("#{path}/request.xml", '<foo>bar</foo>')
|
13
|
+
# response = service.read_response("#{path}/response.xml")
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# or (the sucky way):
|
17
|
+
#
|
18
|
+
# path = '/the/remote/path'
|
19
|
+
# service = FtpService.new('host', 'user', 'pass')
|
20
|
+
# service.write_request("#{path}/request.xml", '<foo>bar</foo>')
|
21
|
+
# response = service.read_response("#{path}/response.xml")
|
22
|
+
# service.close
|
6
23
|
class FtpService
|
7
24
|
|
8
25
|
# Open a connection to the FTP server and return an FtpService object.
|
9
|
-
# The object must be closed explicitely.
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# ftp_service.write_request(path, request)
|
13
|
-
# response = ftp_service.read_response(path)
|
14
|
-
# ftp_service.close
|
26
|
+
# The object must be closed explicitely. See FtpServier#open for a
|
27
|
+
# better way to do this that will automatically close the connection,
|
28
|
+
# even if an exception is raised.
|
15
29
|
def initialize(host, user, pass)
|
16
30
|
@ftp = Net::FTP.open(host, user, pass)
|
17
31
|
end
|
@@ -19,11 +33,6 @@ class FtpService
|
|
19
33
|
# Open a connection and pass an FtpService instance to the block. The
|
20
34
|
# instance will be closed when the block finishes, or when an
|
21
35
|
# exception is raised.
|
22
|
-
#
|
23
|
-
# FtpService.open(host, user, pass) do |ftp_service|
|
24
|
-
# ftp_service.write_request(path, request)
|
25
|
-
# response = ftp_service.read_response(path)
|
26
|
-
# end
|
27
36
|
def self.open(host, user, pass)
|
28
37
|
instance = new(host, user, pass)
|
29
38
|
begin
|
@@ -33,6 +42,21 @@ class FtpService
|
|
33
42
|
end
|
34
43
|
end
|
35
44
|
|
45
|
+
# Write `request` to a local temp file and upload it to `remote_path`
|
46
|
+
# on the FTP server.
|
47
|
+
def write_request(request, remote_path)
|
48
|
+
tmp = TempfileHelper.write(request, 'request')
|
49
|
+
@ftp.puttextfile(tmp.path, remote_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Download the file at `remote_path` from the FTP server to a local
|
53
|
+
# temp file and return its contents.
|
54
|
+
def read_response(remote_path)
|
55
|
+
TempfileHelper.read('response') do |tmp|
|
56
|
+
@ftp.gettextfile(remote_path, tmp.path)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
36
60
|
# Close the connection to the FTP server.
|
37
61
|
def close
|
38
62
|
@ftp.close
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module TempfileHelper
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def read(name = nil)
|
7
|
+
tempfile = nil
|
8
|
+
name ||= Time.now.to_f
|
9
|
+
Tempfile.open(name) { |tempfile| yield(tempfile) }
|
10
|
+
File.read(tempfile.path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(content, name = nil)
|
14
|
+
name ||= Time.now.to_f.to_s
|
15
|
+
file = Tempfile.new(name)
|
16
|
+
file.write(content)
|
17
|
+
file.close
|
18
|
+
file
|
19
|
+
end
|
20
|
+
end
|
data/spec/ftp_service_spec.rb
CHANGED
@@ -7,35 +7,35 @@ describe "FtpService" do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe '.new(host, user, pass)' do
|
10
|
-
it '
|
10
|
+
it 'connects to the requested ftp server' do
|
11
11
|
Net::FTP.expects(:open).with('host', 'user', 'pass').returns(@ftp)
|
12
12
|
FtpService.new('host', 'user', 'pass')
|
13
13
|
end
|
14
14
|
|
15
|
-
it '
|
15
|
+
it 'returns an instance of the ftp service' do
|
16
16
|
service = FtpService.new('host', 'user', 'pass')
|
17
17
|
service.should be_a(FtpService)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '.open(host, user, pass)' do
|
22
|
-
it '
|
22
|
+
it 'connects to the requested ftp server' do
|
23
23
|
Net::FTP.expects(:open).with('host', 'user', 'pass').returns(@ftp)
|
24
24
|
FtpService.open('host', 'user', 'pass') {}
|
25
25
|
end
|
26
26
|
|
27
|
-
it '
|
27
|
+
it 'yields an instance of the ftp service' do
|
28
28
|
service = nil
|
29
29
|
FtpService.open('host', 'user', 'pass') { |service| }
|
30
30
|
service.should be_a(FtpService)
|
31
31
|
end
|
32
32
|
|
33
|
-
it '
|
33
|
+
it 'automatically closes the connection' do
|
34
34
|
@ftp.expects(:close)
|
35
35
|
FtpService.open('host', 'user', 'pass') {}
|
36
36
|
end
|
37
37
|
|
38
|
-
it '
|
38
|
+
it 'closes the connection even if an exception is raised' do
|
39
39
|
@ftp.expects(:close)
|
40
40
|
lambda {
|
41
41
|
FtpService.open('host', 'user', 'pass') { raise "boom" }
|
@@ -43,8 +43,43 @@ describe "FtpService" do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
describe '#write_request(path, request)' do
|
47
|
+
before do
|
48
|
+
@tempfile = stub('tempfile', :path => '/local/path')
|
49
|
+
@service = FtpService.new('host', 'user', 'pass')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "saves the request to a temp file" do
|
53
|
+
TempfileHelper.expects(:write).with('request', optionally(anything)).returns(@tempfile)
|
54
|
+
@service.write_request('request', '/remote/path')
|
55
|
+
end
|
56
|
+
|
57
|
+
it "uploads the request to `path` on the FTP server" do
|
58
|
+
TempfileHelper.stubs(:write).returns(@tempfile)
|
59
|
+
@ftp.expects(:puttextfile).with('/local/path', '/remote/path')
|
60
|
+
@service.write_request('request', '/remote/path')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#read_response(path)' do
|
65
|
+
before do
|
66
|
+
tempfile = stub('tempfile', :path => '/local/path')
|
67
|
+
TempfileHelper.stubs(:read).returns('response').yields(tempfile)
|
68
|
+
@service = FtpService.new('host', 'user', 'pass')
|
69
|
+
end
|
70
|
+
|
71
|
+
it "downloads the response at `path` from the FTP server" do
|
72
|
+
@ftp.expects(:gettextfile).with('/remote/path', '/local/path')
|
73
|
+
@service.read_response('/remote/path')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns the contents of the downloaded response" do
|
77
|
+
@service.read_response('/remote/path').should == "response"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
46
81
|
describe '#close' do
|
47
|
-
it '
|
82
|
+
it 'closes the connection to the ftp server' do
|
48
83
|
@ftp.expects(:close)
|
49
84
|
FtpService.new('host', 'user', 'pass').close
|
50
85
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'tempfile_helper'
|
3
|
+
|
4
|
+
describe "TempfileHelper" do
|
5
|
+
describe '.read([name]) { |tempfile| }' do
|
6
|
+
before do
|
7
|
+
@tempfile = nil
|
8
|
+
TempfileHelper.read { |@tempfile| }
|
9
|
+
end
|
10
|
+
|
11
|
+
it "yields a Tempfile object" do
|
12
|
+
@tempfile.should be_a(Tempfile)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "closes the tempfile object after the block executes" do
|
16
|
+
@tempfile.should be_closed
|
17
|
+
end
|
18
|
+
|
19
|
+
it "closes the tempfile object even if an exception is raised" do
|
20
|
+
tempfile = nil
|
21
|
+
lambda {
|
22
|
+
TempfileHelper.read { |tempfile| raise "boom" }
|
23
|
+
}.should raise_error
|
24
|
+
tempfile.should be_closed
|
25
|
+
end
|
26
|
+
|
27
|
+
it "accepts an optional name for the tempfile" do
|
28
|
+
tempfile = nil
|
29
|
+
TempfileHelper.read('the_name') { |tempfile| }
|
30
|
+
tempfile.path.should include('the_name')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns contents of the tempfile after the block is executed" do
|
34
|
+
TempfileHelper.read do |tempfile|
|
35
|
+
tempfile.write('the contents')
|
36
|
+
end.should == 'the contents'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.write_temp_file(content[, name])' do
|
41
|
+
before do
|
42
|
+
@tempfile = TempfileHelper.write('the content')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns a tempfile object" do
|
46
|
+
@tempfile.should be_a(Tempfile)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "writes the passed content to the temp file" do
|
50
|
+
File.read(@tempfile.path).should == 'the content'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "closes the tempfile object" do
|
54
|
+
@tempfile.should be_closed
|
55
|
+
end
|
56
|
+
|
57
|
+
it "accepts an optional name for the temp file" do
|
58
|
+
tempfile = TempfileHelper.write('the content', 'the_name')
|
59
|
+
tempfile.path.should include('the_name')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Justin Blake
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-08 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -45,6 +45,18 @@ dependencies:
|
|
45
45
|
version: 0.9.8
|
46
46
|
type: :development
|
47
47
|
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: yard
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id003
|
48
60
|
description: An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.
|
49
61
|
email: justin@megablaix.com
|
50
62
|
executables: []
|
@@ -53,19 +65,21 @@ extensions: []
|
|
53
65
|
|
54
66
|
extra_rdoc_files:
|
55
67
|
- LICENSE
|
56
|
-
- README.
|
68
|
+
- README.markdown
|
57
69
|
files:
|
58
|
-
- .document
|
59
70
|
- .gitignore
|
71
|
+
- CHANGELOG.markdown
|
60
72
|
- LICENSE
|
61
|
-
- README.
|
73
|
+
- README.markdown
|
62
74
|
- Rakefile
|
63
75
|
- VERSION
|
64
76
|
- ftp_service.gemspec
|
65
77
|
- lib/ftp_service.rb
|
78
|
+
- lib/tempfile_helper.rb
|
66
79
|
- spec/ftp_service_spec.rb
|
67
80
|
- spec/spec.opts
|
68
81
|
- spec/spec_helper.rb
|
82
|
+
- spec/tempfile_helper_spec.rb
|
69
83
|
has_rdoc: true
|
70
84
|
homepage: http://github.com/blaix/ftp_service
|
71
85
|
licenses: []
|
@@ -99,3 +113,4 @@ summary: A class for dealing with the worst possible type of "web" service.
|
|
99
113
|
test_files:
|
100
114
|
- spec/ftp_service_spec.rb
|
101
115
|
- spec/spec_helper.rb
|
116
|
+
- spec/tempfile_helper_spec.rb
|
data/.document
DELETED
data/README.rdoc
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
= FTP Service
|
2
|
-
|
3
|
-
An FTP Service is like a web service except stupid. You send your
|
4
|
-
request by uploading an xml file and get your response by downloading
|
5
|
-
another xml file. Have you ever had to deal with something like that? I
|
6
|
-
have.
|
7
|
-
|
8
|
-
== Installation
|
9
|
-
|
10
|
-
gem install ftp_service
|
11
|
-
|
12
|
-
== Usage
|
13
|
-
|
14
|
-
require 'ftp_service'
|
15
|
-
|
16
|
-
FtpService.open('host', 'user', 'pass') do |service|
|
17
|
-
path = '/the/remote/path'
|
18
|
-
service.write_request("#{path}/request.xml", '<foo>bar</foo>')
|
19
|
-
response = service.read_response("#{path}/response.xml")
|
20
|
-
end
|
21
|
-
|
22
|
-
* +read_response+ will block while it polls the server waiting for a
|
23
|
-
response.
|
24
|
-
* Temp files are created for the local request and response files and
|
25
|
-
deleted when no longer needed.
|
26
|
-
|
27
|
-
== Note on Patches/Pull Requests
|
28
|
-
|
29
|
-
* Fork the project.
|
30
|
-
* Make your feature addition or bug fix.
|
31
|
-
* Add tests for it. This is important so I don't break it in a
|
32
|
-
future version unintentionally.
|
33
|
-
* Commit, do not mess with rakefile, version, or history. (if you want
|
34
|
-
to have your own version, that is fine but bump version in a commit by
|
35
|
-
itself I can ignore when I pull)
|
36
|
-
* Send me a pull request. Bonus points for topic branches.
|
37
|
-
|
38
|
-
== Copyright
|
39
|
-
|
40
|
-
Copyright (c) 2010 Justin Blake. See LICENSE for details.
|