s3cp 1.1.8 → 1.1.9
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/History.txt +5 -0
- data/bin/s3tree +4 -0
- data/lib/s3cp/s3cp.rb +10 -3
- data/lib/s3cp/s3tree.rb +162 -0
- data/lib/s3cp/version.rb +1 -1
- metadata +7 -4
data/History.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
=== 1.1.9 (2012-11-27)
|
2
|
+
|
3
|
+
* Added: New `s3tree` command similar to Unix `tree` command.
|
4
|
+
* Changed: Correctly display 'Move' text instead of 'Copy' when moving files.
|
5
|
+
|
1
6
|
=== 1.1.8 (2012-10-29)
|
2
7
|
|
3
8
|
* Changed: Relaxed highline dependency requirement from ~> 1.5.1 to >= 1.5.1
|
data/bin/s3tree
ADDED
data/lib/s3cp/s3cp.rb
CHANGED
@@ -250,8 +250,15 @@ def md5(filename)
|
|
250
250
|
digest.hexdigest
|
251
251
|
end
|
252
252
|
|
253
|
+
def operation(options)
|
254
|
+
operation = "Copy"
|
255
|
+
operation = "Move" if options[:move]
|
256
|
+
operation = "Sync" if options[:sync]
|
257
|
+
operation
|
258
|
+
end
|
259
|
+
|
253
260
|
def s3_to_s3(bucket_from, key, bucket_to, dest, options = {})
|
254
|
-
log(with_headers("
|
261
|
+
log(with_headers("#{operation(options)} s3://#{bucket_from}/#{key} to s3://#{bucket_to}/#{dest}"))
|
255
262
|
s3_source = @s3.buckets[bucket_from].objects[key]
|
256
263
|
s3_dest = @s3.buckets[bucket_to].objects[dest]
|
257
264
|
s3_options = {}
|
@@ -265,7 +272,7 @@ def s3_to_s3(bucket_from, key, bucket_to, dest, options = {})
|
|
265
272
|
end
|
266
273
|
|
267
274
|
def local_to_s3(bucket_to, key, file, options = {})
|
268
|
-
log(with_headers("
|
275
|
+
log(with_headers("#{operation(options)} #{file} to s3://#{bucket_to}/#{key}"))
|
269
276
|
|
270
277
|
expected_md5 = if options[:checksum] || options[:sync]
|
271
278
|
md5(file)
|
@@ -342,7 +349,7 @@ def local_to_s3(bucket_to, key, file, options = {})
|
|
342
349
|
end
|
343
350
|
|
344
351
|
def s3_to_local(bucket_from, key_from, dest, options = {})
|
345
|
-
log("
|
352
|
+
log("#{operation(options)} s3://#{bucket_from}/#{key_from} to #{dest}")
|
346
353
|
|
347
354
|
retries = 0
|
348
355
|
begin
|
data/lib/s3cp/s3tree.rb
ADDED
@@ -0,0 +1,162 @@
|
|
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
|
+
require 's3cp/utils'
|
19
|
+
|
20
|
+
# Parse arguments
|
21
|
+
options = {}
|
22
|
+
options[:rows_per_page] = ($terminal.output_rows - 1) if $stdout.isatty
|
23
|
+
options[:delimiter] = ENV["S3CP_DELIMITER"] || "/"
|
24
|
+
options[:max_depth] = 9999999
|
25
|
+
|
26
|
+
op = OptionParser.new do |opts|
|
27
|
+
opts.banner = "s3tree [path]"
|
28
|
+
opts.separator ''
|
29
|
+
|
30
|
+
opts.on("-d", "Show directories only") do
|
31
|
+
options[:directories_only] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("--rows ROWS", "Rows per page") do |rows|
|
35
|
+
options[:rows_per_page] = rows.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("--max-keys KEYS", "Maximum number of keys to display") do |keys|
|
39
|
+
options[:max_keys] = keys.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("--max-depth DEPTH", "Maximum directory depth to display") do |depth|
|
43
|
+
options[:max_depth] = depth.to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("--delimiter CHAR", "Display keys starting with given path prefix and up to delimiter character") do |delimiter|
|
47
|
+
options[:delimiter] = delimiter
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
51
|
+
puts op
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
op.parse!(ARGV)
|
56
|
+
|
57
|
+
unless ARGV.size > 0
|
58
|
+
puts op
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
|
62
|
+
url = ARGV[0]
|
63
|
+
|
64
|
+
@bucket, @key = S3CP.bucket_and_key(url)
|
65
|
+
fail "Your URL looks funny, doesn't it?" unless @bucket
|
66
|
+
|
67
|
+
S3CP.load_config()
|
68
|
+
|
69
|
+
@s3 = S3CP.connect().buckets[@bucket]
|
70
|
+
|
71
|
+
keys = 0
|
72
|
+
rows = 0
|
73
|
+
|
74
|
+
begin
|
75
|
+
# find last index of character `ch` in `str`.
|
76
|
+
last_index_of = lambda do |str, ch|
|
77
|
+
case
|
78
|
+
when str[ch] then str.length-(str.reverse.index(ch)+1)
|
79
|
+
else -1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# displays the next line, returns true if user interrupts or max keys shown
|
84
|
+
display_line = lambda do |line|
|
85
|
+
puts line
|
86
|
+
keys += 1
|
87
|
+
if options[:max_keys] && keys > options[:max_keys]
|
88
|
+
return true
|
89
|
+
end
|
90
|
+
rows += 1
|
91
|
+
response = ''
|
92
|
+
if options[:rows_per_page] && (rows % options[:rows_per_page] == 0)
|
93
|
+
begin
|
94
|
+
print "Continue? (Y/n) "
|
95
|
+
response = STDIN.gets.chomp.downcase
|
96
|
+
end until response == 'n' || response == 'y' || response == ''
|
97
|
+
end
|
98
|
+
(response == 'n')
|
99
|
+
end
|
100
|
+
|
101
|
+
# returns relative path against @key
|
102
|
+
#
|
103
|
+
# e.g. relative.call("foo/bar") => "bar" (assuming @key = "foo/")
|
104
|
+
#
|
105
|
+
relative = lambda do |key|
|
106
|
+
last_delimiter = last_index_of.call(@key, options[:delimiter])
|
107
|
+
(last_delimiter != -1) ? key[last_delimiter..-1] : key
|
108
|
+
end
|
109
|
+
|
110
|
+
# trim up to the last delimiter
|
111
|
+
#
|
112
|
+
# e.g. trim.call("foo/bar") => "foo/"
|
113
|
+
#
|
114
|
+
trim = lambda do |key|
|
115
|
+
last_delimiter = last_index_of.call(key, options[:delimiter])
|
116
|
+
(last_delimiter != -1) ? key[0..last_delimiter] : ""
|
117
|
+
end
|
118
|
+
|
119
|
+
# recursively display tree elements
|
120
|
+
#
|
121
|
+
# +prefix+: line prefix
|
122
|
+
# +children+: children of the current directory
|
123
|
+
# +depth+: current directory depth
|
124
|
+
display_tree = lambda do |prefix, children, depth|
|
125
|
+
stop = false
|
126
|
+
children = children.to_a # aws-sdk returns a sucky ChildCollection object
|
127
|
+
children.each_with_index do |node, index|
|
128
|
+
node = node
|
129
|
+
if options[:directories_only] && node.leaf?
|
130
|
+
next
|
131
|
+
end
|
132
|
+
|
133
|
+
last = (index == children.size - 1)
|
134
|
+
has_siblings = (children.size > 1)
|
135
|
+
key = node.branch? ? node.prefix : node.key
|
136
|
+
parts = relative.call(key).split(options[:delimiter])
|
137
|
+
postfix = last ? '└── ' : '├── '
|
138
|
+
|
139
|
+
stop = display_line.call(prefix + postfix + parts.last)
|
140
|
+
break if stop
|
141
|
+
|
142
|
+
if node.branch? && depth < options[:max_depth]
|
143
|
+
new_prefix = prefix + (has_siblings ? "│ " : " ")
|
144
|
+
stop = display_tree.call(new_prefix, node.children, depth + 1)
|
145
|
+
break if stop
|
146
|
+
end
|
147
|
+
|
148
|
+
break if stop
|
149
|
+
end
|
150
|
+
stop
|
151
|
+
end
|
152
|
+
|
153
|
+
display_line.call("s3://#{@bucket}/#{trim.call(@key)}")
|
154
|
+
|
155
|
+
prefix = ""
|
156
|
+
root = @s3.objects.with_prefix(@key).as_tree( :delimier => options[:delimiter], :append => false)
|
157
|
+
depth = 1
|
158
|
+
display_tree.call(prefix, root.children, depth)
|
159
|
+
rescue Errno::EPIPE
|
160
|
+
# ignore
|
161
|
+
end
|
162
|
+
|
data/lib/s3cp/version.rb
CHANGED
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:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
9
|
+
- 9
|
10
|
+
version: 1.1.9
|
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: 2012-
|
18
|
+
date: 2012-11-27 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
prerelease: false
|
@@ -127,6 +127,7 @@ executables:
|
|
127
127
|
- s3mv
|
128
128
|
- s3rm
|
129
129
|
- s3stat
|
130
|
+
- s3tree
|
130
131
|
- s3up
|
131
132
|
extensions: []
|
132
133
|
|
@@ -140,6 +141,7 @@ files:
|
|
140
141
|
- lib/s3cp/s3du.rb
|
141
142
|
- lib/s3cp/s3mod.rb
|
142
143
|
- lib/s3cp/utils.rb
|
144
|
+
- lib/s3cp/s3tree.rb
|
143
145
|
- lib/s3cp/s3cp.rb
|
144
146
|
- lib/s3cp/s3cat.rb
|
145
147
|
- lib/s3cp/s3buckets.rb
|
@@ -160,6 +162,7 @@ files:
|
|
160
162
|
- bin/s3cp
|
161
163
|
- bin/s3ls
|
162
164
|
- bin/s3stat
|
165
|
+
- bin/s3tree
|
163
166
|
homepage:
|
164
167
|
licenses: []
|
165
168
|
|