middleman-s3_sync 3.0.0

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in middleman-s3_sync.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Frederic Jean
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Middleman::S3Sync
2
+
3
+ This gem determines which files need to be added, updated and optionally deleted
4
+ and only transfer these files up. This reduces the impact of an update
5
+ on a web site hosted on S3.
6
+
7
+ ## Why not Middleman Sync?
8
+
9
+ [Middleman Sync](https://github.com/karlfreeman/middleman-sync) does a
10
+ great job to push [Middleman](http://middlemanapp.com) generated
11
+ websites to S3. The only issue I have with it is that it pushes
12
+ every files under build to S3 and doesn't seem to properly delete files
13
+ that are no longer needed.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'middleman-s3_sync'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install middleman-s3_sync
28
+
29
+ ## Usage
30
+
31
+ You need to add the following code to your ```config.rb``` file:
32
+
33
+ ```ruby
34
+ activate :s3_sync do |s3_sync|
35
+ s3_sync.bucket = 'my.bucket.com' # The name of the S3 bucket you are targetting. This is globally unique.
36
+ s3_sync.region = 'us-west-1' # The AWS region for your bucket.
37
+ s3_sync.aws_access_key_id = 'AWS KEY ID'
38
+ s3_sync.aws_secret_access_key = 'AWS SECRET KEY'
39
+ s3_sync.delete = false # We delete stray files by default.
40
+ s3_sync.after_build = false # We chain after the build step by default. This may not be your desired behavior...
41
+ end
42
+ ```
43
+
44
+ You can then start synchronizing files with S3 through ```middleman s3_sync```.
45
+
46
+ ## A Debt of Gratitude
47
+
48
+ I used Middleman Sync as a template for building a Middleman extension.
49
+ The code is well structured and easy to understand and it was easy to
50
+ extend it to add my synchronization code. My gratitude goes to @karlfreeman
51
+ and is work on Middleman sync.
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,106 @@
1
+ require 'middleman-core'
2
+ require 'fog'
3
+ require 'parallel'
4
+ require 'digest/md5'
5
+ require 'middleman-s3_sync/version'
6
+ require 'middleman-s3_sync/commands'
7
+
8
+ ::Middleman::Extensions.register(:s3_sync, '>= 3.0.0') do
9
+ require 'middleman-s3_sync/extension'
10
+ ::Middleman::S3Sync
11
+ end
12
+
13
+ module Middleman
14
+ module S3Sync
15
+ class << self
16
+ def sync
17
+ puts "Gathering local files."
18
+ local_files = Dir[options.public_path + "/**/*"]
19
+ .reject { |f| File.directory?(f) }
20
+ .map { |f| f.gsub(/^build\//, '') }
21
+ puts "Gathering remote files."
22
+ remote_files = bucket.files.map { |f| f.key }
23
+
24
+ # First pass on the set of files to work with.
25
+ puts "Determine files to add to S3."
26
+ files_to_push = local_files - remote_files
27
+ if options.delete
28
+ puts "Determine which files to delete from S3"
29
+ files_to_delete = remote_files - local_files
30
+ end
31
+ files_to_evaluate = local_files - files_to_push
32
+
33
+ # No need to evaluate the files that are newer on S3 than the local files.
34
+ puts "Determine which local files are newer than their S3 counterparts"
35
+ files_to_reject = []
36
+ Parallel.each(files_to_evaluate, :in_threads => 4) do |f|
37
+ print '.'
38
+ local_mtime = File.mtime("build/#{f}")
39
+ remote_mtime = s3_files.get(f).last_modified
40
+ files_to_reject << f if remote_mtime >= local_mtime
41
+ end
42
+
43
+ files_to_evaluate = files_to_evaluate - files_to_reject
44
+
45
+ # Are the files different? Use MD5 to see
46
+ if (files_to_evaluate.size > 0)
47
+ puts "\n\nDetermine which remaining files are actually different than their S3 counterpart."
48
+ Parallel.each(files_to_evaluate, :in_threads => 4) do |f|
49
+ print '.'
50
+ local_md5 = Digest::MD5.hexdigest(File.read("build/#{f}"))
51
+ remote_md5 = s3_files.get(f).etag
52
+ files_to_push << f if local_md5 != remote_md5
53
+ end
54
+ end
55
+
56
+ if files_to_push.size > 0
57
+ puts "\n\nReady to apply updates to S3."
58
+ files_to_push.each do |f|
59
+ if remote_files.include?(f)
60
+ puts "Updating #{f}"
61
+ file = s3_files.get(f)
62
+ file.body = File.open("build/#{f}")
63
+ file.save
64
+ else
65
+ puts "Creating #{f}"
66
+ file = bucket.files.create({
67
+ :key => f,
68
+ :body => File.open("build/#{f}"),
69
+ :public => true
70
+ })
71
+ end
72
+ end
73
+ else
74
+ puts "\n\nNo files to update."
75
+ end
76
+
77
+ if options.delete
78
+ files_to_delete.each do |f|
79
+ puts "Deleting #{f}"
80
+ file = s3_files.get(f)
81
+ file.destroy
82
+ end
83
+ end
84
+ end
85
+
86
+ protected
87
+ def connection
88
+ @connection ||= Fog::Storage.new({
89
+ :provider => 'AWS',
90
+ :aws_access_key_id => options.aws_access_key_id,
91
+ :aws_secret_access_key => options.aws_secret_access_key,
92
+ :region => options.region
93
+ })
94
+ end
95
+
96
+ def bucket
97
+ @bucket ||= connection.directories.get(options.bucket)
98
+ end
99
+
100
+ def s3_files
101
+ @s3_files ||= bucket.files
102
+ end
103
+ end
104
+ end
105
+ end
106
+
@@ -0,0 +1,31 @@
1
+ require 'middleman-core/cli'
2
+ require 'middleman-s3_sync/extension'
3
+
4
+ module Middleman
5
+ module Cli
6
+ class S3Sync < Thor
7
+ include Thor::Actions
8
+
9
+ check_unknown_options!
10
+
11
+ namespace :s3_sync
12
+
13
+ def self.exit_on_failure?
14
+ true
15
+ end
16
+
17
+ desc "s3_sync", "Builds and push the minimum set of files needed to S3"
18
+ def s3_sync
19
+ shared_inst = ::Middleman::Application.server.inst
20
+ bucket = shared_inst.options.bucket
21
+ if (!bucket)
22
+ raise Thor::Error.new "You need to activate this extension."
23
+ end
24
+
25
+ ::Middleman::S3Sync.sync
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'middleman-core'
2
+
3
+ module Middleman
4
+ module S3Sync
5
+ class Options < Struct.new(
6
+ :prefix,
7
+ :public_path,
8
+ :bucket,
9
+ :region,
10
+ :aws_access_key_id,
11
+ :aws_secret_access_key,
12
+ :after_build,
13
+ :delete,
14
+ :existing_remote_file,
15
+ )
16
+ end
17
+
18
+ class << self
19
+ def options
20
+ @@options
21
+ end
22
+
23
+ def registered(app, options_hash = {}, &block)
24
+ options = Options.new(options_hash)
25
+ yield options if block_given?
26
+
27
+ @@options = options
28
+
29
+ app.send :include, Helpers
30
+
31
+ options.public_path ||= "build"
32
+ app.after_configuration do |config|
33
+ after_build do |builder|
34
+ ::Middleman::S3Sync.sync if options.after_build
35
+ end
36
+ end
37
+ end
38
+
39
+ alias :included :registered
40
+
41
+ module Helpers
42
+ def options
43
+ ::Middleman::S3Sync.options
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module S3Sync
3
+ VERSION = "3.0.0"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require 'middleman-s3_sync'
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'middleman-s3_sync/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "middleman-s3_sync"
8
+ gem.version = Middleman::S3Sync::VERSION
9
+ gem.authors = ["Frederic Jean"]
10
+ gem.email = ["fred@fredjean.net"]
11
+ gem.description = %q{Only syncs files that have been updated to S3.}
12
+ gem.summary = %q{Tries really, really hard not to push files to S3.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency 'middleman-core', '>= 3.0.0'
21
+ gem.add_runtime_dependency 'fog'
22
+ gem.add_runtime_dependency 'parallel'
23
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-s3_sync
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 3.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Frederic Jean
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ type: :runtime
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ name: middleman-core
23
+ prerelease: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ type: :runtime
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ name: fog
39
+ prerelease: false
40
+ requirement: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ type: :runtime
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ name: parallel
55
+ prerelease: false
56
+ requirement: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Only syncs files that have been updated to S3.
63
+ email:
64
+ - fred@fredjean.net
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - lib/middleman-s3_sync.rb
75
+ - lib/middleman-s3_sync/commands.rb
76
+ - lib/middleman-s3_sync/extension.rb
77
+ - lib/middleman-s3_sync/version.rb
78
+ - lib/middleman_extension.rb
79
+ - middleman-s3_sync.gemspec
80
+ homepage: ''
81
+ licenses: []
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ segments:
92
+ - 0
93
+ hash: 3576862975289207856
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ hash: 3576862975289207856
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.23
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Tries really, really hard not to push files to S3.
110
+ test_files: []