static_sync 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +28 -10
- data/lib/static_sync/config.rb +20 -18
- data/lib/static_sync/processor.rb +15 -8
- data/lib/static_sync/storage.rb +20 -13
- data/lib/static_sync/storage_cache.rb +30 -0
- data/lib/static_sync/uploadable.rb +6 -2
- data/lib/static_sync/version.rb +1 -1
- data/spec/processor_spec.rb +55 -1
- data/spec/storage_cache_spec.rb +78 -0
- data/spec/uploadable_spec.rb +25 -8
- metadata +5 -2
data/README.md
CHANGED
@@ -21,13 +21,11 @@ This gem provides a command line tool for uploading static websites to amazon/ra
|
|
21
21
|
gem install static_sync
|
22
22
|
```
|
23
23
|
|
24
|
-
## Example Usage
|
24
|
+
## Example Command Line Usage
|
25
25
|
|
26
26
|
In your project directory create a `.static` file:
|
27
27
|
|
28
28
|
```
|
29
|
-
> cat .static
|
30
|
-
|
31
29
|
# What to upload
|
32
30
|
local:
|
33
31
|
directory: build
|
@@ -43,7 +41,7 @@ remote:
|
|
43
41
|
# Everything below this line is optional.
|
44
42
|
|
45
43
|
# What not to upload (ruby regular expression).
|
46
|
-
ignored: (psd
|
44
|
+
ignored: (psd|gz)$
|
47
45
|
|
48
46
|
# Number of seconds to cache each content type, defaults to no cache.
|
49
47
|
cache:
|
@@ -52,8 +50,11 @@ cache:
|
|
52
50
|
css: 31536000
|
53
51
|
image: 31536000
|
54
52
|
|
55
|
-
# If you wish to
|
56
|
-
|
53
|
+
# If you wish to prevent modification of existing files.
|
54
|
+
# conflict_mode: 'fail'
|
55
|
+
|
56
|
+
# If you wish to prevent modification of existing files that are cached.
|
57
|
+
# conflict_mode: 'fail_if_cached'
|
57
58
|
```
|
58
59
|
|
59
60
|
And simply run the following command any time you want to upload.
|
@@ -62,16 +63,33 @@ And simply run the following command any time you want to upload.
|
|
62
63
|
static_sync
|
63
64
|
```
|
64
65
|
|
65
|
-
|
66
|
+
## Example Ruby Project Usage
|
67
|
+
|
68
|
+
Very similar to the command line version except options can passed as a hash instead of being read from .static
|
69
|
+
|
70
|
+
```
|
71
|
+
require 'static_sync'
|
72
|
+
|
73
|
+
StaticSync.upload(
|
74
|
+
'local' => {
|
75
|
+
...
|
76
|
+
},
|
77
|
+
'remote' => {
|
78
|
+
...
|
79
|
+
}
|
80
|
+
)
|
81
|
+
```
|
82
|
+
|
83
|
+
## Environment Variables
|
66
84
|
|
67
85
|
You can reference environment variables in your `.static` file like this:
|
68
86
|
|
69
87
|
```
|
70
88
|
remote:
|
71
89
|
provider: AWS
|
72
|
-
username: <%= ENV['
|
73
|
-
password: <%= ENV['
|
74
|
-
directory: <%= ENV['
|
90
|
+
username: <%= ENV['S3_KEY'] %>
|
91
|
+
password: <%= ENV['S3_SECRET'] %>
|
92
|
+
directory: <%= ENV['S3_BUCKET'] %>
|
75
93
|
```
|
76
94
|
|
77
95
|
## Contributing
|
data/lib/static_sync/config.rb
CHANGED
@@ -7,38 +7,40 @@ module StaticSync
|
|
7
7
|
self.fetch('log', true)
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
self.fetch('
|
10
|
+
def local
|
11
|
+
self.fetch('local', {})
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
self.
|
14
|
+
def local_directory
|
15
|
+
self.local['directory']
|
16
16
|
end
|
17
17
|
|
18
18
|
def remote
|
19
19
|
self.fetch('remote', {})
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
self.fetch('local', {})['directory']
|
24
|
-
end
|
25
|
-
|
26
|
-
def target
|
22
|
+
def remote_directory
|
27
23
|
self.remote['directory']
|
28
24
|
end
|
29
25
|
|
30
|
-
def
|
31
|
-
|
32
|
-
:persistent => true,
|
33
|
-
:provider => self.remote['provider'],
|
34
|
-
:region => self.remote['region'],
|
35
|
-
:aws_access_key_id => self.remote['username'],
|
36
|
-
:aws_secret_access_key => self.remote['password']
|
37
|
-
})
|
26
|
+
def cache
|
27
|
+
self.fetch('cache', {})
|
38
28
|
end
|
39
29
|
|
40
30
|
def ignored
|
41
|
-
self
|
31
|
+
self.fetch('ignored', nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def conflict_mode
|
35
|
+
self.fetch('conflict_mode', 'overwrite')
|
36
|
+
end
|
37
|
+
|
38
|
+
def fail_on_conflict?
|
39
|
+
conflict_mode == 'fail'
|
40
|
+
end
|
41
|
+
|
42
|
+
def fail_on_conflict_if_cached?
|
43
|
+
conflict_mode == 'fail_if_cached'
|
42
44
|
end
|
43
45
|
|
44
46
|
def load(path = '.static')
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "fog"
|
2
1
|
require "logger"
|
3
2
|
|
4
3
|
require_relative "storage"
|
@@ -7,7 +6,7 @@ require_relative "uploadable"
|
|
7
6
|
module StaticSync
|
8
7
|
class Processor
|
9
8
|
|
10
|
-
class
|
9
|
+
class ConflictError < StandardError
|
11
10
|
end
|
12
11
|
|
13
12
|
def initialize(config, storage = nil)
|
@@ -16,17 +15,14 @@ module StaticSync
|
|
16
15
|
end
|
17
16
|
|
18
17
|
def sync
|
19
|
-
log.info("Synching #{@config.
|
20
|
-
Dir.chdir(@config.
|
18
|
+
log.info("Synching #{@config.local_directory} to #{@config.remote_directory}.") if @config.log
|
19
|
+
Dir.chdir(@config.local_directory) do
|
21
20
|
local_filtered_files.each do |file|
|
22
21
|
current_file = Uploadable.new(file, @config)
|
23
22
|
|
24
23
|
unless @storage.has_version?(current_file.version)
|
25
24
|
if @storage.has_file?(current_file.version)
|
26
|
-
|
27
|
-
if @config.immutable_mode
|
28
|
-
raise ImmutableError, "immutable_mode does not allow modifications to existing files."
|
29
|
-
end
|
25
|
+
handle_conflict(current_file)
|
30
26
|
else
|
31
27
|
log.info("Uploading #{file}") if @config.log
|
32
28
|
end
|
@@ -42,6 +38,17 @@ module StaticSync
|
|
42
38
|
log.info("Synching done.") if @config.log
|
43
39
|
end
|
44
40
|
|
41
|
+
def handle_conflict(file)
|
42
|
+
log.info("Overwriting #{file}") if @config.log
|
43
|
+
if @config.fail_on_conflict?
|
44
|
+
raise ConflictError, "modifications to existing files are not allowed."
|
45
|
+
elsif @config.fail_on_conflict_if_cached?
|
46
|
+
if file.cached?
|
47
|
+
raise ConflictError, "modifications to existing cached files are not allowed."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
45
52
|
def local_filtered_files
|
46
53
|
local_files.reject do |file|
|
47
54
|
file =~ Regexp.new(@config.ignored) if @config.ignored
|
data/lib/static_sync/storage.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
require "fog"
|
2
|
-
require "logger"
|
3
2
|
|
4
3
|
module StaticSync
|
5
4
|
class Storage
|
6
5
|
|
7
|
-
class Version < Struct.new(:path, :etag)
|
8
|
-
end
|
9
|
-
|
10
6
|
def initialize(config)
|
11
7
|
@config = config
|
12
8
|
|
@@ -14,20 +10,21 @@ module StaticSync
|
|
14
10
|
end
|
15
11
|
|
16
12
|
def has_file?(version)
|
17
|
-
|
13
|
+
cache.has_file?(version)
|
18
14
|
end
|
19
15
|
|
20
16
|
def has_version?(version)
|
21
|
-
|
17
|
+
cache.has_version?(version)
|
22
18
|
end
|
23
19
|
|
24
|
-
def
|
25
|
-
@
|
26
|
-
|
20
|
+
def cache
|
21
|
+
@cache ||= begin
|
22
|
+
versions = []
|
27
23
|
remote_directory.files.each do |file|
|
28
|
-
|
24
|
+
versions << StorageCache::Version.new(file.key, file.etag)
|
29
25
|
end
|
30
|
-
|
26
|
+
versions
|
27
|
+
StorageCache.new(versions)
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
@@ -38,11 +35,21 @@ module StaticSync
|
|
38
35
|
private
|
39
36
|
|
40
37
|
def remote_directory
|
41
|
-
|
38
|
+
storage.directories.new(:key => @config.remote['directory'])
|
42
39
|
end
|
43
40
|
|
44
41
|
def validate_credentials!
|
45
|
-
|
42
|
+
storage.get_bucket(@config.remote['directory'])
|
43
|
+
end
|
44
|
+
|
45
|
+
def storage
|
46
|
+
Fog::Storage.new({
|
47
|
+
:persistent => true,
|
48
|
+
:provider => @config.remote['provider'],
|
49
|
+
:region => @config.remote['region'],
|
50
|
+
:aws_access_key_id => @config.remote['username'],
|
51
|
+
:aws_secret_access_key => @config.remote['password']
|
52
|
+
})
|
46
53
|
end
|
47
54
|
|
48
55
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module StaticSync
|
2
|
+
class StorageCache
|
3
|
+
|
4
|
+
class Version < Struct.new(:path, :etag)
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(versions)
|
8
|
+
@versions = versions
|
9
|
+
end
|
10
|
+
|
11
|
+
def has_file?(file)
|
12
|
+
@versions.any? do |version|
|
13
|
+
file.path == version.path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_version?(file)
|
18
|
+
@versions.any? do |version|
|
19
|
+
file.path == version.path && file.etag == version.etag
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_conflict?(file)
|
24
|
+
@versions.any? do |version|
|
25
|
+
file.path == version.path && file.etag != version.etag
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -4,13 +4,13 @@ require "mime/types"
|
|
4
4
|
require "tempfile"
|
5
5
|
require "zlib"
|
6
6
|
|
7
|
-
require_relative "
|
7
|
+
require_relative "storage_cache"
|
8
8
|
|
9
9
|
module StaticSync
|
10
10
|
class Uploadable < Struct.new(:path, :config)
|
11
11
|
|
12
12
|
def version
|
13
|
-
|
13
|
+
StorageCache::Version.new(path, etag)
|
14
14
|
end
|
15
15
|
|
16
16
|
def mime
|
@@ -33,6 +33,10 @@ module StaticSync
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def cached?
|
37
|
+
!cache_time.nil?
|
38
|
+
end
|
39
|
+
|
36
40
|
def cache_time
|
37
41
|
if mime
|
38
42
|
type = mime.sub_type
|
data/lib/static_sync/version.rb
CHANGED
data/spec/processor_spec.rb
CHANGED
@@ -18,6 +18,60 @@ describe StaticSync::Processor do
|
|
18
18
|
StaticSync::Processor.new(config, storage)
|
19
19
|
end
|
20
20
|
|
21
|
+
describe "#handle_conflict" do
|
22
|
+
let(:file) { stub }
|
23
|
+
|
24
|
+
context "when in overwrite mode" do
|
25
|
+
let(:config) do
|
26
|
+
StaticSync::Config.new.merge({
|
27
|
+
'conflict_mode' => 'overwrite'
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does nothing" do
|
32
|
+
subject.handle_conflict(file)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when in fail mode" do
|
37
|
+
let(:config) do
|
38
|
+
StaticSync::Config.new.merge({
|
39
|
+
'conflict_mode' => 'fail'
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
it "raises a conflict error" do
|
44
|
+
expect {
|
45
|
+
subject.handle_conflict(file)
|
46
|
+
}.to raise_error(StaticSync::Processor::ConflictError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when in fail on cache mode" do
|
51
|
+
let(:file) { stub(:cached? => false) }
|
52
|
+
|
53
|
+
let(:config) do
|
54
|
+
StaticSync::Config.new.merge({
|
55
|
+
'conflict_mode' => 'fail_if_cached'
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
it "does nothing by default" do
|
60
|
+
subject.handle_conflict(file)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the file is cached" do
|
64
|
+
let(:file) { stub(:cached? => true) }
|
65
|
+
|
66
|
+
it "raises a conflict error" do
|
67
|
+
expect {
|
68
|
+
subject.handle_conflict(file)
|
69
|
+
}.to raise_error(StaticSync::Processor::ConflictError)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
21
75
|
describe "#local_filtered_files" do
|
22
76
|
|
23
77
|
before do
|
@@ -27,7 +81,7 @@ describe StaticSync::Processor do
|
|
27
81
|
end
|
28
82
|
|
29
83
|
it "does not include files matching the ignore regex" do
|
30
|
-
Dir.chdir(config.
|
84
|
+
Dir.chdir(config.local_directory) do
|
31
85
|
subject.local_filtered_files.should == [
|
32
86
|
"assets/javascripts/jquery.min.js",
|
33
87
|
"cat.com/index.html",
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "./lib/static_sync/storage_cache"
|
2
|
+
|
3
|
+
module StaticSync
|
4
|
+
describe StorageCache do
|
5
|
+
|
6
|
+
let(:path) { "index.html" }
|
7
|
+
|
8
|
+
let(:version_one) { StorageCache::Version.new(path, "0cc175b9c0f1b6a831c399e269772661") }
|
9
|
+
let(:version_two) { StorageCache::Version.new(path, "92eb5ffee6ae2fec3ad71c777531578f") }
|
10
|
+
|
11
|
+
let(:files) { [] }
|
12
|
+
|
13
|
+
subject do
|
14
|
+
StorageCache.new(files)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#has_file?" do
|
18
|
+
|
19
|
+
it "returns false by default" do
|
20
|
+
subject.has_file?(version_one).should be_false
|
21
|
+
subject.has_file?(version_two).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when an existing version of a file exists in the cache" do
|
25
|
+
|
26
|
+
let(:files) { [version_one] }
|
27
|
+
|
28
|
+
it "returns true if the given version is the same" do
|
29
|
+
subject.has_file?(version_one).should be_true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#has_version?" do
|
35
|
+
|
36
|
+
it "returns false by default" do
|
37
|
+
subject.has_version?(version_one).should be_false
|
38
|
+
subject.has_version?(version_two).should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when an existing version of a file exists in the cache" do
|
42
|
+
|
43
|
+
let(:files) { [version_one] }
|
44
|
+
|
45
|
+
it "returns false if the given version is different" do
|
46
|
+
subject.has_version?(version_two).should be_false
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns true if the given version is the same" do
|
50
|
+
subject.has_version?(version_one).should be_true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#has_conflict?" do
|
56
|
+
|
57
|
+
it "returns false by default" do
|
58
|
+
subject.has_conflict?(version_one).should be_false
|
59
|
+
subject.has_conflict?(version_two).should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when an existing version of a file exists in the cache" do
|
63
|
+
|
64
|
+
let(:files) { [version_one] }
|
65
|
+
|
66
|
+
it "returns false when the given version is the same" do
|
67
|
+
subject.has_conflict?(version_one).should be_false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns true when the given version is different" do
|
71
|
+
subject.has_conflict?(version_two).should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/spec/uploadable_spec.rb
CHANGED
@@ -68,6 +68,23 @@ describe StaticSync::Uploadable do
|
|
68
68
|
|
69
69
|
end
|
70
70
|
|
71
|
+
describe "#cached?" do
|
72
|
+
it "returns false by default" do
|
73
|
+
subject.cached?.should be_false
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when caching is enabled for html" do
|
77
|
+
|
78
|
+
before do
|
79
|
+
config['cache'] = { 'html' => '86400' }
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns true for a html file" do
|
83
|
+
html_file.cached?.should be_true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
71
88
|
describe "#cache_time" do
|
72
89
|
|
73
90
|
context "when caching is disabled" do
|
@@ -76,7 +93,7 @@ describe StaticSync::Uploadable do
|
|
76
93
|
config['cache'] = { }
|
77
94
|
end
|
78
95
|
|
79
|
-
it "
|
96
|
+
it "returns nil for a html file" do
|
80
97
|
html_file.cache_time.should be_nil
|
81
98
|
end
|
82
99
|
end
|
@@ -87,15 +104,15 @@ describe StaticSync::Uploadable do
|
|
87
104
|
config['cache'] = { 'html' => '86400' }
|
88
105
|
end
|
89
106
|
|
90
|
-
it "
|
107
|
+
it "returns the configured value for html files" do
|
91
108
|
html_file.cache_time.should == 86400
|
92
109
|
end
|
93
110
|
|
94
|
-
it "
|
111
|
+
it "returns the configured value for text files" do
|
95
112
|
text_file.cache_time.should be_nil
|
96
113
|
end
|
97
114
|
|
98
|
-
it "
|
115
|
+
it "returns nil for css files" do
|
99
116
|
css_file.cache_time.should be_nil
|
100
117
|
end
|
101
118
|
end
|
@@ -106,11 +123,11 @@ describe StaticSync::Uploadable do
|
|
106
123
|
config['cache'] = { 'image' => '86400' }
|
107
124
|
end
|
108
125
|
|
109
|
-
it "
|
126
|
+
it "returns the configured value for gif files" do
|
110
127
|
gif_file.cache_time.should == 86400
|
111
128
|
end
|
112
129
|
|
113
|
-
it "
|
130
|
+
it "returns the configured value for png files" do
|
114
131
|
png_file.cache_time.should == 86400
|
115
132
|
end
|
116
133
|
end
|
@@ -119,11 +136,11 @@ describe StaticSync::Uploadable do
|
|
119
136
|
|
120
137
|
describe "#gzipped?" do
|
121
138
|
|
122
|
-
it "
|
139
|
+
it "returns true for html files" do
|
123
140
|
html_file.gzipped?.should be_true
|
124
141
|
end
|
125
142
|
|
126
|
-
it "
|
143
|
+
it "returns false for png files" do
|
127
144
|
png_file.gzipped?.should be_false
|
128
145
|
end
|
129
146
|
|
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.1.
|
4
|
+
version: 0.1.8
|
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-02-
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- lib/static_sync/config.rb
|
78
78
|
- lib/static_sync/processor.rb
|
79
79
|
- lib/static_sync/storage.rb
|
80
|
+
- lib/static_sync/storage_cache.rb
|
80
81
|
- lib/static_sync/uploadable.rb
|
81
82
|
- lib/static_sync/version.rb
|
82
83
|
- spec/fixtures/site/assets/images/spinner.gif
|
@@ -86,6 +87,7 @@ files:
|
|
86
87
|
- spec/fixtures/site/cat.com/index.html
|
87
88
|
- spec/fixtures/site/index.html
|
88
89
|
- spec/processor_spec.rb
|
90
|
+
- spec/storage_cache_spec.rb
|
89
91
|
- spec/uploadable_spec.rb
|
90
92
|
- static_sync.gemspec
|
91
93
|
homepage:
|
@@ -114,4 +116,5 @@ specification_version: 3
|
|
114
116
|
summary: Command line tool for uploading static websites to amazon/rackspace.
|
115
117
|
test_files:
|
116
118
|
- spec/processor_spec.rb
|
119
|
+
- spec/storage_cache_spec.rb
|
117
120
|
- spec/uploadable_spec.rb
|