closync 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ env:
5
+ - [
6
+ # GOOGLE_STORAGE_ACCESS_KEY_ID
7
+ {secure: "GOJGnwF6G7u+K9WsZxcWX2H35QdnXNDS4UCJw9ekpEJk0ymmY685lUCmZqGD\nmkZAkJLql+T4oScaGVO7XjNTZnDXN/1NivYhPXtyPbgAtThMm0GPTKT3Kt/z\nxWdDurXqUg44YqEXuFJHOXdOkmNUZM5/4dqNfgW4vtlMzAB4Rw0="},
8
+ # GOOGLE_STORAGE_SECRET_ACCESS_KEY
9
+ {secure: "P9J9ss9mRBHmbHHKPZSZHuo7Rc2o9AJx7+7L4IUnvhssxGEiKu6Umov7LKMh\n5ibQH1oaW+JGlpVyqN7EioSMj/ahrZFjK5LAaWIbG5JsttVAgd/9gdUXDuNc\nUOEwLMg9PEOPD/Q1N7VO8SlHj7CuEMPBD2FX3vRJK1kgD2SHA4M="}
10
+
11
+ # AWS_ACCESS_KEY_ID
12
+ # AWS_SECRET_ACCESS_KEY
13
+ ]
14
+ script:
15
+ - bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,30 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in closync.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'rake'
8
+
9
+ gem 'rspec'
10
+ gem 'fuubar'
11
+
12
+ unless ENV['TRAVIS']
13
+ gem 'guard-rspec'
14
+ gem 'guard-bundler'
15
+
16
+ gem 'ruby-debug', :platform => :mri_18
17
+ gem 'debugger', :platform => :mri_19
18
+
19
+ require 'rbconfig'
20
+ if RbConfig::CONFIG['target_os'] =~ /darwin/i
21
+ gem 'rb-fsevent'
22
+ gem 'growl'
23
+ end
24
+ if RbConfig::CONFIG['target_os'] =~ /linux/i
25
+ gem 'rb-inotify'
26
+ gem 'libnotify'
27
+ end
28
+
29
+ end
30
+ end
data/Guardfile ADDED
@@ -0,0 +1,29 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ # watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ # watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ # watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ # watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ # watch('config/routes.rb') { "spec/routing" }
15
+ # watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara request specs
18
+ # watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
25
+
26
+ guard 'bundler' do
27
+ watch('Gemfile')
28
+ watch(/^.+\.gemspec/)
29
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Alexander Wenzowski
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,49 @@
1
+ # Closync
2
+
3
+ Synchronizes local and cloud storage.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'closync'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install closync
18
+
19
+ ## Usage
20
+
21
+ Closync reads from a yaml configuration file to determine origin and
22
+ destination to perform a one-way synchronization.
23
+
24
+ **.closync.yml**
25
+
26
+ credentials:
27
+ google_storage_access_key_id: ENV['GOOGLE_STORAGE_ACCESS_KEY_ID']
28
+ google_storage_secret_access_key: ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY']
29
+ storage:
30
+ local:
31
+ provider: 'Local'
32
+ directory: 'folder/name'
33
+ remote:
34
+ provider: 'Google'
35
+ directory: 'bucket_name'
36
+ cache-control:
37
+ 300:
38
+ - .htm
39
+ - .html
40
+ 3600:
41
+ - default
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/closync.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/closync/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Alexander Wenzowski"]
6
+ gem.email = ["alexander@wenzowski.com"]
7
+ gem.summary = 'A tool for synchronizing cloud storage buckets.'
8
+ gem.description = <<-EOF
9
+ Closync is a cloud storage interaction tool designed to simplify
10
+ synchronization between multiple filesystems. It uses the fog gem
11
+ to interact with both local and remote storage.
12
+ EOF
13
+ gem.homepage = "http://github.com/wenzowski/closync"
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.name = 'closync'
19
+ gem.require_paths = ["lib"]
20
+ gem.version = Closync::VERSION
21
+
22
+ gem.add_dependency('fog')
23
+ end
@@ -0,0 +1,120 @@
1
+ module Closync
2
+ class Config
3
+
4
+ # Fog config
5
+ attr_accessor :credentials
6
+ attr_accessor :storage
7
+ attr_accessor :cache_control
8
+
9
+ # Git
10
+ attr_accessor :branch
11
+
12
+
13
+ def initialize(opts={})
14
+ self.credentials = {}
15
+ self.storage = {}
16
+ self.cache_control = {}
17
+ self.branch = []
18
+
19
+ @yml_path = ( opts[:yml_path] || "#{Dir.pwd}/.closync.yml" )
20
+
21
+ if self.yml_exists?
22
+ load_yml!
23
+ else
24
+ raise "Config file not found at #{opts[:yml_path]}" if opts[:yml_path]
25
+ end
26
+ end
27
+
28
+ def yml_path
29
+ @yml_path
30
+ end
31
+
32
+ def yml_exists?
33
+ File.exists?(self.yml_path)
34
+ end
35
+
36
+ def max_age(extension)
37
+ self.cache_control[extension] || self.cache_control['default'] ||
38
+ (raise 'No default max-age configured.')
39
+ end
40
+
41
+ def set_max_age!(extension, max_age)
42
+ self.cache_control[extension] = max_age
43
+ end
44
+
45
+ def local
46
+ storage[:local] || (raise 'No local storage configured.')
47
+ end
48
+
49
+ def local=(config={})
50
+ raise 'Config must include :provider and :directory.' unless
51
+ config.keys == [:provider, :directory]
52
+ storage[:local] = {}
53
+ storage[:local][:provider] = config[:provider]
54
+ storage[:local][:directory] = config[:directory]
55
+ end
56
+
57
+ def remote
58
+ storage[:remote] || (raise 'No remote storage configured.')
59
+ end
60
+
61
+ def remote=(config={})
62
+ raise 'Config must include :provider and :directory.' unless
63
+ config.keys == [:provider, :directory]
64
+ storage[:remote] = {}
65
+ storage[:remote][:provider] = config[:provider]
66
+ storage[:remote][:directory] = config[:directory]
67
+ end
68
+
69
+ private
70
+
71
+ def load_yml!
72
+ read_yml!
73
+ set_credentials!
74
+ set_storage!
75
+ set_cache_control!
76
+ set_branch!
77
+ end
78
+
79
+ def read_yml
80
+ YAML.load(ERB.new(IO.read(self.yml_path)).result) rescue nil || {}
81
+ end
82
+
83
+ def read_yml!
84
+ @yml = read_yml
85
+ end
86
+
87
+ def set_credentials!
88
+ self.credentials = {}
89
+ @yml['credentials'].each do |key, val|
90
+ self.credentials[key.to_sym] = val
91
+ end
92
+ end
93
+
94
+ def set_storage!
95
+ self.storage = {}
96
+ @yml['storage'].each do |remote, config|
97
+ self.storage[remote.to_sym] = {}
98
+ config.each do |key, val|
99
+ self.storage[remote.to_sym][key.to_sym] = val
100
+ end
101
+ end
102
+ end
103
+
104
+ def set_cache_control!
105
+ @yml['cache_control'].each do |max_age, extensions|
106
+ extensions.each do |extension|
107
+ set_max_age!(extension, max_age)
108
+ end
109
+ end
110
+ end
111
+
112
+ def set_branch!
113
+ self.branch = []
114
+ @yml['branch'].each do |branch|
115
+ self.branch << branch
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,49 @@
1
+ require 'fog'
2
+
3
+ module Closync
4
+ class Storage
5
+ attr_accessor :directory
6
+
7
+ # * config (<~object) Closync::Config
8
+ # * opts (<~dict) Options to initialize fog connection.
9
+ # * :provider (<~string): Options are ['Local', 'AWS', 'Google', 'Rackspace']
10
+ # * :directory (<~string) Bucket or local directory.
11
+ def initialize(config, opts={})
12
+ dir = opts.delete(:directory)
13
+ case opts[:provider]
14
+ when 'Local'
15
+ opts[:local_root] = Dir.pwd
16
+ @storage = Fog::Storage.new(opts)
17
+ when 'AWS'
18
+ opts[:aws_access_key_id] =
19
+ config.credentials[:aws_access_key_id]
20
+ opts[:aws_secret_access_key] =
21
+ config.credentials[:aws_access_key_id]
22
+ @storage = Fog::Storage.new(opts)
23
+ when 'Google'
24
+ opts[:google_storage_access_key_id] =
25
+ config.credentials[:google_storage_access_key_id]
26
+ opts[:google_storage_secret_access_key] =
27
+ config.credentials[:google_storage_secret_access_key]
28
+ @storage = Fog::Storage.new(opts)
29
+ when 'Rackspace'
30
+ opts[:rackspace_username] =
31
+ config.credentials[:rackspace_username]
32
+ opts[:rackspace_api_key] =
33
+ config.credentials[:rackspace_api_key]
34
+ @storage = Fog::Storage.new(opts)
35
+ else
36
+ raise 'Unsupported provider'
37
+ end
38
+
39
+ # Get the requested bucket/directory. Create if missing.
40
+ if d = @storage.directories.get(dir)
41
+ self.directory = d
42
+ else
43
+ @storage.directories.create(key: dir, public: true)
44
+ self.directory = @storage.directories.get(dir)
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,64 @@
1
+ require 'closync/storage'
2
+
3
+ module Closync
4
+ class Sync
5
+
6
+ def initialize(config)
7
+ @config = config
8
+ raise 'Local directory not configured' unless config.local
9
+ raise 'Remote directory not configured' unless config.remote
10
+ @local = Closync::Storage.new(config, config.local)
11
+ @remote = Closync::Storage.new(config, config.remote)
12
+ end
13
+
14
+ def push!
15
+ push_new_data!
16
+ delete_old_data!
17
+ end
18
+
19
+ private
20
+
21
+ def push_new_data!
22
+ @local.directory.files.each do |file|
23
+ upload!(file) if upload?(file)
24
+ end
25
+ end
26
+
27
+ def delete_old_data!
28
+ # @remote.directory.files.each do |file|
29
+ # file.delete unless @local.directory.files.head(file)
30
+ # end
31
+ end
32
+
33
+ def upload?(file)
34
+ upload = false
35
+ if ( remote_file = @remote.directory.files.head(file.key) )
36
+ if remote_file.last_modified < file.last_modified
37
+ # TODO(wenzowski): check etag to see if file has changed
38
+ upload = true # clobber remote file
39
+ end
40
+ else
41
+ upload = true
42
+ end
43
+ upload
44
+ end
45
+
46
+ # If file already exists on remote it will be overwritten.
47
+ def upload!(file)
48
+ @remote.directory.files.create(
49
+ key: file.key,
50
+ body: file.body,
51
+ cache_control: max_age(file),
52
+ public: true
53
+ )
54
+ end
55
+
56
+ def max_age(file)
57
+ @config.max_age( extension(file) )
58
+ end
59
+
60
+ def extension(file)
61
+ /(\.\w+)$/.match(file.key)[0]
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module Closync
2
+ VERSION = "0.0.1"
3
+ end
data/lib/closync.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'closync/version'
2
+ require 'closync/config'
3
+ require 'closync/storage'
4
+ require 'closync/sync'
5
+
6
+ module Closync
7
+ class << self
8
+ def config=(data)
9
+ @config = data
10
+ end
11
+
12
+ def config
13
+ @config ||= Config.new
14
+ @config
15
+ end
16
+
17
+ def configure(&proc)
18
+ @config ||= Config.new
19
+ yield @config
20
+ end
21
+
22
+ def push!
23
+ Sync.new(config).push!
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'closync/config'
3
+
4
+ describe Closync::Config do
5
+ context 'no yml config file' do
6
+ subject { Closync::Config.new() }
7
+
8
+ it { subject.yml_path.should == "#{Dir.pwd}/.closync.yml" }
9
+ it { subject.yml_exists?.should be_false }
10
+
11
+ it { subject.credentials.should == {} }
12
+ it { subject.storage.should == {} }
13
+ it { subject.cache_control.should == {} }
14
+
15
+ it { subject.branch.should == [] }
16
+ end
17
+
18
+ context 'yml config file missing' do
19
+ let(:yml_path) { "#{Dir.pwd}/.closync.yml" }
20
+ it 'raises error if yml_path does not point to a file' do
21
+ lambda { Closync::Config.new(yml_path: yml_path) }.should raise_error
22
+ end
23
+ end
24
+
25
+ context 'yml config file exists' do
26
+ let(:yml_path) { "#{Dir.pwd}/spec/support/closync.yml" }
27
+ subject { Closync::Config.new(yml_path: yml_path) }
28
+
29
+ it { subject.yml_path.should == yml_path }
30
+ it { subject.yml_exists?.should be_true }
31
+
32
+ # Fog credentials
33
+ it { subject.credentials.keys.should == [:google_storage_access_key_id, :google_storage_secret_access_key] }
34
+
35
+ # Remotes to interact with
36
+ it { subject.storage.keys.should == [:local, :remote] }
37
+ it { subject.local.keys.should == [:provider, :directory] }
38
+ it { subject.local[:provider].should == 'Local' }
39
+ it { subject.local[:directory].should == 'folder/name' }
40
+ it { subject.remote.keys.should == [:provider, :directory] }
41
+ it { subject.remote[:provider].should == 'Google' }
42
+ it { subject.remote[:directory].should == 'bucket_name' }
43
+
44
+ # Cache-Control headers
45
+ it { subject.cache_control.should == {'.htm' => 300, '.html' => 300, 'default' => 3600} }
46
+ it { subject.max_age('.htm').should == 300 }
47
+ it { subject.max_age('.jpg').should == 3600 }
48
+
49
+ # Git branch to check for before performing actions
50
+ it { subject.branch.should == ['master'] }
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'closync/storage'
3
+ require 'closync/config'
4
+
5
+ describe Closync::Storage do
6
+ let(:yml_path) { "#{Dir.pwd}/spec/support/closync.yml" }
7
+ let(:dir) { SecureRandom.hex }
8
+ let(:config) { Closync::Config.new(yml_path: yml_path) }
9
+
10
+ context 'local storage' do
11
+ # DIRTY HACK: Fog's Local Storage is not mocked.
12
+ before(:each) do
13
+ FileUtils.rm_rf 'tmp'
14
+ FileUtils.mkdir 'tmp'
15
+ end
16
+ subject { Closync::Storage.new(Closync::Config.new, provider: 'Local', directory: "tmp/#{dir}") }
17
+ it { subject.directory.class.should be(Fog::Storage::Local::Directory) }
18
+ it { subject.directory.key.should eq("tmp/#{dir}") }
19
+ end
20
+
21
+ context 'google storage' do
22
+ # WARNING: THESE TESTS CREATE BUCKETS ON GOOGLE STORAGE
23
+ # subject { Closync::Storage.new(config, provider: 'Google', directory: dir) }
24
+ # it { subject.directory.class.should be(Fog::Storage::Google::Directory) }
25
+ # it { subject.directory.key.should == dir }
26
+ end
27
+
28
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'closync/sync'
3
+ require 'closync/config'
4
+
5
+ describe Closync::Storage do
6
+ let(:dir) { SecureRandom.hex }
7
+ let(:local_dir) { "tmp/local/#{dir}" }
8
+ let(:remote_dir) { "tmp/remote/#{dir}" }
9
+
10
+ let(:yml_path) { "#{Dir.pwd}/spec/support/closync.yml" }
11
+ let(:config) {
12
+ config = Closync::Config.new(yml_path: yml_path)
13
+ config.local = { provider: 'Local', directory: local_dir }
14
+ config.remote = { provider: 'Local', directory: remote_dir }
15
+ config
16
+ }
17
+
18
+ context 'local sync' do
19
+ before(:each) do
20
+ FileUtils.mkdir_p local_dir
21
+ FileUtils.mkdir_p remote_dir
22
+ FileUtils.touch "#{local_dir}/index.html"
23
+ FileUtils.touch "#{local_dir}/pic.jpg"
24
+ end
25
+ after(:each) do
26
+ FileUtils.rm_rf local_dir
27
+ FileUtils.rm_rf remote_dir
28
+ end
29
+
30
+ it { lambda {Closync::Sync.new(config)}.should_not raise_error }
31
+
32
+ it 'pushes files to remote' do
33
+ File.exists?("#{remote_dir}/index.html").should be_false
34
+ File.exists?("#{remote_dir}/pic.jpg").should be_false
35
+ Closync::Sync.new(config).push!
36
+ File.exists?("#{remote_dir}/index.html").should be_true
37
+ File.exists?("#{remote_dir}/pic.jpg").should be_true
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'closync/version'
3
+
4
+ describe Closync do
5
+ it { Closync::VERSION.should eq('0.0.1'), "Please don't bump the version." }
6
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'closync'
3
+
4
+ describe Closync do
5
+ it 'should be configured by block' do
6
+ Closync.configure do |config|
7
+ config.credentials = {
8
+ google_storage_access_key_id: ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'],
9
+ google_storage_secret_access_key: ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY']
10
+ }
11
+ config.local = {provider: 'Local', directory: 'folder/name'}
12
+ config.remote = {provider: 'Google', directory: 'bucket_name'}
13
+ config.branch = ['master']
14
+ config.set_max_age!('default', 3600)
15
+ config.set_max_age!('.htm', 300)
16
+ config.set_max_age!('.html', 300)
17
+ end
18
+ Closync.config.credentials.should_not be_nil
19
+ Closync.config.storage.should_not be_nil
20
+ Closync.config.branch.should_not be_nil
21
+ Closync.config.cache_control.should_not be_nil
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
19
+ # require 'fog'
20
+ # Fog.mock!
@@ -0,0 +1,18 @@
1
+ credentials: # symbol names per fog gem
2
+ google_storage_access_key_id: <%= ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'] || 'mock_key' %>
3
+ google_storage_secret_access_key: <%= ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY'] || 'mock_secret' %>
4
+ storage: # provider strings per fog gem
5
+ local:
6
+ provider: 'Local'
7
+ directory: 'folder/name'
8
+ remote:
9
+ provider: 'Google'
10
+ directory: 'bucket_name'
11
+ branch: # restrict push to git branch
12
+ - master
13
+ cache_control:
14
+ 300:
15
+ - .htm
16
+ - .html
17
+ 3600:
18
+ - default
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: closync
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alexander Wenzowski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: ! " Closync is a cloud storage interaction tool designed to simplify\n
31
+ \ synchronization between multiple filesystems. It uses the fog gem\n to interact
32
+ with both local and remote storage.\n"
33
+ email:
34
+ - alexander@wenzowski.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - .gitignore
40
+ - .rspec
41
+ - .travis.yml
42
+ - Gemfile
43
+ - Guardfile
44
+ - LICENSE
45
+ - README.md
46
+ - Rakefile
47
+ - closync.gemspec
48
+ - lib/closync.rb
49
+ - lib/closync/config.rb
50
+ - lib/closync/storage.rb
51
+ - lib/closync/sync.rb
52
+ - lib/closync/version.rb
53
+ - spec/lib/closync/config_spec.rb
54
+ - spec/lib/closync/storage_spec.rb
55
+ - spec/lib/closync/sync_spec.rb
56
+ - spec/lib/closync/version_spec.rb
57
+ - spec/lib/closync_spec.rb
58
+ - spec/spec_helper.rb
59
+ - spec/support/closync.yml
60
+ homepage: http://github.com/wenzowski/closync
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ segments:
73
+ - 0
74
+ hash: 2016661747058335688
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ segments:
82
+ - 0
83
+ hash: 2016661747058335688
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 1.8.24
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: A tool for synchronizing cloud storage buckets.
90
+ test_files:
91
+ - spec/lib/closync/config_spec.rb
92
+ - spec/lib/closync/storage_spec.rb
93
+ - spec/lib/closync/sync_spec.rb
94
+ - spec/lib/closync/version_spec.rb
95
+ - spec/lib/closync_spec.rb
96
+ - spec/spec_helper.rb
97
+ - spec/support/closync.yml