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 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,gz)$
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 strictly prevent modification of existing files.
56
- immutable_mode: false
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
- ### Environment Variables
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['s3_key'] %>
73
- password: <%= ENV['s3_secret'] %>
74
- directory: <%= ENV['s3_bucket'] %>
90
+ username: <%= ENV['S3_KEY'] %>
91
+ password: <%= ENV['S3_SECRET'] %>
92
+ directory: <%= ENV['S3_BUCKET'] %>
75
93
  ```
76
94
 
77
95
  ## Contributing
@@ -7,38 +7,40 @@ module StaticSync
7
7
  self.fetch('log', true)
8
8
  end
9
9
 
10
- def immutable_mode
11
- self.fetch('immutable_mode', false)
10
+ def local
11
+ self.fetch('local', {})
12
12
  end
13
13
 
14
- def cache
15
- self.fetch('cache', {})
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 source
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 storage
31
- Fog::Storage.new({
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['ignored']
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 ImmutableError < StandardError
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.source} to #{@config.target}.") if @config.log
20
- Dir.chdir(@config.source) do
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
- log.info("Overwriting #{file}") if @config.log
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
@@ -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
- file_versions.map(&:path).include?(version.path)
13
+ cache.has_file?(version)
18
14
  end
19
15
 
20
16
  def has_version?(version)
21
- file_versions.include?(version)
17
+ cache.has_version?(version)
22
18
  end
23
19
 
24
- def file_versions
25
- @file_versions ||= begin
26
- result = []
20
+ def cache
21
+ @cache ||= begin
22
+ versions = []
27
23
  remote_directory.files.each do |file|
28
- result << Version.new(file.key, file.etag)
24
+ versions << StorageCache::Version.new(file.key, file.etag)
29
25
  end
30
- result
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
- @config.storage.directories.new(:key => @config.target)
38
+ storage.directories.new(:key => @config.remote['directory'])
42
39
  end
43
40
 
44
41
  def validate_credentials!
45
- @config.storage.get_bucket(@config.target)
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 "storage"
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
- Storage::Version.new(path, etag)
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
@@ -1,3 +1,3 @@
1
1
  module StaticSync
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
@@ -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.source) do
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
@@ -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 "is nil for html files" do
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 "is the configured value for html files" do
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 "is the configured value for text files" do
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 "is nil for css files" do
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 "is the configured value for gif files" do
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 "is the configured value for png files" do
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 "is true for html files" do
139
+ it "returns true for html files" do
123
140
  html_file.gzipped?.should be_true
124
141
  end
125
142
 
126
- it "is false for png files" do
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.7
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-10 00:00:00.000000000 Z
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