static_sync 0.1.7 → 0.1.8
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/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
|