static_sync 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +27 -30
- data/bin/static_sync +1 -3
- data/lib/static_sync.rb +0 -7
- data/lib/static_sync/config.rb +6 -2
- data/lib/static_sync/meta.rb +25 -28
- data/lib/static_sync/meta/caching.rb +24 -0
- data/lib/static_sync/meta/compression.rb +38 -0
- data/lib/static_sync/storage.rb +30 -5
- data/lib/static_sync/version.rb +1 -1
- data/spec/fixtures/site/assets/images/spinner.gif +0 -0
- data/spec/fixtures/site/assets/stylesheets/screen.scss +0 -0
- data/spec/fixtures/site/cat.com/index.html +0 -0
- data/spec/meta/caching_spec.rb +75 -0
- data/spec/meta/compression_spec.rb +50 -0
- data/spec/meta_spec.rb +15 -40
- data/spec/storage_spec.rb +27 -14
- data/static_sync.gemspec +1 -1
- metadata +12 -4
data/README.md
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
# StaticSync
|
2
2
|
|
3
|
-
This gem provides a
|
4
|
-
[Amazon AWS](http://en.wikipedia.org/wiki/Amazon_S3#Hosting_entire_websites).
|
3
|
+
This gem provides a command line tool for uploading static websites to amazon/rackspace.
|
5
4
|
|
6
5
|
### Features
|
7
6
|
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
7
|
+
* Compares the md5 cheksum of each file before deciding to upload it.
|
8
|
+
* Automatically gzips non binary files.
|
9
|
+
* Sets appropriate HTTP metadata header information for serving html files.
|
10
|
+
* Content Type (text/css, image/png etc).
|
11
|
+
* Cache Control (public, max-age=31536000).
|
12
|
+
* Content Enconding (gzip).
|
13
|
+
|
14
|
+
## Requirements
|
15
|
+
|
16
|
+
* Ruby 1.9
|
11
17
|
|
12
18
|
## Installation
|
13
19
|
|
@@ -15,23 +21,36 @@ This gem provides a stand alone mechanism for uploading static websites to cloud
|
|
15
21
|
gem install static_sync
|
16
22
|
```
|
17
23
|
|
18
|
-
## Usage
|
24
|
+
## Example Usage
|
19
25
|
|
20
26
|
In your project directory create a `.static` file:
|
21
27
|
|
22
28
|
```
|
23
29
|
> cat .static
|
30
|
+
|
31
|
+
# Source directory
|
24
32
|
local:
|
25
|
-
directory: build
|
33
|
+
directory: build
|
26
34
|
|
35
|
+
# Target directory
|
27
36
|
remote:
|
28
37
|
provider: AWS
|
29
38
|
username: my-aws-key
|
30
39
|
password: my-aws-secret
|
31
40
|
directory: my-aws-bucket
|
41
|
+
|
42
|
+
# Number of seconds to cache each content type, defaults to no cache.
|
43
|
+
cache:
|
44
|
+
html: 31536000
|
45
|
+
javascript: 31536000
|
46
|
+
css: 31536000
|
47
|
+
image: 31536000
|
48
|
+
|
49
|
+
# Flag to enable / disable automatic gzip compression.
|
50
|
+
gzip: true
|
32
51
|
```
|
33
52
|
|
34
|
-
And run the following command any time you want to upload.
|
53
|
+
And simply run the following command any time you want to upload.
|
35
54
|
|
36
55
|
```bash
|
37
56
|
static_sync
|
@@ -49,28 +68,6 @@ remote:
|
|
49
68
|
directory: <%= ENV['s3_bucket'] %>
|
50
69
|
```
|
51
70
|
|
52
|
-
### Cache Control
|
53
|
-
|
54
|
-
By default uploaded files are not cached.
|
55
|
-
|
56
|
-
You can cache content for a given number of seconds by updating your `.static` file:
|
57
|
-
|
58
|
-
```
|
59
|
-
cache:
|
60
|
-
javascript: 31536000
|
61
|
-
css: 31536000
|
62
|
-
```
|
63
|
-
|
64
|
-
### Compression
|
65
|
-
|
66
|
-
By default uploaded files are not compressed.
|
67
|
-
|
68
|
-
You can gzip all non binary content by updating your `.static` file:
|
69
|
-
|
70
|
-
```
|
71
|
-
gzip: true
|
72
|
-
```
|
73
|
-
|
74
71
|
## Contributing
|
75
72
|
|
76
73
|
1. Fork it
|
data/bin/static_sync
CHANGED
data/lib/static_sync.rb
CHANGED
data/lib/static_sync/config.rb
CHANGED
data/lib/static_sync/meta.rb
CHANGED
@@ -1,45 +1,42 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
require "mime/types"
|
3
|
+
|
4
|
+
require_relative "meta/caching"
|
5
|
+
require_relative "meta/compression"
|
6
|
+
|
1
7
|
module StaticSync
|
2
8
|
class Meta
|
3
9
|
|
4
10
|
def initialize(config)
|
5
|
-
@config
|
11
|
+
@config = config
|
12
|
+
@compression = Compression.new(@config)
|
13
|
+
@caching = Caching.new(@config)
|
6
14
|
end
|
7
15
|
|
8
|
-
#TODO This class / method has too many responsibilities.
|
9
16
|
def for(file)
|
10
17
|
meta = {
|
11
|
-
:key
|
12
|
-
:body
|
13
|
-
:public
|
18
|
+
:key => file,
|
19
|
+
:body => File.new(file),
|
20
|
+
:public => true,
|
21
|
+
:storage_class => 'REDUCED_REDUNDANCY'
|
14
22
|
}
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
:body => gzip(file),
|
20
|
-
:content_encoding => 'gzip'
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
23
|
+
|
24
|
+
mime = MIME::Types::of(file).first
|
25
|
+
|
26
|
+
if mime
|
24
27
|
meta.merge!(
|
25
28
|
:content_type => MIME::Type.simplified(mime)
|
26
29
|
)
|
27
|
-
|
28
|
-
|
29
|
-
meta.merge!(
|
30
|
-
:cache_control => "public, max-age=#{expiry}"
|
31
|
-
)
|
32
|
-
end
|
30
|
+
meta.merge!(@compression.for(file, mime))
|
31
|
+
meta.merge!(@caching.for(file, mime))
|
33
32
|
end
|
34
|
-
meta
|
35
|
-
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
body = meta[:body].read
|
35
|
+
|
36
|
+
meta.merge!(
|
37
|
+
:etag => Digest::MD5.hexdigest(body), # A local version of the etag expected after upload.
|
38
|
+
:content_md5 => Digest::MD5.base64digest(body) # Enable checksum validation during uploads.
|
39
|
+
)
|
43
40
|
end
|
44
41
|
|
45
42
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module StaticSync
|
2
|
+
class Meta
|
3
|
+
class Caching
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
def for(file, mime)
|
10
|
+
meta = {}
|
11
|
+
type = mime.sub_type
|
12
|
+
type = mime.media_type if mime.media_type == "image"
|
13
|
+
if @config.cache.has_key?(type)
|
14
|
+
expiry = @config.cache[type].to_i
|
15
|
+
meta.merge!(
|
16
|
+
:cache_control => "public, max-age=#{expiry}"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
meta
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "zlib"
|
3
|
+
|
4
|
+
module StaticSync
|
5
|
+
class Meta
|
6
|
+
class Compression
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def for(file, mime)
|
13
|
+
meta = {}
|
14
|
+
if @config.gzip && !mime.binary?
|
15
|
+
meta.merge!(
|
16
|
+
:body => gzip(file),
|
17
|
+
:content_encoding => 'gzip'
|
18
|
+
)
|
19
|
+
end
|
20
|
+
meta
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def gzip(file)
|
26
|
+
zipped = Tempfile.new("static_sync")
|
27
|
+
Zlib::GzipWriter.open(zipped) do |archive|
|
28
|
+
# Gzip by default incorporates file creation time into the content.
|
29
|
+
# For the purpose of repeatable etag comparison we want avoid this.
|
30
|
+
archive.mtime = 1
|
31
|
+
archive.write File.read(file)
|
32
|
+
end
|
33
|
+
zipped
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/static_sync/storage.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "fog"
|
2
|
+
require "logger"
|
3
|
+
|
1
4
|
require_relative "meta"
|
2
5
|
|
3
6
|
module StaticSync
|
@@ -9,18 +12,40 @@ module StaticSync
|
|
9
12
|
end
|
10
13
|
|
11
14
|
def sync
|
15
|
+
remote_keys = []
|
16
|
+
remote_directory.files.each do |file|
|
17
|
+
remote_keys << [file.key, file.etag]
|
18
|
+
end
|
12
19
|
Dir.chdir(@config.source) do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
)
|
20
|
+
local_files.each do |file|
|
21
|
+
current_file = @meta.for(file)
|
22
|
+
current_file_key = [current_file[:key], current_file[:etag]]
|
23
|
+
|
24
|
+
unless remote_keys.include?(current_file_key)
|
25
|
+
log.info("Uploading #{file}") if @config.log
|
26
|
+
begin
|
27
|
+
remote_directory.files.create(current_file)
|
28
|
+
rescue => error
|
29
|
+
log.error("Failed to upload #{file}")
|
30
|
+
raise error
|
31
|
+
end
|
32
|
+
end
|
18
33
|
end
|
19
34
|
end
|
20
35
|
end
|
21
36
|
|
22
37
|
private
|
23
38
|
|
39
|
+
def local_files
|
40
|
+
Dir.glob("**/*.*").reject do |file|
|
41
|
+
File.directory?(file)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def remote_directory
|
46
|
+
@config.storage.directories.new(:key => @config.storage_directory)
|
47
|
+
end
|
48
|
+
|
24
49
|
def log
|
25
50
|
@log ||= begin
|
26
51
|
logger = Logger.new(STDOUT)
|
data/lib/static_sync/version.rb
CHANGED
Binary file
|
File without changes
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "mime/types"
|
2
|
+
require "./lib/static_sync/config"
|
3
|
+
require "./lib/static_sync/meta/caching"
|
4
|
+
|
5
|
+
describe StaticSync::Meta::Caching do
|
6
|
+
|
7
|
+
let(:config) { StaticSync::Config.new }
|
8
|
+
|
9
|
+
let(:html) { MIME::Type.new('text/html') }
|
10
|
+
let(:plain) { MIME::Type.new('text/plain') }
|
11
|
+
let(:css) { MIME::Type.new('text/css') }
|
12
|
+
let(:gif) { MIME::Type.new('image/gif') }
|
13
|
+
let(:jpg) { MIME::Type.new('image/jpg') }
|
14
|
+
let(:png) { MIME::Type.new('image/png') }
|
15
|
+
|
16
|
+
subject do
|
17
|
+
StaticSync::Meta::Caching.new(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when caching is completely disabled" do
|
21
|
+
|
22
|
+
before do
|
23
|
+
config['cache'] = { }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#for" do
|
27
|
+
it "does not set cache headers for html files" do
|
28
|
+
subject.for("index.html", html).should_not include(:cache_control)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when caching is enabled for html only" do
|
34
|
+
|
35
|
+
before do
|
36
|
+
config['cache'] = { 'html' => '86400' }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#for" do
|
40
|
+
it "sets cache headers for html files" do
|
41
|
+
subject.for("index.html", html).should include(:cache_control)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "does not set cache headers for text files" do
|
45
|
+
subject.for("data.txt", plain).should_not include(:cache_control)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "does not set cache headers for css files" do
|
49
|
+
subject.for("screen.css", css).should_not include(:cache_control)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when caching is enabled for images" do
|
55
|
+
|
56
|
+
before do
|
57
|
+
config['cache'] = { 'image' => '86400' }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#for" do
|
61
|
+
it "sets cache headers for gif files" do
|
62
|
+
subject.for("spinner.gif", gif).should include(:cache_control)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "sets cache headers for jpg files" do
|
66
|
+
subject.for("kitten.jpg", jpg).should include(:cache_control)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "sets cache headers for png files" do
|
70
|
+
subject.for("cat.png", png).should include(:cache_control)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "mime/types"
|
2
|
+
require "./lib/static_sync/config"
|
3
|
+
require "./lib/static_sync/meta/compression"
|
4
|
+
|
5
|
+
describe StaticSync::Meta::Compression do
|
6
|
+
|
7
|
+
let(:config) { StaticSync::Config.new }
|
8
|
+
|
9
|
+
let(:html) { MIME::Type.new('text/html') }
|
10
|
+
let(:image) { MIME::Type.new('image/gif') }
|
11
|
+
|
12
|
+
subject do
|
13
|
+
StaticSync::Meta::Compression.new(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
File.stub(:read).and_return("")
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when compression is disabled" do
|
21
|
+
|
22
|
+
before do
|
23
|
+
config['gzip'] = false
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#for" do
|
27
|
+
it "does not set compression headers for html files" do
|
28
|
+
subject.for("index.html", html).should_not include(:content_encoding => "gzip")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when compression is enabled" do
|
34
|
+
|
35
|
+
before do
|
36
|
+
config['gzip'] = true
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#for" do
|
40
|
+
it "sets compression headers for html files" do
|
41
|
+
subject.for("index.html", html).should include(:content_encoding => "gzip")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "does not set compression headers for binary files" do
|
45
|
+
subject.for("assets/images/spinner.gif", image).should_not include(:content_encoding => "gzip")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/spec/meta_spec.rb
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
require "cgi"
|
2
|
-
require "mime/types"
|
3
|
-
require "tempfile"
|
4
|
-
require "zlib"
|
5
1
|
require "./lib/static_sync/config"
|
6
2
|
require "./lib/static_sync/meta"
|
7
3
|
|
@@ -13,6 +9,21 @@ describe StaticSync::Meta do
|
|
13
9
|
StaticSync::Meta.new(config)
|
14
10
|
end
|
15
11
|
|
12
|
+
it "sets files as public" do
|
13
|
+
Dir.chdir("spec/fixtures/site") do
|
14
|
+
subject.for("index.html").should include(:public => true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sets appropriate content types for a range of common file types" do
|
19
|
+
Dir.chdir("spec/fixtures/site") do
|
20
|
+
subject.for("index.html").should include(:content_type => "text/html")
|
21
|
+
subject.for("assets/images/spinner.gif").should include(:content_type => "image/gif")
|
22
|
+
subject.for("assets/stylesheets/screen.css").should include(:content_type => "text/css")
|
23
|
+
subject.for("assets/javascripts/jquery.min.js").should include(:content_type => "application/javascript")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
16
27
|
describe "all files" do
|
17
28
|
|
18
29
|
it "should be public" do
|
@@ -35,41 +46,5 @@ describe StaticSync::Meta do
|
|
35
46
|
end
|
36
47
|
end
|
37
48
|
|
38
|
-
it "should cache files when requested" do
|
39
|
-
config['cache'] = {
|
40
|
-
'css' => '86400',
|
41
|
-
'javascript' => '86400'
|
42
|
-
}
|
43
|
-
Dir.chdir("spec/fixtures/site") do
|
44
|
-
subject.for("index.html").should_not include(
|
45
|
-
:cache_control
|
46
|
-
)
|
47
|
-
subject.for("assets/stylesheets/screen.css").should include(
|
48
|
-
:cache_control
|
49
|
-
)
|
50
|
-
subject.for("assets/javascripts/jquery.min.js").should include(
|
51
|
-
:cache_control
|
52
|
-
)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should gzip files when requested" do
|
57
|
-
Dir.chdir("spec/fixtures/site") do
|
58
|
-
subject.for("index.html").should_not include(
|
59
|
-
:content_encoding => 'gzip'
|
60
|
-
)
|
61
|
-
config['gzip'] = true
|
62
|
-
subject.for("index.html").should include(
|
63
|
-
:content_encoding => 'gzip'
|
64
|
-
)
|
65
|
-
subject.for("assets/stylesheets/screen.css").should include(
|
66
|
-
:content_encoding => 'gzip'
|
67
|
-
)
|
68
|
-
subject.for("assets/javascripts/jquery.min.js").should include(
|
69
|
-
:content_encoding => 'gzip'
|
70
|
-
)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
49
|
end
|
75
50
|
end
|
data/spec/storage_spec.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require "./lib/static_sync"
|
1
|
+
require "./lib/static_sync/config"
|
2
|
+
require "./lib/static_sync/storage"
|
2
3
|
|
3
4
|
describe StaticSync::Storage do
|
4
5
|
|
5
6
|
let(:config) do
|
6
7
|
StaticSync::Config.new.merge({
|
8
|
+
'log' => false,
|
7
9
|
'local' => {
|
8
10
|
'directory' => 'spec/fixtures/site'
|
9
11
|
},
|
@@ -22,28 +24,39 @@ describe StaticSync::Storage do
|
|
22
24
|
|
23
25
|
before do
|
24
26
|
Fog.mock!
|
25
|
-
config.storage.directories.create(
|
26
|
-
:key => config.storage_directory,
|
27
|
-
:public => true
|
28
|
-
)
|
29
27
|
end
|
30
28
|
|
31
29
|
after do
|
32
30
|
Fog::Mock.reset
|
33
31
|
end
|
34
32
|
|
35
|
-
|
33
|
+
context "with a remote storage directory" do
|
36
34
|
|
37
|
-
|
38
|
-
|
35
|
+
before do
|
36
|
+
config.storage.directories.create(
|
37
|
+
:key => config.storage_directory,
|
38
|
+
:public => true
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
context "syncing a new site" do
|
43
|
+
|
44
|
+
describe "#sync" do
|
39
45
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
it "sets a unique key for each uploaded file" do
|
47
|
+
subject.sync
|
48
|
+
|
49
|
+
config.storage.directories.get(config.storage_directory).files.map(&:key).should == [
|
50
|
+
"assets/images/spinner.gif",
|
51
|
+
"assets/javascripts/jquery.min.js",
|
52
|
+
"assets/stylesheets/screen.css",
|
53
|
+
"assets/stylesheets/screen.scss",
|
54
|
+
"cat.com/index.html",
|
55
|
+
"index.html"
|
56
|
+
]
|
57
|
+
end
|
58
|
+
end
|
45
59
|
end
|
46
60
|
|
47
61
|
end
|
48
|
-
|
49
62
|
end
|
data/static_sync.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = StaticSync::VERSION
|
9
9
|
gem.authors = ["Shanon McQuay"]
|
10
10
|
gem.email = ["shanonmcquay@gmail.com"]
|
11
|
-
gem.summary = %q{
|
11
|
+
gem.summary = %q{Command line tool for uploading static websites to amazon/rackspace.}
|
12
12
|
|
13
13
|
gem.files = `git ls-files`.split($/)
|
14
14
|
gem.bindir = "bin"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: static_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.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: 2013-
|
12
|
+
date: 2013-02-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -60,11 +60,18 @@ files:
|
|
60
60
|
- lib/static_sync.rb
|
61
61
|
- lib/static_sync/config.rb
|
62
62
|
- lib/static_sync/meta.rb
|
63
|
+
- lib/static_sync/meta/caching.rb
|
64
|
+
- lib/static_sync/meta/compression.rb
|
63
65
|
- lib/static_sync/storage.rb
|
64
66
|
- lib/static_sync/version.rb
|
67
|
+
- spec/fixtures/site/assets/images/spinner.gif
|
65
68
|
- spec/fixtures/site/assets/javascripts/jquery.min.js
|
66
69
|
- spec/fixtures/site/assets/stylesheets/screen.css
|
70
|
+
- spec/fixtures/site/assets/stylesheets/screen.scss
|
71
|
+
- spec/fixtures/site/cat.com/index.html
|
67
72
|
- spec/fixtures/site/index.html
|
73
|
+
- spec/meta/caching_spec.rb
|
74
|
+
- spec/meta/compression_spec.rb
|
68
75
|
- spec/meta_spec.rb
|
69
76
|
- spec/storage_spec.rb
|
70
77
|
- static_sync.gemspec
|
@@ -91,8 +98,9 @@ rubyforge_project:
|
|
91
98
|
rubygems_version: 1.8.23
|
92
99
|
signing_key:
|
93
100
|
specification_version: 3
|
94
|
-
summary:
|
101
|
+
summary: Command line tool for uploading static websites to amazon/rackspace.
|
95
102
|
test_files:
|
103
|
+
- spec/meta/caching_spec.rb
|
104
|
+
- spec/meta/compression_spec.rb
|
96
105
|
- spec/meta_spec.rb
|
97
106
|
- spec/storage_spec.rb
|
98
|
-
has_rdoc: false
|