firefly 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.sqlite3
2
+ config.ru
3
+ pkg
data/HISTORY ADDED
@@ -0,0 +1,3 @@
1
+ = 0.1 / 2010-03-28
2
+
3
+ * First official release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ariejan de Vroom
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # FireFly
2
+
3
+ FireFly is a simple URL shortener for personal use.
4
+
5
+ # Installation
6
+
7
+ sudo gem install firefly
8
+
9
+ After you have installed the Firefly gem you should create a `config.ru` file that tells your webserver what to do. Here is a sample `config.ru`:
10
+
11
+ require 'rubygems'
12
+ require 'firefly'
13
+
14
+ disable :run
15
+
16
+ app = Firefly::Server.new do
17
+ set :hostname, "localhost:3000"
18
+ set :api_key, "test"
19
+
20
+ # Use Sqlite3 by default
21
+ set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3"
22
+
23
+ # You can use MySQL as well.
24
+ # Make sure to install the do_mysql gem:
25
+ # sudo gem install do_mysql
26
+ # set :database, "mysql://root@localhost/firefly"
27
+ end
28
+
29
+ run app
30
+
31
+ Next you can start your web server. You may try thin:
32
+
33
+ thin start -R config.ru
34
+
35
+ # Configuration
36
+
37
+ All configuration is done in `config.ru`.
38
+
39
+ * `:hostname` sets the hostname to use for shortened URLs.
40
+ * `:api_key` sets the API key. This key is required when posting new URLs
41
+ * `:database` a database URI that [DataMapper][1] can understand.
42
+
43
+ It's possible to use all kinds of backends with DataMapper. Sqlite3 and MySQL have been tested, but others like MongoDB may work as well.
44
+
45
+ [1]: http://datamapper.org/
46
+
47
+ # Usage
48
+
49
+ Adding a URL is done by doing a simple POST request that includes the URL and your API key.
50
+
51
+ curl -d "url=http://ariejan.net" -d "api_key=test" http://localhost:3000/api/add
52
+
53
+ If you're on a MacOSX you could add the following function to your `~/.profile` to automate URL shortening:
54
+
55
+ shorten(){
56
+ URL=$1
57
+ SHORT_URL=`curl -s -d "url=$URL&api_key=test" http://localhost:3000/api/add`
58
+ echo $SHORT_URL | pbcopy
59
+
60
+ echo "-- $URL => $SHORT_URL"
61
+ echo "Short URL copied to clipboard."
62
+ }
63
+
64
+ After you restart Terminal.app (or at least reload the `.profile` file) you can use it like this:
65
+
66
+ $ shorten http://ariejan.net
67
+ -- http://ariejan.net => http://aj.gs/1
68
+ Short URL copied to clipboard.
69
+
70
+ # Bugs, Feature Requests, etc.
71
+
72
+ * [Source][2]
73
+ * [Issue tracker][3]
74
+
75
+ Feel free to fork Firefly and create patches for it. Here are some basic instructions:
76
+
77
+ * Fork the project.
78
+ * Make your feature addition or bug fix.
79
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
80
+ * Commit, do not mess with Rakefile, VERSION, or HISTORY. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
81
+ * Send me a pull request. Bonus points for topic branches.
82
+
83
+ # License
84
+
85
+ Copyright (c) 2009 Ariejan de Vroom
86
+
87
+ Permission is hereby granted, free of charge, to any person obtaining
88
+ a copy of this software and associated documentation files (the
89
+ "Software"), to deal in the Software without restriction, including
90
+ without limitation the rights to use, copy, modify, merge, publish,
91
+ distribute, sublicense, and/or sell copies of the Software, and to
92
+ permit persons to whom the Software is furnished to do so, subject to
93
+ the following conditions:
94
+
95
+ The above copyright notice and this permission notice shall be
96
+ included in all copies or substantial portions of the Software.
97
+
98
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
99
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
100
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
101
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
102
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
103
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
104
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
105
+
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "firefly"
8
+ gemspec.summary = "FireFly is a simple URL shortner for personal use"
9
+ gemspec.description = "FireFly is a simple URL shortner for personal use. It's powered by Sinatra and can be run with any Rack-capable web server."
10
+ gemspec.email = "ariejan@ariejan.net"
11
+ gemspec.homepage = "http://github.com/ariejan/firefly"
12
+ gemspec.authors = ["Ariejan de Vroom"]
13
+ gemspec.rubyforge_project = 'firefly'
14
+ gemspec.add_dependency('sinatra', '>= 1.0')
15
+ gemspec.add_dependency('dm-core', '>= 0.10.2')
16
+ gemspec.add_dependency('dm-aggregates', '>= 0.10.2')
17
+ gemspec.add_dependency('do_sqlite3', '>= 0.10.1.1')
18
+
19
+ gemspec.add_development_dependency('rspec', '>= 1.3.0')
20
+ gemspec.add_development_dependency('rack-test', '>= 0.5.3')
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ require 'spec/rake/spectask'
28
+ Spec::Rake::SpecTask.new(:spec) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.spec_files = FileList['spec/**/*_spec.rb']
31
+ end
32
+
33
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
34
+ spec.libs << 'lib' << 'spec'
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :spec => :check_dependencies
40
+
41
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/config.ru.example ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'firefly'
3
+
4
+ disable :run
5
+
6
+ app = Firefly::Server.new do
7
+ set :hostname, "localhost:3000"
8
+ set :api_key, "test"
9
+
10
+ # Use Sqlite3 by default
11
+ set :database, "sqlite3://#{Dir.pwd}/firefly.sqlite3"
12
+
13
+ # You can use MySQL as well.
14
+ # Make sure to install the do_mysql gem:
15
+ # sudo gem install do_mysql
16
+ # set :database, "mysql://root@localhost/firefly"
17
+ end
18
+
19
+ run app
data/firefly.gemspec ADDED
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{firefly}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ariejan de Vroom"]
12
+ s.date = %q{2010-03-28}
13
+ s.description = %q{FireFly is a simple URL shortner for personal use. It's powered by Sinatra and can be run with any Rack-capable web server.}
14
+ s.email = %q{ariejan@ariejan.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "HISTORY",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "config.ru.example",
27
+ "firefly.gemspec",
28
+ "lib/firefly.rb",
29
+ "lib/firefly/base62.rb",
30
+ "lib/firefly/config.rb",
31
+ "lib/firefly/server.rb",
32
+ "lib/firefly/url.rb",
33
+ "spec/firefly_spec.rb",
34
+ "spec/spec.opts",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/ariejan/firefly}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubyforge_project = %q{firefly}
41
+ s.rubygems_version = %q{1.3.6}
42
+ s.summary = %q{FireFly is a simple URL shortner for personal use}
43
+ s.test_files = [
44
+ "spec/firefly_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<sinatra>, [">= 1.0"])
54
+ s.add_runtime_dependency(%q<dm-core>, [">= 0.10.2"])
55
+ s.add_runtime_dependency(%q<dm-aggregates>, [">= 0.10.2"])
56
+ s.add_runtime_dependency(%q<do_sqlite3>, [">= 0.10.1.1"])
57
+ s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
58
+ s.add_development_dependency(%q<rack-test>, [">= 0.5.3"])
59
+ else
60
+ s.add_dependency(%q<sinatra>, [">= 1.0"])
61
+ s.add_dependency(%q<dm-core>, [">= 0.10.2"])
62
+ s.add_dependency(%q<dm-aggregates>, [">= 0.10.2"])
63
+ s.add_dependency(%q<do_sqlite3>, [">= 0.10.1.1"])
64
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
65
+ s.add_dependency(%q<rack-test>, [">= 0.5.3"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<sinatra>, [">= 1.0"])
69
+ s.add_dependency(%q<dm-core>, [">= 0.10.2"])
70
+ s.add_dependency(%q<dm-aggregates>, [">= 0.10.2"])
71
+ s.add_dependency(%q<do_sqlite3>, [">= 0.10.1.1"])
72
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
73
+ s.add_dependency(%q<rack-test>, [">= 0.5.3"])
74
+ end
75
+ end
76
+
data/lib/firefly.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'dm-core'
4
+ require 'dm-aggregates'
5
+
6
+ $:.unshift(File.dirname(__FILE__)) unless
7
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
8
+
9
+ if ENV['RACK_ENV'] == 'development'
10
+ DataMapper::Logger.new($stdout, :debug)
11
+ end
12
+
13
+ require 'firefly/config'
14
+ require 'firefly/base62'
15
+ require 'firefly/url'
16
+ require 'firefly/server'
@@ -0,0 +1,26 @@
1
+ module Firefly
2
+ class Base62
3
+
4
+ CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split('')
5
+ BASE = 62
6
+
7
+ def self.encode(value)
8
+ s = []
9
+ while value >= BASE
10
+ value, rem = value.divmod(BASE)
11
+ s << CHARS[rem]
12
+ end
13
+ s << CHARS[value]
14
+ s.reverse.to_s
15
+ end
16
+
17
+ def self.decode(str)
18
+ str = str.split('').reverse
19
+ total = 0
20
+ str.each_with_index do |v,k|
21
+ total += (CHARS.index(v) * (BASE ** k))
22
+ end
23
+ total
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module Firefly
2
+ class Config < Hash
3
+
4
+ DEFAULTS = {
5
+ :hostname => "localhost:3000",
6
+ :api_key => "test",
7
+ :database => "sqlite3://#{Dir.pwd}/firefly_#{ENV['RACK_ENV']}.sqlite3"
8
+ }
9
+
10
+ def initialize obj
11
+ self.update DEFAULTS
12
+ self.update obj
13
+ end
14
+
15
+ def set key, val = nil, &blk
16
+ if val.is_a? Hash
17
+ self[key].update val
18
+ else
19
+ self[key] = block_given?? blk : val
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ require 'sinatra/base'
2
+
3
+ module Firefly
4
+ class Server < Sinatra::Base
5
+ set :sessions, false
6
+
7
+ attr_reader :config
8
+
9
+ def initialize config = {}, &blk
10
+ super
11
+ @config = config.is_a?(Config) ? config : Firefly::Config.new(config)
12
+ @config.instance_eval(&blk) if block_given?
13
+
14
+ begin
15
+ DataMapper.setup(:default, @config[:database])
16
+ DataMapper.auto_upgrade!
17
+ rescue
18
+ puts "Error setting up database connection. Please check the `database` setting in config.ru"
19
+ exit(1)
20
+ end
21
+ end
22
+
23
+ get '/' do
24
+ "Hello world!"
25
+ end
26
+
27
+ # POST /add?url=http://ariejan.net
28
+ #
29
+ # Returns the shortened URL
30
+ post '/api/add' do
31
+ if params[:api_key] != config[:api_key]
32
+ status 401
33
+ return "Permission denied: Invalid API key."
34
+ end
35
+
36
+ if params[:url].nil? || params[:url] == ""
37
+ "Invalid or no URL specified"
38
+ else
39
+ "http://#{config[:hostname]}/#{Firefly::Url.encode(params[:url])}"
40
+ end
41
+ end
42
+
43
+ # GET /b3d
44
+ #
45
+ # Redirect to the shortened URL
46
+ get '/:code' do
47
+ url = Firefly::Url.decode(params[:code])
48
+
49
+ if url.nil?
50
+ status 404
51
+ "Sorry, that code is unknown."
52
+ else
53
+ redirect url, 301
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,29 @@
1
+ module Firefly
2
+ class Url
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+ property :url, String, :index => true
7
+ property :code, String, :index => true
8
+ property :created_at, DateTime
9
+
10
+ # Encode a URL and return the encoded ID
11
+ def self.encode(url)
12
+
13
+ @result = self.first(:url => url)
14
+
15
+ if @result.nil?
16
+ @result = self.create(:url => url)
17
+ @result.update(:code => Firefly::Base62.encode(@result.id.to_i))
18
+ end
19
+
20
+ return @result.code
21
+ end
22
+
23
+ # Decode a code to the original URL
24
+ def self.decode(code)
25
+ @result = Firefly::Url.first(:code => code)
26
+ return @result.nil? ? nil : @result.url
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,89 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ require File.dirname(__FILE__) + '/spec_helper'
4
+
5
+ describe "Firefly" do
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ @@app
10
+ end
11
+
12
+ describe "/" do
13
+ it "should respond ok" do
14
+ get '/'
15
+ last_response.should be_ok
16
+ end
17
+ end
18
+
19
+ describe "adding a URL" do
20
+ it "should be okay adding a new URL" do
21
+ post '/api/add', :url => 'http://example.org', :api_key => 'test'
22
+ last_response.should be_ok
23
+ end
24
+
25
+ it "should return a 401 on a wrong API key" do
26
+ post '/api/add', :url => 'http://example.org', :api_key => 'false'
27
+ last_response.status.should eql(401)
28
+ end
29
+
30
+ it "should create a new Firefly::Url" do
31
+ lambda {
32
+ post '/api/add', :url => 'http://example.org', :api_key => 'test'
33
+ }.should change(Firefly::Url, :count).by(1)
34
+ end
35
+
36
+ it "should not create the same Firefly::Url twice" do
37
+ post '/api/add', :url => 'http://example.org', :api_key => 'test'
38
+
39
+ lambda {
40
+ post '/api/add', :url => 'http://example.org', :api_key => 'test'
41
+ }.should_not change(Firefly::Url, :count).by(1)
42
+ end
43
+ end
44
+
45
+ describe "Base62 encoding/decoding" do
46
+ [
47
+ [ 1, "1"],
48
+ [ 10, "a"],
49
+ [ 61, "Z"],
50
+ [ 62, "10"],
51
+ [ 63, "11"],
52
+ [ 124, "20"],
53
+ [200000000, "dxb8s"]
54
+ ].each do |input, output|
55
+ it "should encode #{input} correctly to #{output}" do
56
+ Firefly::Base62.encode(input).should eql(output)
57
+ end
58
+
59
+ it "should decode correctly" do
60
+ Firefly::Base62.decode(output).should eql(input)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "redirecting" do
66
+ it "should redirect to the original URL" do
67
+ fake = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
68
+
69
+ get '/alpha'
70
+ follow_redirect!
71
+
72
+ last_request.url.should eql('http://example.com/123')
73
+ end
74
+
75
+ it "should redirect with a 301 Permanent redirect" do
76
+ fake = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
77
+
78
+ get '/alpha'
79
+
80
+ last_response.status.should eql(301)
81
+ end
82
+
83
+ it "should throw a 404 when the code is unknown" do
84
+ get '/some_random_code_that_does_not_exist'
85
+
86
+ last_response.status.should eql(404)
87
+ end
88
+ end
89
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'firefly.rb')
2
+
3
+ require 'rubygems'
4
+ require 'sinatra'
5
+ require 'rack/test'
6
+ require 'spec'
7
+ require 'spec/autorun'
8
+ require 'spec/interop/test'
9
+
10
+ # set test environment
11
+ set :environment, :test
12
+ set :run, false
13
+ set :raise_errors, true
14
+ set :logging, false
15
+
16
+ @@app = Firefly::Server.new do
17
+ set :hostname, "test.host"
18
+ set :api_key, "test"
19
+ set :database, "sqlite3://#{Dir.pwd}/firefly_test.sqlite3"
20
+ end
21
+
22
+ Spec::Runner.configure do |config|
23
+ config.after(:each) do
24
+ repository do |r|
25
+ adapter = r.adapter
26
+ while adapter.current_transaction
27
+ adapter.current_transaction.rollback
28
+ adapter.pop_transaction
29
+ end
30
+ end
31
+ end
32
+
33
+ config.before(:each) do
34
+ repository do |r|
35
+ transaction = DataMapper::Transaction.new(r)
36
+ transaction.begin
37
+ r.adapter.push_transaction(transaction)
38
+ end
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: firefly
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Ariejan de Vroom
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-28 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ version: "1.0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: dm-core
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ - 10
43
+ - 2
44
+ version: 0.10.2
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: dm-aggregates
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ - 10
57
+ - 2
58
+ version: 0.10.2
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: do_sqlite3
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ - 10
71
+ - 1
72
+ - 1
73
+ version: 0.10.1.1
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: rspec
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 3
86
+ - 0
87
+ version: 1.3.0
88
+ type: :development
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: rack-test
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ - 5
100
+ - 3
101
+ version: 0.5.3
102
+ type: :development
103
+ version_requirements: *id006
104
+ description: FireFly is a simple URL shortner for personal use. It's powered by Sinatra and can be run with any Rack-capable web server.
105
+ email: ariejan@ariejan.net
106
+ executables: []
107
+
108
+ extensions: []
109
+
110
+ extra_rdoc_files:
111
+ - LICENSE
112
+ - README.md
113
+ files:
114
+ - .gitignore
115
+ - HISTORY
116
+ - LICENSE
117
+ - README.md
118
+ - Rakefile
119
+ - VERSION
120
+ - config.ru.example
121
+ - firefly.gemspec
122
+ - lib/firefly.rb
123
+ - lib/firefly/base62.rb
124
+ - lib/firefly/config.rb
125
+ - lib/firefly/server.rb
126
+ - lib/firefly/url.rb
127
+ - spec/firefly_spec.rb
128
+ - spec/spec.opts
129
+ - spec/spec_helper.rb
130
+ has_rdoc: true
131
+ homepage: http://github.com/ariejan/firefly
132
+ licenses: []
133
+
134
+ post_install_message:
135
+ rdoc_options:
136
+ - --charset=UTF-8
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ segments:
144
+ - 0
145
+ version: "0"
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ segments:
151
+ - 0
152
+ version: "0"
153
+ requirements: []
154
+
155
+ rubyforge_project: firefly
156
+ rubygems_version: 1.3.6
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: FireFly is a simple URL shortner for personal use
160
+ test_files:
161
+ - spec/firefly_spec.rb
162
+ - spec/spec_helper.rb