s3cp 1.1.22 → 1.1.23

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,22 @@
1
+ === 1.1.23 (2013-03-15)
2
+
3
+ * Added: s3cat now accepts --head, --tail and --range arguments.
4
+
5
+ # Display only first 8KB of file
6
+ % s3cat --head 8k bucket:path/to/file
7
+
8
+ # Display only last 4096 bytes of file
9
+ % s3cat --tail 4096 bucket:path/to/file
10
+
11
+ # Download file content between positions 4096 - 12288 (exclusive)
12
+ % s3cat --range 4k-12k bucket:path/to/file > file_fragment
13
+
14
+ # Download content after position 12288 (inclusive)
15
+ % s3cat --range 12k- bucket:path/to/file > file_fragment
16
+
17
+ # Download content before position 12288 (exclusive)
18
+ % s3cat --range -12k bucket:path/to/file > file_fragment
19
+
1
20
  === 1.1.22 (2013-03-07)
2
21
 
3
22
  * Changed: s3cp now adds a new "md5" custom metadata to any uploaded file
data/bin/tmp ADDED
File without changes
data/lib/s3cp/s3cat.rb CHANGED
@@ -39,6 +39,21 @@ op = OptionParser.new do |opts|
39
39
  options[:edit] = edit
40
40
  end
41
41
 
42
+ opts.on("--head SIZE", "Download only 'head' part of the file mode, e.g. 4KB, 1024B, 2GB") do |size|
43
+ options[:head] = S3CP.size_in_bytes(size)
44
+ end
45
+
46
+ opts.on("--tail SIZE", "Download only 'tail' part of the file mode, e.g. 4KB, 1024B, 2GB") do |size|
47
+ options[:tail] = S3CP.size_in_bytes(size)
48
+ end
49
+
50
+ opts.on("--range START-END", "Download only range (in absolute positions) portion, e.g. 1GB-2GB, 16K-128k, 128k-, -128k") do |range|
51
+ range_start, range_end = range.split("-")
52
+ options[:range_start] = S3CP.size_in_bytes(range_start) if range_start && (!range_start.empty?)
53
+ options[:range_end] = S3CP.size_in_bytes(range_end) - 1 if range_end && (!range_end.empty?)
54
+ range_start, range_end = range.split("-")
55
+ end
56
+
42
57
  opts.on_tail("-h", "--help", "Show this message") do
43
58
  puts op
44
59
  exit
@@ -63,8 +78,20 @@ fail "Your URL looks funny, doesn't it?" unless @bucket
63
78
 
64
79
  S3CP.load_config()
65
80
 
81
+ read_options = {}
82
+ read_options[:debug] = options[:debug]
83
+ read_options[:head] = options[:head] if options[:head]
84
+ read_options[:tail] = options[:tail] if options[:tail]
85
+ read_options[:range_start] = options[:range_start] if options[:range_start]
86
+ read_options[:range_end] = options[:range_end] if options[:range_end]
87
+
66
88
  @s3 = S3CP.connect().buckets[@bucket]
67
89
 
90
+
91
+ if options[:edit] && (options[:head] || options[:tail] || options[:range_start] || options[:range_end])
92
+ fail "--edit option is not intended to be used with --head, --tail nor --range"
93
+ end
94
+
68
95
  if options[:tty] || options[:edit]
69
96
  # store contents to file to display with PAGER
70
97
  size = @s3.objects[@prefix].content_length
@@ -76,7 +103,7 @@ if options[:tty] || options[:edit]
76
103
  file = Tempfile.new(File.basename(@prefix) + '_')
77
104
  out = File.new(file.path, "wb")
78
105
  begin
79
- @s3.objects[@prefix].read_as_stream do |chunk|
106
+ @s3.objects[@prefix].read_as_stream(read_options) do |chunk|
80
107
  out.write(chunk)
81
108
  progress_bar.inc chunk.size
82
109
  end
@@ -104,7 +131,7 @@ if options[:tty] || options[:edit]
104
131
  end
105
132
  file.delete()
106
133
  else
107
- @s3.objects[@prefix].read_as_stream do |chunk|
134
+ @s3.objects[@prefix].read_as_stream(read_options) do |chunk|
108
135
  begin
109
136
  STDOUT.print(chunk)
110
137
  rescue Errno::EPIPE
data/lib/s3cp/utils.rb CHANGED
@@ -165,6 +165,23 @@ module S3CP
165
165
  end
166
166
  end
167
167
 
168
+ def size_in_bytes(size)
169
+ case size
170
+ when /^(\d+)$/ # bytes by default
171
+ $1.to_i
172
+ when /^(\d+)b$/i
173
+ $1.to_i
174
+ when /^(\d+)kb?$/i
175
+ $1.to_i * 1024
176
+ when /^(\d+)mb?$/i
177
+ $1.to_i * 1024 * 1024
178
+ when /^(\d+)gb?$/i
179
+ $1.to_i * 1024 * 1024 * 1024
180
+ else
181
+ fail("Invalid size value: #{size}.")
182
+ end
183
+ end
184
+
168
185
  def set_header_options(options, headers)
169
186
  return options unless headers
170
187
 
@@ -245,11 +262,19 @@ module AWS
245
262
  class S3Object
246
263
  def read_as_stream(options = nil, &blk)
247
264
  options ||= {}
248
- chunk_size = options[:chunk] || DEFAULT_STREAMING_CHUNK_SIZE
249
265
  size = content_length
250
- byte_offset = 0
251
- while byte_offset < size
252
- range = "bytes=#{byte_offset}-#{byte_offset + chunk_size - 1}"
266
+ chunk_size = options[:chunk] || DEFAULT_STREAMING_CHUNK_SIZE
267
+ if options[:range_start] || options[:range_end]
268
+ byte_offset = options[:range_start] || 0
269
+ max_offset = options[:range_end] || size
270
+ else
271
+ byte_offset = options[:tail] ? (size - options[:tail]) : 0
272
+ max_offset = options[:head] ? (options[:head] - 1) : size
273
+ end
274
+ $stderr.print "Downloading byte range #{byte_offset}-#{max_offset}\n" if options[:debug]
275
+ while byte_offset < max_offset
276
+ range = "bytes=#{byte_offset}-#{[byte_offset + chunk_size - 1, max_offset].min}"
277
+ $stderr.print range + "\n" if options[:debug]
253
278
  yield read(:range => range)
254
279
  byte_offset += chunk_size
255
280
  end
data/lib/s3cp/version.rb CHANGED
@@ -16,5 +16,5 @@
16
16
  # the License.
17
17
 
18
18
  module S3CP
19
- VERSION = "1.1.22"
19
+ VERSION = "1.1.23"
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: 63
4
+ hash: 61
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 22
10
- version: 1.1.22
9
+ - 23
10
+ version: 1.1.23
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-03-08 00:00:00 Z
18
+ date: 2013-03-15 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement
@@ -171,6 +171,7 @@ files:
171
171
  - bin/s3lifecycle
172
172
  - bin/s3rm
173
173
  - bin/s3stat
174
+ - bin/tmp
174
175
  homepage:
175
176
  licenses: []
176
177