s3cp 1.1.12 → 1.1.13

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.
@@ -1,3 +1,12 @@
1
+ === 1.1.13 (2013-01-27)
2
+
3
+ * Added: s3stat --acl option to display associated access-control list XML document.
4
+
5
+ * Added: s3mod now accepts multiple (wildcard) paths and supports setting both
6
+ --headers and --acl. (Denis Arh).
7
+
8
+ * Fixed: Beter metadata display in s3stat.
9
+
1
10
  === 1.1.12 (2013-01-22)
2
11
 
3
12
  * Added: Support for 'Content-Disposition' header (Denis Arh).
@@ -17,17 +17,51 @@
17
17
 
18
18
  require 's3cp/utils'
19
19
 
20
+ # Default options
21
+ options = {
22
+ :verbose => false,
23
+ :acl => nil,
24
+ :headers => []
25
+ }
26
+
27
+ # Setup cli params
20
28
  op = OptionParser.new do |opts|
21
- opts.banner = "s3mod [path] [permission]"
29
+ opts.banner = "s3mod [path(s)]"
30
+
31
+ opts.banner = <<-BANNER
32
+ s3mod [path(s)] ([permission])
33
+
34
+ Multiple paths with multiple wildcards are supported:
35
+ s3://bucket/path/*foo/*/bar*.jpg
36
+
37
+ LEGACY SUPPORT
38
+
39
+ This tool still supports old paramater format:
40
+ % s3mod [path] [permission]
41
+ You are encouraged to use --acl instead of passing permission as last parameter.
42
+
43
+ WARNINGS:
44
+
45
+ 1) Due to limitations in AWS's S3 API, when you use --headers all ACL
46
+ properties are removed from the S3 object.
47
+
48
+ 2) Due to limitations in AWS's S3 API, this command fails on S3 objects
49
+ larger then 5Gb.
50
+
51
+ BANNER
52
+ opts.separator ''
53
+
54
+ opts.on("--verbose", "Verbose mode") do
55
+ options[:verbose] = true
56
+ end
22
57
 
23
- opts.separator ""
24
- opts.separator "where [permission] is one of:"
25
- opts.separator ""
26
- opts.separator " * private"
27
- opts.separator " * authenticated-read"
28
- opts.separator " * public-read"
29
- opts.separator " * public-read-write"
30
- opts.separator ""
58
+ opts.on('--headers \'Header1: Header1Value\',\'Header2: Header2Value\'', Array, "Headers to set on the item in S3." ) do |h|
59
+ options[:headers] = h
60
+ end
61
+
62
+ opts.on("--acl PERMISSION", "One of 'private', 'authenticated-read', 'public-read', 'public-read-write'") do |permission|
63
+ options[:acl] = S3CP.validate_acl(permission)
64
+ end
31
65
 
32
66
  opts.on_tail("-h", "--help", "Show this message") do
33
67
  puts op
@@ -36,22 +70,36 @@ op = OptionParser.new do |opts|
36
70
  end
37
71
 
38
72
  op.parse!(ARGV)
73
+ paths = ARGV
39
74
 
40
- if ARGV.size < 2
75
+ if ARGV.size < 1 || !options[:headers]
41
76
  puts op
42
77
  exit
43
78
  end
44
79
 
45
- def update_permissions(s3, bucket, key, permission)
46
- puts "Setting #{permission} on s3://#{bucket}/#{key}"
47
- s3.buckets[bucket].objects[key].acl = permission
80
+ # Legacy (support for s3mod [path] [acl] )
81
+ # See if last param starts with "s3://", validate & remove it from list of paths
82
+ if !options[:acl] && paths.size > 1 && S3CP::LEGAL_MODS.include?(paths.last)
83
+ options[:acl] = S3CP.validate_acl(paths.pop);
48
84
  end
49
85
 
50
- source = ARGV[0]
51
- permission = S3CP.validate_acl(ARGV.last)
52
-
53
86
  S3CP.load_config()
54
-
55
87
  @s3 = S3CP.connect()
56
- bucket,key = S3CP.bucket_and_key(source)
57
- update_permissions(@s3, bucket, key, permission)
88
+
89
+ paths.each do |path|
90
+ bucket,key = S3CP.bucket_and_key(path)
91
+ fail "Invalid bucket/key: #{path}" unless key
92
+
93
+ S3CP.objects_by_wildcard(@s3.buckets[bucket], key) { | obj |
94
+ puts "s3://#{bucket}/#{obj.key}"
95
+
96
+ if options[:headers].size > 0
97
+ current_medata = obj.metadata
98
+ object_metadata = S3CP.set_header_options(current_medata, S3CP.headers_array_to_hash(options[:headers]))
99
+ end
100
+
101
+ if options[:acl]
102
+ obj.acl = options[:acl]
103
+ end
104
+ }
105
+ end
@@ -17,9 +17,15 @@
17
17
 
18
18
  require 's3cp/utils'
19
19
 
20
+ @options = {}
21
+
20
22
  op = OptionParser.new do |opts|
21
23
  opts.banner = "s3stat [path]"
22
24
 
25
+ opts.on("--acl", "Display Access Control List XML document") do
26
+ @options[:acl] = true
27
+ end
28
+
23
29
  opts.on_tail("-h", "--help", "Show this message") do
24
30
  puts op
25
31
  exit
@@ -43,8 +49,15 @@ S3CP.load_config()
43
49
 
44
50
  @s3 = S3CP.connect().buckets[@bucket]
45
51
 
46
- metadata = @s3.objects[@key].head
52
+ obj = @s3.objects[@key]
53
+
54
+ metadata = obj.head
47
55
  metadata.keys.sort { |k1, k2| k1.to_s <=> k2.to_s}.each do |k|
48
- puts "#{"%30s" % k} #{metadata[k]}"
56
+ puts "#{"%30s" % k} #{metadata[k].is_a?(Hash) ? metadata[k].inspect : metadata[k].to_s}"
49
57
  end
50
58
 
59
+ if @options[:acl]
60
+ puts
61
+ xml = Nokogiri::XML(obj.acl.to_s)
62
+ puts xml.to_s
63
+ end
@@ -175,8 +175,9 @@ module S3CP
175
175
  end
176
176
  end
177
177
 
178
-
179
- options[:metadata] = remaining unless remaining.empty?
178
+ remaining.each do |k,v|
179
+ options[k] = v
180
+ end
180
181
 
181
182
  options
182
183
  end
@@ -187,6 +188,31 @@ module S3CP
187
188
  end
188
189
  permission
189
190
  end
191
+
192
+ # Yield to block for all objects matching key_regex
193
+ def objects_by_wildcard(bucket, key_regex, &block)
194
+ # First, trim multiple wildcards & wildcards on the end
195
+ key = key_regex.gsub(/\*+/, '*')
196
+
197
+ if 0 < key.count('*')
198
+ key_split = key.split('*', 2);
199
+ kpfix = key_split.shift(); # ignore first part as AWS API takes it as a prefix
200
+ regex = []
201
+
202
+ key_split.each do |kpart|
203
+ regex.push Regexp.quote(kpart)
204
+ end
205
+
206
+ regex = regex.empty? ? nil : Regexp.new(regex.join('.*') + '$');
207
+
208
+ bucket.objects.with_prefix(kpfix).each do |obj|
209
+ yield obj if regex == nil || regex.match(obj.key[kpfix.size..-1])
210
+ end
211
+ else
212
+ # no wildcards, simple:
213
+ yield bucket.objects[key]
214
+ end
215
+ end
190
216
  end
191
217
 
192
218
  # Monkey-patch S3 object for download streaming
@@ -16,5 +16,5 @@
16
16
  # the License.
17
17
 
18
18
  module S3CP
19
- VERSION = "1.1.12"
19
+ VERSION = "1.1.13"
20
20
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3cp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 12
10
- version: 1.1.12
9
+ - 13
10
+ version: 1.1.13
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Boisvert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-01-22 00:00:00 Z
18
+ date: 2013-01-27 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement