s3cp 1.1.31 → 1.1.32

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,44 @@
1
+ === 1.1.32 (2013-08-26)
2
+
3
+ * Added: New --mkdir option on s3cp allowing to recreate the source directory
4
+ structure from any point in the source path(s).
5
+
6
+ The --mkdir option accepts a regular expression to match against the
7
+ source path(s) and will recreate the source directory structure from
8
+ the match point.
9
+
10
+ Assuming the following bucket content,
11
+
12
+ s3://bucket/foo/bar/1
13
+ s3://bucket/foo/bar/2
14
+ s3://bucket/foo/baz/3
15
+ s3://bucket/foo/baz/4
16
+
17
+ then running:
18
+
19
+ % s3cp --recursive --mkdir /foo/ s3://bucket/foo/bar .
20
+
21
+ would create the following local directories and files:
22
+
23
+ ./foo/bar/1
24
+ ./foo/bar/2
25
+
26
+ If the regular expression contains a capturing group, the destination
27
+ path(s) will be relative to the group's starting position instead of
28
+ the regular expression's matching position:
29
+
30
+ % s3cp --recursive --mkdir "/foo/(.)" s3://bucket/foo/ .
31
+
32
+ would create the following local content:
33
+
34
+ ./bar/1
35
+ ./bar/2
36
+ ./baz/3
37
+ ./baz/4
38
+
39
+ Note: The --mkdir option is currently only valid when copying from S3
40
+ to the local filesystem.
41
+
1
42
  === 1.1.31 (2013-05-16)
2
43
 
3
44
  * Fixed: Passing ACLs to s3cp using --header 'x-amz-acl: public-read' was broken
data/lib/s3cp/s3cat.rb CHANGED
@@ -31,8 +31,12 @@ op = OptionParser.new do |opts|
31
31
  options[:debug] = true
32
32
  end
33
33
 
34
- opts.on("--tty", "TTY mode") do |tty|
35
- options[:tty] = tty
34
+ opts.on("--tty", "Force TTY mode") do
35
+ options[:tty] = true
36
+ end
37
+
38
+ opts.on("--no-tty", "Disable TTY mode") do
39
+ options[:tty] = false
36
40
  end
37
41
 
38
42
  opts.on("--edit", "Edit mode") do |edit|
data/lib/s3cp/s3cp.rb CHANGED
@@ -39,6 +39,7 @@ options[:include_regex] = []
39
39
  options[:exclude_regex] = []
40
40
  options[:sync] = false
41
41
  options[:move] = false
42
+ options[:mkdir] = nil
42
43
 
43
44
  op = OptionParser.new do |opts|
44
45
  opts.banner = <<-BANNER
@@ -79,6 +80,10 @@ op = OptionParser.new do |opts|
79
80
  options[:move] = true
80
81
  end
81
82
 
83
+ opts.on("--mkdir MATCH", "Recreate directory structure starting at `MATCH` from source path(s)") do |prefix|
84
+ options[:mkdir] = Regexp.new(prefix)
85
+ end
86
+
82
87
  opts.on("--max-attempts N", "Number of attempts to upload/download until checksum matches (default #{options[:retries]})") do |attempts|
83
88
  options[:retries] = attempts.to_i
84
89
  end
@@ -234,6 +239,12 @@ def relative(base, path)
234
239
  no_slash(path[dir.length..-1])
235
240
  end
236
241
 
242
+ def mkdir_relative(regex, key)
243
+ m = regex.match(key) or return
244
+ pos = m.captures.empty? ? m.begin(0) : m.begin(1)
245
+ suffix = key[pos..-1]
246
+ end
247
+
237
248
  def log(msg)
238
249
  puts msg if @verbose
239
250
  end
@@ -535,8 +546,13 @@ def copy(from, to, options)
535
546
  end
536
547
  keys.each do |key|
537
548
  if match(key)
538
- dest = File.expand_path(to) + '/' + relative(key_from, key)
539
- dest = File.join(dest, File.basename(key)) if File.directory?(dest)
549
+ dest = if options[:mkdir]
550
+ suffix = mkdir_relative(options[:mkdir], key) or next
551
+ dest = File.join(File.expand_path(to), suffix)
552
+ else
553
+ dest = File.expand_path(to) + '/' + relative(key_from, key)
554
+ dest = File.join(dest, File.basename(key)) if File.directory?(dest)
555
+ end
540
556
  dir = File.dirname(dest)
541
557
  FileUtils.mkdir_p dir unless File.exist? dir
542
558
  fail "Destination path is not a directory: #{dir}" unless File.directory?(dir)
@@ -548,8 +564,16 @@ def copy(from, to, options)
548
564
  end
549
565
  end
550
566
  else
551
- dest = File.expand_path(to)
552
- dest = File.join(dest, File.basename(key_from)) if File.directory?(dest)
567
+ dest = if options[:mkdir]
568
+ suffix = mkdir_relative(options[:mkdir], key_from) or
569
+ fail("Error: The key '#{key_from}' does not match the --mkdir regular expression '#{options[:mkdir]}'")
570
+ dest = File.join(File.expand_path(to), suffix)
571
+ dir = File.dirname(dest)
572
+ FileUtils.mkdir_p dir unless File.exist? dir
573
+ dest
574
+ else
575
+ File.join(File.expand_path(to), File.basename(key_from)) if File.directory?(dest)
576
+ end
553
577
  if !options[:overwrite] && File.exist?(dest)
554
578
  $stderr.puts "Skipping #{dest} - already exists."
555
579
  else
@@ -575,3 +599,4 @@ S3CP.standard_exception_handling(options) do
575
599
  copy(source, destination, options)
576
600
  end
577
601
  end
602
+
data/lib/s3cp/s3ls.rb CHANGED
@@ -17,10 +17,36 @@
17
17
 
18
18
  require 's3cp/utils'
19
19
 
20
+ require "rubygems"
21
+ require "highline/system_extensions"
22
+
23
+ def silence_streams(*streams)
24
+ on_hold = streams.collect { |stream| stream.dup }
25
+ streams.each do |stream|
26
+ stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
27
+ stream.sync = true
28
+ end
29
+ yield
30
+ ensure
31
+ streams.each_with_index do |stream, i|
32
+ stream.reopen(on_hold[i])
33
+ end
34
+ end
35
+
36
+ silence_streams(STDERR) do
37
+ p "size: " + HighLine::SystemExtensions.terminal_size.inspect
38
+ end
39
+
20
40
  # Parse arguments
21
41
  options = {}
22
42
  options[:date_format] = ENV['S3CP_DATE_FORMAT'] || '%x %X'
23
- options[:rows_per_page] = ($terminal.output_rows - 1) if $stdout.isatty rescue nil
43
+ #options[:rows_per_page] = ($terminal.output_rows - 1) if $stdout.isatty rescue nil
44
+ silence_streams(STDERR) do
45
+ if termsize = HighLine::SystemExtensions.terminal_size
46
+ options[:rows_per_page] = termsize[0]
47
+ end
48
+ end
49
+
24
50
  options[:precision] = 0
25
51
 
26
52
  op = OptionParser.new do |opts|
data/lib/s3cp/version.rb CHANGED
@@ -16,5 +16,5 @@
16
16
  # the License.
17
17
 
18
18
  module S3CP
19
- VERSION = "1.1.31"
19
+ VERSION = "1.1.32"
20
20
  end
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2010-2012 Alex Boisvert and Bizo Inc. / All rights reserved.
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one or more contributor
4
+ # license agreements. See the NOTICE file distributed with this work for
5
+ # additional information regarding copyright ownership. The ASF licenses this
6
+ # file to you under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module S3CP
19
+ VERSION = "1.1.31"
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: 45
4
+ hash: 83
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 31
10
- version: 1.1.31
9
+ - 32
10
+ version: 1.1.32
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-05-16 00:00:00 Z
18
+ date: 2013-08-26 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement
@@ -28,9 +28,9 @@ dependencies:
28
28
  - 0
29
29
  - 6
30
30
  version: "0.6"
31
- requirement: *id001
32
31
  type: :runtime
33
32
  prerelease: false
33
+ requirement: *id001
34
34
  name: extensions
35
35
  - !ruby/object:Gem::Dependency
36
36
  version_requirements: &id002 !ruby/object:Gem::Requirement
@@ -44,9 +44,9 @@ dependencies:
44
44
  - 5
45
45
  - 1
46
46
  version: 1.5.1
47
- requirement: *id002
48
47
  type: :runtime
49
48
  prerelease: false
49
+ requirement: *id002
50
50
  name: highline
51
51
  - !ruby/object:Gem::Dependency
52
52
  version_requirements: &id003 !ruby/object:Gem::Requirement
@@ -60,9 +60,9 @@ dependencies:
60
60
  - 8
61
61
  - 3
62
62
  version: 1.8.3
63
- requirement: *id003
64
63
  type: :runtime
65
64
  prerelease: false
65
+ requirement: *id003
66
66
  name: aws-sdk
67
67
  - !ruby/object:Gem::Dependency
68
68
  version_requirements: &id004 !ruby/object:Gem::Requirement
@@ -76,12 +76,28 @@ dependencies:
76
76
  - 10
77
77
  - 0
78
78
  version: 0.10.0
79
- requirement: *id004
80
79
  type: :runtime
81
80
  prerelease: false
81
+ requirement: *id004
82
82
  name: progressbar
83
83
  - !ruby/object:Gem::Dependency
84
84
  version_requirements: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ hash: 23
90
+ segments:
91
+ - 1
92
+ - 5
93
+ - 10
94
+ version: 1.5.10
95
+ type: :runtime
96
+ prerelease: false
97
+ requirement: *id005
98
+ name: nokogiri
99
+ - !ruby/object:Gem::Dependency
100
+ version_requirements: &id006 !ruby/object:Gem::Requirement
85
101
  none: false
86
102
  requirements:
87
103
  - - ~>
@@ -92,12 +108,12 @@ dependencies:
92
108
  - 5
93
109
  - 0
94
110
  version: 2.5.0
95
- requirement: *id005
96
111
  type: :development
97
112
  prerelease: false
113
+ requirement: *id006
98
114
  name: rspec
99
115
  - !ruby/object:Gem::Dependency
100
- version_requirements: &id006 !ruby/object:Gem::Requirement
116
+ version_requirements: &id007 !ruby/object:Gem::Requirement
101
117
  none: false
102
118
  requirements:
103
119
  - - ~>
@@ -108,9 +124,9 @@ dependencies:
108
124
  - 8
109
125
  - 7
110
126
  version: 0.8.7
111
- requirement: *id006
112
127
  type: :development
113
128
  prerelease: false
129
+ requirement: *id007
114
130
  name: rake
115
131
  description:
116
132
  email:
@@ -149,6 +165,7 @@ files:
149
165
  - lib/s3cp/version.rb
150
166
  - lib/s3cp/s3cp.rb
151
167
  - lib/s3cp/s3stat.rb
168
+ - lib/s3cp/version.rb~
152
169
  - lib/s3cp/utils.rb
153
170
  - lib/s3cp/s3lifecycle.rb
154
171
  - lib/s3cp/s3rm.rb