s3sync 2.0.2 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/s3sync/cli.rb +37 -43
- data/lib/s3sync/config.rb +1 -1
- data/lib/s3sync/sync.rb +17 -15
- data/lib/s3sync/version.rb +1 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1647d25f01e1d5890e51aaddee4f23008ccc2b19
|
4
|
+
data.tar.gz: 2afdf32ee7d8cc6c15cde88e75462ecb57278141
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d027fe656ebfccf76cb80c61b1d7ee9926868a8a425c37c502ad88b408ac2743962840b0435d2f698ef990b0a5b78032bd0cada915384f97205104b26444359c
|
7
|
+
data.tar.gz: 2b5d672c278b9527f9821c6159145ef392b1a47b7d0e66c2467c58c21dc1d16a8f42939fc8cbc02a572229d10584e91645663352d05bf87088f27c0aa3576dbb
|
data/lib/s3sync/cli.rb
CHANGED
@@ -25,7 +25,7 @@
|
|
25
25
|
require 's3sync/version'
|
26
26
|
require 's3sync/exceptions'
|
27
27
|
require 's3sync/sync'
|
28
|
-
require 'aws
|
28
|
+
require 'aws-sdk'
|
29
29
|
require 'cmdparse'
|
30
30
|
|
31
31
|
|
@@ -63,9 +63,9 @@ module S3Sync
|
|
63
63
|
u.join ''
|
64
64
|
end
|
65
65
|
|
66
|
-
def execute(args)
|
66
|
+
def execute(*args)
|
67
67
|
# Connecting to amazon
|
68
|
-
s3 =
|
68
|
+
s3 = Aws::S3::Resource.new(client: Aws::S3::Client.new)
|
69
69
|
|
70
70
|
# From the command line
|
71
71
|
key, file = args
|
@@ -78,13 +78,13 @@ module S3Sync
|
|
78
78
|
# of the common errors here, saving duplications in each command;
|
79
79
|
begin
|
80
80
|
run s3, bucket, key, file, args
|
81
|
-
rescue
|
82
|
-
raise FailureFeedback.new("Access Denied")
|
83
|
-
rescue
|
81
|
+
rescue Aws::S3::Errors::SignatureDoesNotMatch, Aws::S3::Errors::InvalidAccessKeyId => e
|
82
|
+
raise FailureFeedback.new("Access Denied: #{e.message}")
|
83
|
+
rescue Aws::S3::Errors::NoSuchBucket
|
84
84
|
raise FailureFeedback.new("There's no bucket named `#{bucket}'")
|
85
|
-
rescue
|
85
|
+
rescue Aws::S3::Errors::NoSuchKey
|
86
86
|
raise FailureFeedback.new("There's no key named `#{key}' in the bucket `#{bucket}'")
|
87
|
-
rescue
|
87
|
+
rescue Aws::S3::Errors::ServiceError => exc
|
88
88
|
raise FailureFeedback.new("Error: `#{exc.message}'")
|
89
89
|
end
|
90
90
|
end
|
@@ -101,7 +101,7 @@ module S3Sync
|
|
101
101
|
|
102
102
|
class ListBuckets < BaseCmd
|
103
103
|
def initialize
|
104
|
-
super 'listbuckets', false
|
104
|
+
super 'listbuckets', takes_commands: false #, false, false
|
105
105
|
|
106
106
|
@short_desc = "List all available buckets for your user"
|
107
107
|
end
|
@@ -117,11 +117,11 @@ module S3Sync
|
|
117
117
|
attr_accessor :acl
|
118
118
|
|
119
119
|
def initialize
|
120
|
-
super 'createbucket', false
|
120
|
+
super 'createbucket', takes_commands: false #, false
|
121
121
|
|
122
122
|
@short_desc = "Create a new bucket under your user account"
|
123
123
|
|
124
|
-
self.options
|
124
|
+
self.options do |opt|
|
125
125
|
parse_acl(opt)
|
126
126
|
end
|
127
127
|
end
|
@@ -136,8 +136,8 @@ module S3Sync
|
|
136
136
|
params.merge!({:acl => @acl})
|
137
137
|
end
|
138
138
|
|
139
|
-
s3.
|
140
|
-
rescue
|
139
|
+
s3.client.create_bucket(params.merge(bucket: bucket))
|
140
|
+
rescue Aws::S3::Errors::BucketAlreadyExists
|
141
141
|
raise FailureFeedback.new("Bucket `#{bucket}' already exists")
|
142
142
|
end
|
143
143
|
end
|
@@ -147,13 +147,13 @@ module S3Sync
|
|
147
147
|
attr_accessor :force
|
148
148
|
|
149
149
|
def initialize
|
150
|
-
super 'deletebucket', false
|
150
|
+
super 'deletebucket', takes_commands: false #, false
|
151
151
|
|
152
152
|
@short_desc = "Remove a bucket from your account"
|
153
153
|
|
154
154
|
@force = false
|
155
155
|
|
156
|
-
self.options
|
156
|
+
self.options do |opt|
|
157
157
|
opt.on("-f", "--force", "Clean the bucket then deletes it") {|f|
|
158
158
|
@force = f
|
159
159
|
}
|
@@ -164,7 +164,7 @@ module S3Sync
|
|
164
164
|
raise WrongUsage.new(nil, "You need to inform a bucket") if not bucket
|
165
165
|
|
166
166
|
# Getting the bucket
|
167
|
-
bucket_obj = s3.
|
167
|
+
bucket_obj = s3.bucket(bucket)
|
168
168
|
|
169
169
|
# Do not kill buckets with content unless explicitly asked
|
170
170
|
if not @force and bucket_obj.objects.count > 0
|
@@ -179,7 +179,7 @@ module S3Sync
|
|
179
179
|
attr_accessor :max_entries
|
180
180
|
|
181
181
|
def initialize
|
182
|
-
super 'list', false
|
182
|
+
super 'list', takes_commands: false #, false
|
183
183
|
|
184
184
|
@short_desc = "List items filed under a given bucket"
|
185
185
|
|
@@ -189,7 +189,7 @@ module S3Sync
|
|
189
189
|
|
190
190
|
@has_prefix = true
|
191
191
|
|
192
|
-
self.options
|
192
|
+
self.options do |opt|
|
193
193
|
opt.on("-m", "--max-entries=NUM", "Limit the number of entries to output") {|m|
|
194
194
|
@max_entries = m
|
195
195
|
}
|
@@ -203,7 +203,7 @@ module S3Sync
|
|
203
203
|
def run s3, bucket, key, file, args
|
204
204
|
raise WrongUsage.new(nil, "You need to inform a bucket") if not bucket
|
205
205
|
|
206
|
-
collection = s3.
|
206
|
+
collection = s3.bucket(bucket).objects( prefix: (key || "") )
|
207
207
|
|
208
208
|
if @max_entries > 0
|
209
209
|
collection = collection.page(:per_page => @max_entries)
|
@@ -223,7 +223,7 @@ module S3Sync
|
|
223
223
|
|
224
224
|
class Delete < BaseCmd
|
225
225
|
def initialize
|
226
|
-
super 'delete', false
|
226
|
+
super 'delete', takes_commands: false #, false
|
227
227
|
|
228
228
|
@short_desc = "Delete a key from a bucket"
|
229
229
|
|
@@ -233,7 +233,7 @@ module S3Sync
|
|
233
233
|
def run s3, bucket, key, file, args
|
234
234
|
raise WrongUsage.new(nil, "You need to inform a bucket") if not bucket
|
235
235
|
raise WrongUsage.new(nil, "You need to inform a key") if not key
|
236
|
-
s3.buckets
|
236
|
+
s3.buckets(bucket).object(key).delete
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
@@ -242,7 +242,7 @@ module S3Sync
|
|
242
242
|
attr_accessor :secure
|
243
243
|
|
244
244
|
def initialize
|
245
|
-
super 'url', false
|
245
|
+
super 'url', takes_commands: false #, false
|
246
246
|
|
247
247
|
@short_desc = "Generates public urls or authenticated endpoints for the object"
|
248
248
|
@description = "Notice that --method and --public are mutually exclusive"
|
@@ -252,7 +252,7 @@ module S3Sync
|
|
252
252
|
@expires_in = false
|
253
253
|
@has_prefix = 'required'
|
254
254
|
|
255
|
-
self.options
|
255
|
+
self.options do |opt|
|
256
256
|
opt.on("-m", "--method=METHOD", "Options: #{AVAILABLE_METHODS.join ', '}") {|m|
|
257
257
|
@method = m
|
258
258
|
}
|
@@ -295,17 +295,17 @@ module S3Sync
|
|
295
295
|
opts.merge!({:secure => @secure})
|
296
296
|
|
297
297
|
if @public
|
298
|
-
puts s3.
|
298
|
+
puts s3.bucket(bucket).object(key).public_url(opts).to_s
|
299
299
|
else
|
300
300
|
opts.merge!({:expires => @expires_in}) if @expires_in
|
301
|
-
puts s3.
|
301
|
+
puts s3.bucket(bucket).object(key).presigned_url(method.to_sym, opts).to_s
|
302
302
|
end
|
303
303
|
end
|
304
304
|
end
|
305
305
|
|
306
306
|
class Put < BaseCmd
|
307
307
|
def initialize
|
308
|
-
super 'put', false
|
308
|
+
super 'put', takes_commands: false #, false
|
309
309
|
|
310
310
|
@short_desc = 'Upload a file to a bucket under a certain prefix'
|
311
311
|
@has_prefix = true
|
@@ -320,13 +320,13 @@ module S3Sync
|
|
320
320
|
raise WrongUsage.new(nil, "You need to inform a file") if not file
|
321
321
|
|
322
322
|
name = S3Sync.safe_join [key, File.basename(file)]
|
323
|
-
s3.
|
323
|
+
s3.bucket(bucket).object(name).upload_file(Pathname.new(file))
|
324
324
|
end
|
325
325
|
end
|
326
326
|
|
327
327
|
class Get < BaseCmd
|
328
328
|
def initialize
|
329
|
-
super 'get', false
|
329
|
+
super 'get', takes_commands: false #, false
|
330
330
|
@short_desc = "Retrieve an object and save to the specified file"
|
331
331
|
@has_prefix = 'required'
|
332
332
|
end
|
@@ -345,7 +345,7 @@ module S3Sync
|
|
345
345
|
path = File.absolute_path file
|
346
346
|
path = S3Sync.safe_join [path, File.basename(key)] if File.directory? path
|
347
347
|
File.open(path, 'wb') do |f|
|
348
|
-
s3.
|
348
|
+
s3.bucket(bucket).object(key).get do |chunk| f.write(chunk) end
|
349
349
|
end
|
350
350
|
end
|
351
351
|
end
|
@@ -359,7 +359,7 @@ module S3Sync
|
|
359
359
|
attr_accessor :acl
|
360
360
|
|
361
361
|
def initialize
|
362
|
-
super 'sync', false
|
362
|
+
super 'sync', takes_commands: false #, false
|
363
363
|
|
364
364
|
@short_desc = "Synchronize an S3 and a local folder"
|
365
365
|
@s3 = nil
|
@@ -368,7 +368,7 @@ module S3Sync
|
|
368
368
|
@dry_run = false
|
369
369
|
@verbose = false
|
370
370
|
|
371
|
-
self.options
|
371
|
+
self.options do |opt|
|
372
372
|
opt.on("-x EXPR", "--exclude=EXPR", "Skip copying files that matches this pattern. (Ruby REs)") {|v|
|
373
373
|
@exclude = v
|
374
374
|
}
|
@@ -425,22 +425,16 @@ END
|
|
425
425
|
end
|
426
426
|
|
427
427
|
def run conf
|
428
|
-
cmd = CmdParse::CommandParser.new true
|
429
|
-
cmd.
|
430
|
-
|
428
|
+
cmd = CmdParse::CommandParser.new handle_exceptions: true
|
429
|
+
cmd.main_options do |opt|
|
430
|
+
opt.program_name = File.basename $0
|
431
|
+
opt.version = S3Sync::VERSION
|
432
|
+
end
|
431
433
|
|
432
|
-
cmd.
|
434
|
+
cmd.global_options do |opt|
|
433
435
|
opt.separator "Global options:"
|
434
436
|
end
|
435
437
|
|
436
|
-
cmd.main_command.short_desc = 'Tool belt for managing your S3 buckets'
|
437
|
-
cmd.main_command.description =<<END.strip
|
438
|
-
S3Sync provides a list of commands that will allow you to manage your content
|
439
|
-
stored in S3 buckets. To learn about each feature, please use the `help`
|
440
|
-
command:
|
441
|
-
|
442
|
-
$ #{File.basename $0} help sync"
|
443
|
-
END
|
444
438
|
# Commands used more often
|
445
439
|
cmd.add_command List.new
|
446
440
|
cmd.add_command Delete.new
|
data/lib/s3sync/config.rb
CHANGED
@@ -43,7 +43,7 @@ module S3Sync
|
|
43
43
|
|
44
44
|
class Config < Hash
|
45
45
|
|
46
|
-
REQUIRED_VARS = [:AWS_ACCESS_KEY_ID, :AWS_SECRET_ACCESS_KEY]
|
46
|
+
REQUIRED_VARS = [:AWS_ACCESS_KEY_ID, :AWS_SECRET_ACCESS_KEY, :AWS_REGION]
|
47
47
|
|
48
48
|
CONFIG_PATHS = ["#{ENV['S3SYNC_PATH']}", "#{ENV['HOME']}/.s3sync.yml", "/etc/s3sync.yml"]
|
49
49
|
|
data/lib/s3sync/sync.rb
CHANGED
@@ -172,6 +172,7 @@ module S3Sync
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def initialize args, source, destination
|
175
|
+
# @args.s3 should be of type Aws::S3::Resource
|
175
176
|
@args = args
|
176
177
|
@source = source
|
177
178
|
@destination = destination
|
@@ -302,11 +303,14 @@ module S3Sync
|
|
302
303
|
dir += '/' if not dir.empty? and not dir.end_with?('/')
|
303
304
|
|
304
305
|
nodes = {}
|
305
|
-
|
306
|
+
|
307
|
+
@args.s3.bucket(location.bucket).objects(prefix: (dir || "")).to_a.collect do |obj|
|
306
308
|
# etag comes back with quotes (obj.etag.inspcet # => "\"abc...def\""
|
307
309
|
small_comparator = lambda { obj.etag[/[a-z0-9]+/] }
|
308
310
|
node = Node.new(location.path, obj.key, obj.content_length, small_comparator)
|
309
|
-
|
311
|
+
# The key is relative path from dir.
|
312
|
+
key = node.path[(dir || "").length,node.path.length - 1]
|
313
|
+
nodes[key] = node
|
310
314
|
end
|
311
315
|
return nodes
|
312
316
|
end
|
@@ -326,12 +330,12 @@ module S3Sync
|
|
326
330
|
def upload_files remote, list
|
327
331
|
list.each do |e|
|
328
332
|
if @args.verbose
|
329
|
-
puts " + #{e.full} => #{remote}#{e.path}"
|
333
|
+
puts " + #{e.full} => #{remote.path}#{e.path}"
|
330
334
|
end
|
331
335
|
|
332
336
|
unless @args.dry_run
|
333
337
|
remote_path = "#{remote.path}#{e.path}"
|
334
|
-
@args.s3.
|
338
|
+
@args.s3.bucket(remote.bucket).object(remote_path).upload_file(Pathname.new(e.full), acl: @args.acl)
|
335
339
|
end
|
336
340
|
end
|
337
341
|
end
|
@@ -344,7 +348,9 @@ module S3Sync
|
|
344
348
|
end
|
345
349
|
|
346
350
|
unless @args.dry_run
|
347
|
-
|
351
|
+
list.map(&:path).each do |object_key|
|
352
|
+
@args.s3.bucket(remote.bucket).object(object_key).delete
|
353
|
+
end
|
348
354
|
end
|
349
355
|
end
|
350
356
|
|
@@ -354,11 +360,11 @@ module S3Sync
|
|
354
360
|
path = File.join destination.path, e.path
|
355
361
|
|
356
362
|
if @args.verbose
|
357
|
-
puts " + #{source}
|
363
|
+
puts " + #{source.bucket}:#{e.path} => #{path}"
|
358
364
|
end
|
359
365
|
|
360
366
|
unless @args.dry_run
|
361
|
-
obj = @args.s3.
|
367
|
+
obj = @args.s3.bucket(source.bucket).object(e.path)
|
362
368
|
|
363
369
|
# Making sure this new file will have a safe shelter
|
364
370
|
FileUtils.mkdir_p File.dirname(path)
|
@@ -371,14 +377,10 @@ module S3Sync
|
|
371
377
|
else
|
372
378
|
# Downloading and saving the files
|
373
379
|
File.open(path, 'wb') do |file|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
rescue AWS::Core::Http::NetHttpHandler::TruncatedBodyError => e
|
379
|
-
$stderr.puts "WARNING: (retryable) TruncatedBodyError occured, retrying in a second #{file.basename}"
|
380
|
-
sleep 1
|
381
|
-
retry
|
380
|
+
# By default Aws::S3::Client will retry 3 times if there is a network error.
|
381
|
+
# To increase this number or disable it, set :retry_limit when instantiating the S3 client.
|
382
|
+
obj.get do |chunk|
|
383
|
+
file.write chunk
|
382
384
|
end
|
383
385
|
end
|
384
386
|
end
|
data/lib/s3sync/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lincoln de Sousa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.3.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: cmdparse
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '3.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: simplecov
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,9 +134,9 @@ require_paths:
|
|
134
134
|
- lib
|
135
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- - "
|
137
|
+
- - "~>"
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: '
|
139
|
+
version: '2'
|
140
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
142
|
- - ">="
|
@@ -144,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: '0'
|
145
145
|
requirements: []
|
146
146
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.
|
147
|
+
rubygems_version: 2.5.1
|
148
148
|
signing_key:
|
149
149
|
specification_version: 4
|
150
150
|
summary: s3sync is a library that aggregates a good range of features for managing
|