hoarder 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +6 -0
- data/README.markdown +30 -0
- data/Rakefile +8 -0
- data/bin/hoarder +14 -0
- data/hoarder.gemspec +23 -0
- data/hoarder.yml.sample +4 -0
- data/lib/hoarder.rb +4 -0
- data/lib/hoarder/hoarder.rb +57 -0
- data/lib/hoarder/storage.rb +60 -0
- data/lib/hoarder/version.rb +3 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/storage_spec.rb +46 -0
- metadata +79 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Hoarder
|
2
|
+
|
3
|
+
_For those who can't let go..._
|
4
|
+
|
5
|
+
Hoarder is a utility for pushing your files to cloud storage. Just specify the absolute path of a directory of files you want to store and Hoarder will push all of its contents to the cloud. Hoarder will outright replace any files with the same name in your cloud storage container (bucket?).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
gem install hoarder
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
Create a hoarder.yml file in the directory containing the files you want to push. Hoarder uses the gem [Fog](http://fog.io) to connect to cloud providers. Support is only provided for Rackspace Cloud Files (for now). The available hoarder.yml options are:
|
14
|
+
|
15
|
+
rackspace_username: # Your Rackspace user name
|
16
|
+
rackspace_api_key: # Your Rackspace api key
|
17
|
+
container: # The name of the Cloud Files container to use (does not have to exist)
|
18
|
+
public: # True or False depending on if you want the container to be CDN enabled
|
19
|
+
|
20
|
+
The rackspace_username and rackspace_api_key options come directly from [Fog](http://fog.io).
|
21
|
+
|
22
|
+
Then from your command line simply run:
|
23
|
+
|
24
|
+
hoarder "/absolute/path/to/your/files"
|
25
|
+
|
26
|
+
## To Do
|
27
|
+
|
28
|
+
* Add support for Amazon S3
|
29
|
+
* Make uploading a little smarter
|
30
|
+
* More specs
|
data/Rakefile
ADDED
data/bin/hoarder
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/user/bin/env ruby
|
2
|
+
require 'hoarder'
|
3
|
+
|
4
|
+
begin
|
5
|
+
s = Hoarder::Storage.new(ARGV[0])
|
6
|
+
Hoarder::Hoarder.new(s).hoard(s.absolute_path)
|
7
|
+
Kernel.exit 1
|
8
|
+
rescue SystemExit => e
|
9
|
+
Kernel.exit(e.status)
|
10
|
+
rescue Exception => e
|
11
|
+
STDERR.puts("#{e.message} (#{e.class})")
|
12
|
+
STDERR.puts(e.backtrace.join("\n"))
|
13
|
+
Kernel.exit 1
|
14
|
+
end
|
data/hoarder.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "hoarder/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "hoarder"
|
7
|
+
s.version = Hoarder::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Michael Cheung"]
|
10
|
+
s.email = ["mncheu@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{For those who can't let go of their files.}
|
13
|
+
s.description = %q{A utility to push static files to cloud storage.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "hoarder"
|
16
|
+
|
17
|
+
s.add_runtime_dependency "fog"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
data/hoarder.yml.sample
ADDED
data/lib/hoarder.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Hoarder
|
2
|
+
class Hoarder
|
3
|
+
|
4
|
+
def initialize(storage)
|
5
|
+
@storage = storage
|
6
|
+
end
|
7
|
+
|
8
|
+
def file_name(file, path)
|
9
|
+
relative_path(path).empty? ? File.basename(file) : "#{relative_path(path)}/#{File.basename(file)}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def hidden_file?(file_name)
|
13
|
+
file_name.chr == '.' ? true : false
|
14
|
+
end
|
15
|
+
|
16
|
+
def hoard(path)
|
17
|
+
current_path = relative_path(path).empty? ? @storage.absolute_path : "#{@storage.absolute_path}/#{relative_path(path)}"
|
18
|
+
Dir.new(path).each do |f|
|
19
|
+
unless ignore_file?(f)
|
20
|
+
begin
|
21
|
+
if File.directory?("#{current_path}/#{f}")
|
22
|
+
puts "Creating directory #{File.basename(f)}"
|
23
|
+
@storage.locker.files.create(
|
24
|
+
:key => file_name(f, path),
|
25
|
+
:body => '',
|
26
|
+
:content_type => 'application/directory',
|
27
|
+
:public => @storage.public
|
28
|
+
)
|
29
|
+
self.send "hoard", "#{path}/#{File.basename(f)}"
|
30
|
+
else
|
31
|
+
unless File.basename(f) == "hoarder.yml"
|
32
|
+
puts "Creating file #{File.basename(f)}"
|
33
|
+
@storage.locker.files.create(
|
34
|
+
:key => file_name(f, path),
|
35
|
+
:body => File.open("#{current_path}/#{f}"),
|
36
|
+
:public => @storage.public
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
rescue
|
41
|
+
puts "Error creating file #{file_name(f, path)}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def ignore_file?(file)
|
48
|
+
['.', '..'].include?(File.basename(file)) || hidden_file?(File.basename(file)) ? true : false
|
49
|
+
end
|
50
|
+
|
51
|
+
def relative_path(path)
|
52
|
+
path.split('/').slice(@storage.absolute_path.split('/').size..path.split('/').size).join('/')
|
53
|
+
end
|
54
|
+
private :relative_path
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Hoarder
|
2
|
+
class Storage
|
3
|
+
|
4
|
+
def initialize(path)
|
5
|
+
@absolute_path = path
|
6
|
+
@config = load_config("#{@absolute_path}/hoarder.yml")
|
7
|
+
@public = @config['public'] || true
|
8
|
+
@connection = set_connection(@config['provider'], @config)
|
9
|
+
@locker = set_locker(@config['container'], @public)
|
10
|
+
end
|
11
|
+
|
12
|
+
def absolute_path
|
13
|
+
@absolute_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def locker
|
17
|
+
@locker
|
18
|
+
end
|
19
|
+
|
20
|
+
def public
|
21
|
+
@public
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_config(config_file)
|
25
|
+
if FileTest.exist?(config_file)
|
26
|
+
begin
|
27
|
+
config = File.open(config_file) {|yf| YAML::load(yf)} || {}
|
28
|
+
validate_config(config)
|
29
|
+
rescue
|
30
|
+
raise "Unable to load config file #{config_file}."
|
31
|
+
end
|
32
|
+
else
|
33
|
+
raise "Missing config file #{config_file}."
|
34
|
+
end
|
35
|
+
config
|
36
|
+
end
|
37
|
+
private :load_config
|
38
|
+
|
39
|
+
def set_connection(provider, options = {})
|
40
|
+
Fog::Storage.new({
|
41
|
+
:provider => 'Rackspace',
|
42
|
+
:rackspace_api_key => options['rackspace_api_key'],
|
43
|
+
:rackspace_username => options['rackspace_username']
|
44
|
+
})
|
45
|
+
end
|
46
|
+
private :set_connection
|
47
|
+
|
48
|
+
def set_locker(name, make_public)
|
49
|
+
locker = @connection.directories.get(name)
|
50
|
+
locker.nil? ? @connection.directories.create(:key => name, :public => make_public) : locker
|
51
|
+
end
|
52
|
+
private :set_locker
|
53
|
+
|
54
|
+
def validate_config(config)
|
55
|
+
raise if config.empty?
|
56
|
+
end
|
57
|
+
private :validate_config
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hoarder::Storage, "#initialize" do
|
4
|
+
let(:config) { {:provider => 'rackspace', :rackspace_username => 'testguy', :rackspace_api_key => 'iamakey'} }
|
5
|
+
let(:connection) { mock(Fog::Storage) }
|
6
|
+
|
7
|
+
before {
|
8
|
+
Fog::Storage.stub(:new).and_return(connection)
|
9
|
+
}
|
10
|
+
|
11
|
+
context "when config file is missing" do
|
12
|
+
before {
|
13
|
+
FileTest.stub(:exist?).and_return(false)
|
14
|
+
}
|
15
|
+
specify {
|
16
|
+
lambda { Hoarder::Storage.new('') }.should raise_error(RuntimeError, "Missing config file /hoarder.yml.")
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when config file is not missing" do
|
21
|
+
before {
|
22
|
+
FileTest.stub(:exist?).and_return(true)
|
23
|
+
File.stub(:open).and_return('')
|
24
|
+
}
|
25
|
+
|
26
|
+
context "and opening file causes exception" do
|
27
|
+
specify {
|
28
|
+
lambda { Hoarder::Storage.new('') }.should raise_error(RuntimeError, "Unable to load config file /hoarder.yml.")
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
context "and opening file does not cause an exception" do
|
33
|
+
|
34
|
+
context "and config file is empty" do
|
35
|
+
before {
|
36
|
+
YAML.stub(:load).and_return({})
|
37
|
+
}
|
38
|
+
specify {
|
39
|
+
lambda { Hoarder::Storage.new('') }.should raise_error(RuntimeError, "Unable to load config file /hoarder.yml.")
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hoarder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Cheung
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-11-17 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: fog
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
description: A utility to push static files to cloud storage.
|
28
|
+
email:
|
29
|
+
- mncheu@gmail.com
|
30
|
+
executables:
|
31
|
+
- hoarder
|
32
|
+
extensions: []
|
33
|
+
|
34
|
+
extra_rdoc_files: []
|
35
|
+
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- README.markdown
|
40
|
+
- Rakefile
|
41
|
+
- bin/hoarder
|
42
|
+
- hoarder.gemspec
|
43
|
+
- hoarder.yml.sample
|
44
|
+
- lib/hoarder.rb
|
45
|
+
- lib/hoarder/hoarder.rb
|
46
|
+
- lib/hoarder/storage.rb
|
47
|
+
- lib/hoarder/version.rb
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
- spec/storage_spec.rb
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: ""
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project: hoarder
|
74
|
+
rubygems_version: 1.5.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: For those who can't let go of their files.
|
78
|
+
test_files: []
|
79
|
+
|