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 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