backup2everbox 0.0.1
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 +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +96 -0
- data/README +41 -0
- data/Rakefile +2 -0
- data/TODO +1 -0
- data/backup2everbox.gemspec +26 -0
- data/lib/backup/connection/everbox.rb +240 -0
- data/lib/backup/record/everbox.rb +23 -0
- data/lib/backup/storage/everbox.rb +12 -0
- data/lib/backup2everbox.rb +33 -0
- data/lib/backup2everbox/version.rb +3 -0
- metadata +134 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
backup2everbox (0.0.1)
|
5
|
+
activesupport
|
6
|
+
backup
|
7
|
+
oauth
|
8
|
+
rest-client
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activemodel (3.0.3)
|
14
|
+
activesupport (= 3.0.3)
|
15
|
+
builder (~> 2.1.2)
|
16
|
+
i18n (~> 0.4)
|
17
|
+
activerecord (3.0.3)
|
18
|
+
activemodel (= 3.0.3)
|
19
|
+
activesupport (= 3.0.3)
|
20
|
+
arel (~> 2.0.2)
|
21
|
+
tzinfo (~> 0.3.23)
|
22
|
+
activesupport (3.0.3)
|
23
|
+
arel (2.0.7)
|
24
|
+
backup (2.4.4)
|
25
|
+
activerecord (>= 2.3.5)
|
26
|
+
cloudfiles (>= 1.4.7)
|
27
|
+
dropbox (>= 1.1.2)
|
28
|
+
fog (~> 0.3.5)
|
29
|
+
hirb (>= 0.2.9)
|
30
|
+
json_pure (~> 1.4.6)
|
31
|
+
net-scp (>= 1.0.2)
|
32
|
+
net-sftp (>= 2.0.4)
|
33
|
+
net-ssh (>= 2.0.15)
|
34
|
+
pony (>= 0.5)
|
35
|
+
sqlite3-ruby (>= 1.2.5)
|
36
|
+
builder (2.1.2)
|
37
|
+
cloudfiles (1.4.10)
|
38
|
+
mime-types (>= 1.16)
|
39
|
+
dropbox (1.2.3)
|
40
|
+
json (>= 1.2.0)
|
41
|
+
mechanize (>= 1.0.0)
|
42
|
+
multipart-post (>= 1.0)
|
43
|
+
oauth (>= 0.3.6)
|
44
|
+
excon (0.4.0)
|
45
|
+
fog (0.3.34)
|
46
|
+
builder
|
47
|
+
excon (>= 0.3.6)
|
48
|
+
formatador (>= 0.0.16)
|
49
|
+
json
|
50
|
+
mime-types
|
51
|
+
net-ssh (>= 2.0.23)
|
52
|
+
nokogiri (>= 1.4.4)
|
53
|
+
ruby-hmac
|
54
|
+
formatador (0.0.16)
|
55
|
+
hirb (0.3.6)
|
56
|
+
i18n (0.5.0)
|
57
|
+
json (1.5.1)
|
58
|
+
json_pure (1.4.6)
|
59
|
+
mail (2.2.15)
|
60
|
+
activesupport (>= 2.3.6)
|
61
|
+
i18n (>= 0.4.0)
|
62
|
+
mime-types (~> 1.16)
|
63
|
+
treetop (~> 1.4.8)
|
64
|
+
mechanize (1.0.0)
|
65
|
+
nokogiri (>= 1.2.1)
|
66
|
+
mime-types (1.16)
|
67
|
+
multipart-post (1.1.0)
|
68
|
+
net-scp (1.0.4)
|
69
|
+
net-ssh (>= 1.99.1)
|
70
|
+
net-sftp (2.0.5)
|
71
|
+
net-ssh (>= 2.0.9)
|
72
|
+
net-ssh (2.1.0)
|
73
|
+
nokogiri (1.4.4)
|
74
|
+
oauth (0.4.4)
|
75
|
+
polyglot (0.3.1)
|
76
|
+
pony (1.1)
|
77
|
+
mail (> 2.0)
|
78
|
+
rest-client (1.6.1)
|
79
|
+
mime-types (>= 1.16)
|
80
|
+
ruby-hmac (0.4.0)
|
81
|
+
sqlite3 (1.3.3)
|
82
|
+
sqlite3-ruby (1.3.3)
|
83
|
+
sqlite3 (>= 1.3.3)
|
84
|
+
treetop (1.4.9)
|
85
|
+
polyglot (>= 0.3.1)
|
86
|
+
tzinfo (0.3.24)
|
87
|
+
|
88
|
+
PLATFORMS
|
89
|
+
ruby
|
90
|
+
|
91
|
+
DEPENDENCIES
|
92
|
+
activesupport
|
93
|
+
backup
|
94
|
+
backup2everbox!
|
95
|
+
oauth
|
96
|
+
rest-client
|
data/README
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
使用方法
|
2
|
+
========
|
3
|
+
|
4
|
+
1. 注册一个 EverBox 帐号: http://www.everbox.com/ , 注意必须注册盛大通行证帐号,
|
5
|
+
如果需要邀请码,请到 http://www.douban.com/group/topic/17242955/
|
6
|
+
|
7
|
+
2. 运行 sudo gem install backup2everbox
|
8
|
+
|
9
|
+
3. 运行 sudo backup --setup
|
10
|
+
|
11
|
+
4. 修改 /opt/backup/config/backup.rb, 改为如下的形式
|
12
|
+
|
13
|
+
# ----8<----------
|
14
|
+
gem 'backup2everbox'
|
15
|
+
require 'backup2everbox'
|
16
|
+
|
17
|
+
backup 'archive-backup-everbox' do
|
18
|
+
|
19
|
+
adapter :archive do
|
20
|
+
files ["/path/to/dir/need/backup"]
|
21
|
+
end
|
22
|
+
|
23
|
+
storage :everbox do
|
24
|
+
username 'YOUR SDO USERNAME'
|
25
|
+
password 'YOUR SDO PASSWORD'
|
26
|
+
path '/backups'
|
27
|
+
end
|
28
|
+
|
29
|
+
keep_backups 10
|
30
|
+
encrypt_with_password false
|
31
|
+
notify false
|
32
|
+
|
33
|
+
end
|
34
|
+
# ----8<----------
|
35
|
+
|
36
|
+
5. 运行 sudo backup -r archive-backup-everbox
|
37
|
+
|
38
|
+
6. backup 支持备份目录,数据库等多种源,具体可以参考 backup 的文档:
|
39
|
+
https://github.com/meskyanichi/backup
|
40
|
+
|
41
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "backup2everbox/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "backup2everbox"
|
7
|
+
s.version = Backup2everbox::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["LI Daobing"]
|
10
|
+
s.email = ["lidaobing@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/backup2everbox"
|
12
|
+
s.summary = %q{backup to EverBox}
|
13
|
+
s.description = %q{backup to EverBox}
|
14
|
+
|
15
|
+
s.rubyforge_project = "backup2everbox"
|
16
|
+
|
17
|
+
s.add_dependency 'backup'
|
18
|
+
s.add_dependency 'activesupport'
|
19
|
+
s.add_dependency 'oauth'
|
20
|
+
s.add_dependency 'rest-client'
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
require 'oauth'
|
4
|
+
require 'json'
|
5
|
+
require 'rest_client'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
|
9
|
+
module Backup
|
10
|
+
module Connection
|
11
|
+
class Everbox
|
12
|
+
|
13
|
+
class Session
|
14
|
+
DEFAULT_OPTIONS = {
|
15
|
+
:api_key => 'GW4YtvBpPwHfY0rCSf2xeOqn7tT0YH2O4zftXCOM',
|
16
|
+
:secret_access_key => 'xlKLpZLVSe0Gk6q4w05PsDpzjEbV8SyE71exgz1i',
|
17
|
+
:oauth_site => 'http://account.everbox.com',
|
18
|
+
:fs_site => 'http://fs.everbox.com',
|
19
|
+
:chunk_size => 1024*1024*4
|
20
|
+
}
|
21
|
+
attr_accessor :authorizing_user, :authorizing_password, :access_token
|
22
|
+
def initialize(opts={})
|
23
|
+
@options = DEFAULT_OPTIONS.merge(opts || {})
|
24
|
+
@consumer = OAuth::Consumer.new @options[:api_key], @options[:secret_access_key], :site => 'http://account.everbox.com'
|
25
|
+
end
|
26
|
+
|
27
|
+
def authorize!
|
28
|
+
response = @consumer.request(:post, "/oauth/quick_token?provider=sdo&login=#{CGI.escape @authorizing_user}&password=#{CGI.escape @authorizing_password}")
|
29
|
+
if response.code.to_i != 200
|
30
|
+
raise "login failed: #{response.body}"
|
31
|
+
end
|
32
|
+
|
33
|
+
d = CGI.parse(response.body).inject({}) do |h,(k,v)|
|
34
|
+
h[k.strip.to_sym] = v.first
|
35
|
+
h[k.strip] = v.first
|
36
|
+
h
|
37
|
+
end
|
38
|
+
|
39
|
+
@access_token = OAuth::AccessToken.from_hash(@consumer, d)
|
40
|
+
end
|
41
|
+
|
42
|
+
def authorized?
|
43
|
+
!!@access_token
|
44
|
+
end
|
45
|
+
|
46
|
+
def upload(filename, remote_path, opts={})
|
47
|
+
remote_path = find_real_remote_path(remote_path)
|
48
|
+
mkdir_p(remote_path)
|
49
|
+
basename = File.basename(filename)
|
50
|
+
target_path = File.expand_path(basename, remote_path)
|
51
|
+
keys = calc_digests(filename)
|
52
|
+
params = {
|
53
|
+
:path => target_path,
|
54
|
+
:keys => keys,
|
55
|
+
:chunkSize => 4*1024*1024,
|
56
|
+
:fileSize => File.open(filename).stat.size,
|
57
|
+
:base => ''
|
58
|
+
}
|
59
|
+
pp params
|
60
|
+
info = JSON.parse(access_token.post(fs(:prepare_put), JSON.dump(params), {'Content-Type' => 'text/plain' }).body)
|
61
|
+
pp info
|
62
|
+
File.open(filename) do |f|
|
63
|
+
info["required"].each do |x|
|
64
|
+
puts "upload block ##{x["index"]}"
|
65
|
+
f.seek(x["index"] * @options[:chunk_size])
|
66
|
+
code, response = http_request x['url'], f.read(@options[:chunk_size]), :method => :put
|
67
|
+
if code != 200
|
68
|
+
raise code.to_s
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
ftime = (Time.now.to_i * 1000 * 1000 * 10).to_s
|
75
|
+
params = params.merge :editTime => ftime, :mimeType => 'application/octet-stream'
|
76
|
+
pp access_token
|
77
|
+
code, response = access_token.post(fs(:commit_put), params.to_json, {'Content-Type' => 'text/plain'})
|
78
|
+
pp code, response
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete(remote_path, opts={})
|
82
|
+
remote_path = find_real_remote_path(remote_path)
|
83
|
+
data = {
|
84
|
+
:paths => [remote_path],
|
85
|
+
}
|
86
|
+
response = access_token.post(fs(:delete), data.to_json, {'Content-Type' => 'text/plain'})
|
87
|
+
case response.code
|
88
|
+
when "200"
|
89
|
+
true
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
#raise "delete failed: #{response}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def find_real_remote_path(path)
|
98
|
+
if path.start_with?('/')
|
99
|
+
"/home" + path
|
100
|
+
else
|
101
|
+
"/home/" + path
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def edit_time(time = nil)
|
106
|
+
time ||= Time.now
|
107
|
+
(time.to_i * 1000 * 1000 * 10).to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
def mkdir_p(path)
|
111
|
+
return if path == "/"
|
112
|
+
mkdir_p(File.expand_path("..", path))
|
113
|
+
make_remote_path(path, :ignore_conflict => true)
|
114
|
+
end
|
115
|
+
|
116
|
+
def make_remote_path(path, opts = {})
|
117
|
+
data = {
|
118
|
+
:path => path,
|
119
|
+
:editTime => edit_time
|
120
|
+
}
|
121
|
+
response = access_token.post(fs(:mkdir), data.to_json, {'Content-Type' => 'text/plain'})
|
122
|
+
case response.code
|
123
|
+
when "200"
|
124
|
+
#
|
125
|
+
when "409"
|
126
|
+
unless opts[:ignore_conflict]
|
127
|
+
raise "directory already exist: `#{path}'"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
def http_request url, data = nil, options = {}
|
132
|
+
begin
|
133
|
+
options[:method] = :post unless options[:method]
|
134
|
+
case options[:method]
|
135
|
+
when :get
|
136
|
+
response = RestClient.get url, data, :content_type => options[:content_type]
|
137
|
+
when :post
|
138
|
+
response = RestClient.post url, data, :content_type => options[:content_type]
|
139
|
+
when :put
|
140
|
+
response = RestClient.put url, data
|
141
|
+
end
|
142
|
+
body = response.body
|
143
|
+
data = nil
|
144
|
+
data = JSON.parse body unless body.empty?
|
145
|
+
[response.code.to_i, data]
|
146
|
+
rescue => e
|
147
|
+
raise
|
148
|
+
code = 0
|
149
|
+
data = nil
|
150
|
+
body = nil
|
151
|
+
res = e.response if e.respond_to? :response
|
152
|
+
begin
|
153
|
+
code = res.code if res.respond_to? :code
|
154
|
+
body = res.body if res.respond_to? :body
|
155
|
+
data = JSON.parse body unless body.empty?
|
156
|
+
rescue
|
157
|
+
data = body
|
158
|
+
end
|
159
|
+
[code, data]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
def fs(path)
|
163
|
+
path = path.to_s
|
164
|
+
path = '/' + path unless path.start_with? '/'
|
165
|
+
@options[:fs_site] + path
|
166
|
+
end
|
167
|
+
def urlsafe_base64(content)
|
168
|
+
Base64.encode64(content).strip.gsub('+', '-').gsub('/','_')
|
169
|
+
end
|
170
|
+
|
171
|
+
def calc_digests(fname)
|
172
|
+
res = []
|
173
|
+
File.open(fname) do |ifile|
|
174
|
+
while (data = ifile.read(@options[:chunk_size])) do
|
175
|
+
res << urlsafe_base64(Digest::SHA1.digest(data))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
res
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
attr_accessor :adapter, :procedure, :final_file, :tmp_path, :api_key, :secret_access_key, :username, :password, :path
|
183
|
+
|
184
|
+
def initialize(adapter=false)
|
185
|
+
if adapter
|
186
|
+
self.adapter = adapter
|
187
|
+
self.procedure = adapter.procedure
|
188
|
+
self.final_file = adapter.final_file
|
189
|
+
self.tmp_path = adapter.tmp_path.gsub('\ ', ' ')
|
190
|
+
|
191
|
+
load_storage_configuration_attributes
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def static_initialize(procedure)
|
196
|
+
self.procedure = procedure
|
197
|
+
load_storage_configuration_attributes(true)
|
198
|
+
end
|
199
|
+
|
200
|
+
def session
|
201
|
+
opts = {}
|
202
|
+
opts[:api_key] = api_key unless api_key.nil?
|
203
|
+
opts[:secret_access_key] = secret_access_key unless secret_access_key.nil?
|
204
|
+
@session ||= Session.new(opts)
|
205
|
+
unless @session.authorized?
|
206
|
+
@session.authorizing_user = username
|
207
|
+
@session.authorizing_password = password
|
208
|
+
@session.authorize!
|
209
|
+
end
|
210
|
+
|
211
|
+
@session
|
212
|
+
end
|
213
|
+
|
214
|
+
def connect
|
215
|
+
session
|
216
|
+
end
|
217
|
+
|
218
|
+
def path
|
219
|
+
@path || "backups"
|
220
|
+
end
|
221
|
+
|
222
|
+
def store
|
223
|
+
path_to_file = File.join(tmp_path, final_file)
|
224
|
+
session.upload(path_to_file, path, :mode => :dropbox)
|
225
|
+
end
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def load_storage_configuration_attributes(static=false)
|
230
|
+
%w(api_key secret_access_key username password path).each do |attribute|
|
231
|
+
if static
|
232
|
+
send("#{attribute}=", procedure.get_storage_configuration.attributes[attribute])
|
233
|
+
else
|
234
|
+
send("#{attribute}=", adapter.procedure.get_storage_configuration.attributes[attribute])
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'backup/connection/everbox'
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Record
|
5
|
+
class Everbox < Backup::Record::Base
|
6
|
+
def load_specific_settings(adapter)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def self.destroy_backups(procedure, backups)
|
12
|
+
everbox = Backup::Connection::Everbox.new
|
13
|
+
everbox.static_initialize(procedure)
|
14
|
+
session = everbox.session
|
15
|
+
backups.each do |backup|
|
16
|
+
puts "\nDestroying backup \"#{backup.filename}\"."
|
17
|
+
path_to_file = File.join(everbox.path, backup.filename)
|
18
|
+
session.delete(path_to_file, :mode => :everbox)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'active_support/core_ext/module/aliasing'
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Connection
|
5
|
+
autoload :Everbox, 'backup/connection/everbox'
|
6
|
+
end
|
7
|
+
module Storage
|
8
|
+
autoload :Everbox, 'backup/storage/everbox'
|
9
|
+
end
|
10
|
+
module Record
|
11
|
+
autoload :Everbox, 'backup/record/everbox'
|
12
|
+
end
|
13
|
+
module Configuration
|
14
|
+
class Base
|
15
|
+
def storage_class_with_everbox
|
16
|
+
res = storage_class_without_everbox
|
17
|
+
if res.nil? and @storage_name == :everbox
|
18
|
+
res = Backup::Storage::Everbox
|
19
|
+
end
|
20
|
+
res
|
21
|
+
end
|
22
|
+
def record_class_with_everbox
|
23
|
+
res = record_class_without_everbox
|
24
|
+
if res.nil? and @storage_name == :everbox
|
25
|
+
res = Backup::Record::Everbox
|
26
|
+
end
|
27
|
+
res
|
28
|
+
end
|
29
|
+
alias_method_chain :storage_class, :everbox
|
30
|
+
alias_method_chain :record_class, :everbox
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: backup2everbox
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- LI Daobing
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-30 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: backup
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activesupport
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: oauth
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rest-client
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
77
|
+
description: backup to EverBox
|
78
|
+
email:
|
79
|
+
- lidaobing@gmail.com
|
80
|
+
executables: []
|
81
|
+
|
82
|
+
extensions: []
|
83
|
+
|
84
|
+
extra_rdoc_files: []
|
85
|
+
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- Gemfile
|
89
|
+
- Gemfile.lock
|
90
|
+
- README
|
91
|
+
- Rakefile
|
92
|
+
- TODO
|
93
|
+
- backup2everbox.gemspec
|
94
|
+
- lib/backup/connection/everbox.rb
|
95
|
+
- lib/backup/record/everbox.rb
|
96
|
+
- lib/backup/storage/everbox.rb
|
97
|
+
- lib/backup2everbox.rb
|
98
|
+
- lib/backup2everbox/version.rb
|
99
|
+
has_rdoc: true
|
100
|
+
homepage: http://rubygems.org/gems/backup2everbox
|
101
|
+
licenses: []
|
102
|
+
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
hash: 3
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
requirements: []
|
127
|
+
|
128
|
+
rubyforge_project: backup2everbox
|
129
|
+
rubygems_version: 1.4.2
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: backup to EverBox
|
133
|
+
test_files: []
|
134
|
+
|