s3_cmd_bin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +28 -0
  5. data/Rakefile +1 -0
  6. data/lib/s3_cmd_bin/version.rb +3 -0
  7. data/lib/s3_cmd_bin.rb +15 -0
  8. data/resources/ChangeLog +1462 -0
  9. data/resources/INSTALL +97 -0
  10. data/resources/LICENSE +339 -0
  11. data/resources/MANIFEST.in +2 -0
  12. data/resources/Makefile +4 -0
  13. data/resources/NEWS +234 -0
  14. data/resources/README +342 -0
  15. data/resources/S3/ACL.py +224 -0
  16. data/resources/S3/ACL.pyc +0 -0
  17. data/resources/S3/AccessLog.py +92 -0
  18. data/resources/S3/AccessLog.pyc +0 -0
  19. data/resources/S3/BidirMap.py +42 -0
  20. data/resources/S3/BidirMap.pyc +0 -0
  21. data/resources/S3/CloudFront.py +773 -0
  22. data/resources/S3/CloudFront.pyc +0 -0
  23. data/resources/S3/Config.py +294 -0
  24. data/resources/S3/Config.pyc +0 -0
  25. data/resources/S3/ConnMan.py +71 -0
  26. data/resources/S3/ConnMan.pyc +0 -0
  27. data/resources/S3/Exceptions.py +88 -0
  28. data/resources/S3/Exceptions.pyc +0 -0
  29. data/resources/S3/FileDict.py +53 -0
  30. data/resources/S3/FileDict.pyc +0 -0
  31. data/resources/S3/FileLists.py +517 -0
  32. data/resources/S3/FileLists.pyc +0 -0
  33. data/resources/S3/HashCache.py +53 -0
  34. data/resources/S3/HashCache.pyc +0 -0
  35. data/resources/S3/MultiPart.py +137 -0
  36. data/resources/S3/MultiPart.pyc +0 -0
  37. data/resources/S3/PkgInfo.py +14 -0
  38. data/resources/S3/PkgInfo.pyc +0 -0
  39. data/resources/S3/Progress.py +173 -0
  40. data/resources/S3/Progress.pyc +0 -0
  41. data/resources/S3/S3.py +979 -0
  42. data/resources/S3/S3.pyc +0 -0
  43. data/resources/S3/S3Uri.py +223 -0
  44. data/resources/S3/S3Uri.pyc +0 -0
  45. data/resources/S3/SimpleDB.py +178 -0
  46. data/resources/S3/SortedDict.py +66 -0
  47. data/resources/S3/SortedDict.pyc +0 -0
  48. data/resources/S3/Utils.py +462 -0
  49. data/resources/S3/Utils.pyc +0 -0
  50. data/resources/S3/__init__.py +0 -0
  51. data/resources/S3/__init__.pyc +0 -0
  52. data/resources/TODO +52 -0
  53. data/resources/artwork/AtomicClockRadio.ttf +0 -0
  54. data/resources/artwork/TypeRa.ttf +0 -0
  55. data/resources/artwork/site-top-full-size.xcf +0 -0
  56. data/resources/artwork/site-top-label-download.png +0 -0
  57. data/resources/artwork/site-top-label-s3cmd.png +0 -0
  58. data/resources/artwork/site-top-label-s3sync.png +0 -0
  59. data/resources/artwork/site-top-s3tools-logo.png +0 -0
  60. data/resources/artwork/site-top.jpg +0 -0
  61. data/resources/artwork/site-top.png +0 -0
  62. data/resources/artwork/site-top.xcf +0 -0
  63. data/resources/format-manpage.pl +196 -0
  64. data/resources/magic +63 -0
  65. data/resources/run-tests.py +537 -0
  66. data/resources/s3cmd +2116 -0
  67. data/resources/s3cmd.1 +435 -0
  68. data/resources/s3db +55 -0
  69. data/resources/setup.cfg +2 -0
  70. data/resources/setup.py +80 -0
  71. data/resources/testsuite.tar.gz +0 -0
  72. data/resources/upload-to-sf.sh +7 -0
  73. data/s3_cmd_bin.gemspec +23 -0
  74. metadata +152 -0
@@ -0,0 +1,537 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding=utf-8 -*-
3
+
4
+ ## Amazon S3cmd - testsuite
5
+ ## Author: Michal Ludvig <michal@logix.cz>
6
+ ## http://www.logix.cz/michal
7
+ ## License: GPL Version 2
8
+
9
+ import sys
10
+ import os
11
+ import re
12
+ from subprocess import Popen, PIPE, STDOUT
13
+ import locale
14
+ import pwd
15
+
16
+ count_pass = 0
17
+ count_fail = 0
18
+ count_skip = 0
19
+
20
+ test_counter = 0
21
+ run_tests = []
22
+ exclude_tests = []
23
+
24
+ verbose = False
25
+
26
+ if os.name == "posix":
27
+ have_wget = True
28
+ elif os.name == "nt":
29
+ have_wget = False
30
+ else:
31
+ print "Unknown platform: %s" % os.name
32
+ sys.exit(1)
33
+
34
+ ## Unpack testsuite/ directory
35
+ if not os.path.isdir('testsuite') and os.path.isfile('testsuite.tar.gz'):
36
+ os.system("tar -xz -f testsuite.tar.gz")
37
+ if not os.path.isdir('testsuite'):
38
+ print "Something went wrong while unpacking testsuite.tar.gz"
39
+ sys.exit(1)
40
+
41
+ os.system("tar -xf testsuite/checksum.tar -C testsuite")
42
+ if not os.path.isfile('testsuite/checksum/cksum33.txt'):
43
+ print "Something went wrong while unpacking testsuite/checkum.tar"
44
+ sys.exit(1)
45
+
46
+ ## Fix up permissions for permission-denied tests
47
+ os.chmod("testsuite/permission-tests/permission-denied-dir", 0444)
48
+ os.chmod("testsuite/permission-tests/permission-denied.txt", 0000)
49
+
50
+ ## Patterns for Unicode tests
51
+ patterns = {}
52
+ patterns['UTF-8'] = u"ŪņЇЌœđЗ/☺ unicode € rocks ™"
53
+ patterns['GBK'] = u"12月31日/1-特色條目"
54
+
55
+ encoding = locale.getpreferredencoding()
56
+ if not encoding:
57
+ print "Guessing current system encoding failed. Consider setting $LANG variable."
58
+ sys.exit(1)
59
+ else:
60
+ print "System encoding: " + encoding
61
+
62
+ have_encoding = os.path.isdir('testsuite/encodings/' + encoding)
63
+ if not have_encoding and os.path.isfile('testsuite/encodings/%s.tar.gz' % encoding):
64
+ os.system("tar xvz -C testsuite/encodings -f testsuite/encodings/%s.tar.gz" % encoding)
65
+ have_encoding = os.path.isdir('testsuite/encodings/' + encoding)
66
+
67
+ if have_encoding:
68
+ #enc_base_remote = "%s/xyz/%s/" % (pbucket(1), encoding)
69
+ enc_pattern = patterns[encoding]
70
+ else:
71
+ print encoding + " specific files not found."
72
+
73
+ if not os.path.isdir('testsuite/crappy-file-name'):
74
+ os.system("tar xvz -C testsuite -f testsuite/crappy-file-name.tar.gz")
75
+ # TODO: also unpack if the tarball is newer than the directory timestamp
76
+ # for instance when a new version was pulled from SVN.
77
+
78
+ def test(label, cmd_args = [], retcode = 0, must_find = [], must_not_find = [], must_find_re = [], must_not_find_re = []):
79
+ def command_output():
80
+ print "----"
81
+ print " ".join([arg.find(" ")>=0 and "'%s'" % arg or arg for arg in cmd_args])
82
+ print "----"
83
+ print stdout
84
+ print "----"
85
+
86
+ def failure(message = ""):
87
+ global count_fail
88
+ if message:
89
+ message = " (%r)" % message
90
+ print "\x1b[31;1mFAIL%s\x1b[0m" % (message)
91
+ count_fail += 1
92
+ command_output()
93
+ #return 1
94
+ sys.exit(1)
95
+ def success(message = ""):
96
+ global count_pass
97
+ if message:
98
+ message = " (%r)" % message
99
+ print "\x1b[32;1mOK\x1b[0m%s" % (message)
100
+ count_pass += 1
101
+ if verbose:
102
+ command_output()
103
+ return 0
104
+ def skip(message = ""):
105
+ global count_skip
106
+ if message:
107
+ message = " (%r)" % message
108
+ print "\x1b[33;1mSKIP\x1b[0m%s" % (message)
109
+ count_skip += 1
110
+ return 0
111
+ def compile_list(_list, regexps = False):
112
+ if regexps == False:
113
+ _list = [re.escape(item.encode(encoding, "replace")) for item in _list]
114
+
115
+ return [re.compile(item, re.MULTILINE) for item in _list]
116
+
117
+ global test_counter
118
+ test_counter += 1
119
+ print ("%3d %s " % (test_counter, label)).ljust(30, "."),
120
+ sys.stdout.flush()
121
+
122
+ if run_tests.count(test_counter) == 0 or exclude_tests.count(test_counter) > 0:
123
+ return skip()
124
+
125
+ if not cmd_args:
126
+ return skip()
127
+
128
+ p = Popen(cmd_args, stdout = PIPE, stderr = STDOUT, universal_newlines = True)
129
+ stdout, stderr = p.communicate()
130
+ if retcode != p.returncode:
131
+ return failure("retcode: %d, expected: %d" % (p.returncode, retcode))
132
+
133
+ if type(must_find) not in [ list, tuple ]: must_find = [must_find]
134
+ if type(must_find_re) not in [ list, tuple ]: must_find_re = [must_find_re]
135
+ if type(must_not_find) not in [ list, tuple ]: must_not_find = [must_not_find]
136
+ if type(must_not_find_re) not in [ list, tuple ]: must_not_find_re = [must_not_find_re]
137
+
138
+ find_list = []
139
+ find_list.extend(compile_list(must_find))
140
+ find_list.extend(compile_list(must_find_re, regexps = True))
141
+ find_list_patterns = []
142
+ find_list_patterns.extend(must_find)
143
+ find_list_patterns.extend(must_find_re)
144
+
145
+ not_find_list = []
146
+ not_find_list.extend(compile_list(must_not_find))
147
+ not_find_list.extend(compile_list(must_not_find_re, regexps = True))
148
+ not_find_list_patterns = []
149
+ not_find_list_patterns.extend(must_not_find)
150
+ not_find_list_patterns.extend(must_not_find_re)
151
+
152
+ for index in range(len(find_list)):
153
+ match = find_list[index].search(stdout)
154
+ if not match:
155
+ return failure("pattern not found: %s" % find_list_patterns[index])
156
+ for index in range(len(not_find_list)):
157
+ match = not_find_list[index].search(stdout)
158
+ if match:
159
+ return failure("pattern found: %s (match: %s)" % (not_find_list_patterns[index], match.group(0)))
160
+
161
+ return success()
162
+
163
+ def test_s3cmd(label, cmd_args = [], **kwargs):
164
+ if not cmd_args[0].endswith("s3cmd"):
165
+ cmd_args.insert(0, "python")
166
+ cmd_args.insert(1, "s3cmd")
167
+
168
+ return test(label, cmd_args, **kwargs)
169
+
170
+ def test_mkdir(label, dir_name):
171
+ if os.name in ("posix", "nt"):
172
+ cmd = ['mkdir', '-p']
173
+ else:
174
+ print "Unknown platform: %s" % os.name
175
+ sys.exit(1)
176
+ cmd.append(dir_name)
177
+ return test(label, cmd)
178
+
179
+ def test_rmdir(label, dir_name):
180
+ if os.path.isdir(dir_name):
181
+ if os.name == "posix":
182
+ cmd = ['rm', '-rf']
183
+ elif os.name == "nt":
184
+ cmd = ['rmdir', '/s/q']
185
+ else:
186
+ print "Unknown platform: %s" % os.name
187
+ sys.exit(1)
188
+ cmd.append(dir_name)
189
+ return test(label, cmd)
190
+ else:
191
+ return test(label, [])
192
+
193
+ def test_flushdir(label, dir_name):
194
+ test_rmdir(label + "(rm)", dir_name)
195
+ return test_mkdir(label + "(mk)", dir_name)
196
+
197
+ def test_copy(label, src_file, dst_file):
198
+ if os.name == "posix":
199
+ cmd = ['cp', '-f']
200
+ elif os.name == "nt":
201
+ cmd = ['copy']
202
+ else:
203
+ print "Unknown platform: %s" % os.name
204
+ sys.exit(1)
205
+ cmd.append(src_file)
206
+ cmd.append(dst_file)
207
+ return test(label, cmd)
208
+
209
+ try:
210
+ pwd = pwd.getpwuid(os.getuid())
211
+ bucket_prefix = "%s.%s-" % (pwd.pw_name, pwd.pw_uid)
212
+ except:
213
+ bucket_prefix = ''
214
+ print "Using bucket prefix: '%s'" % bucket_prefix
215
+
216
+ argv = sys.argv[1:]
217
+ while argv:
218
+ arg = argv.pop(0)
219
+ if arg.startswith('--bucket-prefix='):
220
+ print "Usage: '--bucket-prefix PREFIX', not '--bucket-prefix=PREFIX'"
221
+ sys.exit(0)
222
+ if arg in ("-h", "--help"):
223
+ print "%s A B K..O -N" % sys.argv[0]
224
+ print "Run tests number A, B and K through to O, except for N"
225
+ sys.exit(0)
226
+ if arg in ("-l", "--list"):
227
+ exclude_tests = range(0, 999)
228
+ break
229
+ if arg in ("-v", "--verbose"):
230
+ verbose = True
231
+ continue
232
+ if arg in ("-p", "--bucket-prefix"):
233
+ try:
234
+ bucket_prefix = argv.pop(0)
235
+ except IndexError:
236
+ print "Bucket prefix option must explicitly supply a bucket name prefix"
237
+ sys.exit(0)
238
+ continue
239
+ if arg.find("..") >= 0:
240
+ range_idx = arg.find("..")
241
+ range_start = arg[:range_idx] or 0
242
+ range_end = arg[range_idx+2:] or 999
243
+ run_tests.extend(range(int(range_start), int(range_end) + 1))
244
+ elif arg.startswith("-"):
245
+ exclude_tests.append(int(arg[1:]))
246
+ else:
247
+ run_tests.append(int(arg))
248
+
249
+ if not run_tests:
250
+ run_tests = range(0, 999)
251
+
252
+ # helper functions for generating bucket names
253
+ def bucket(tail):
254
+ '''Test bucket name'''
255
+ label = 'autotest'
256
+ if str(tail) == '3':
257
+ label = 'Autotest'
258
+ return '%ss3cmd-%s-%s' % (bucket_prefix, label, tail)
259
+
260
+ def pbucket(tail):
261
+ '''Like bucket(), but prepends "s3://" for you'''
262
+ return 's3://' + bucket(tail)
263
+
264
+ ## ====== Remove test buckets
265
+ test_s3cmd("Remove test buckets", ['rb', '-r', pbucket(1), pbucket(2), pbucket(3)],
266
+ must_find = [ "Bucket '%s/' removed" % pbucket(1),
267
+ "Bucket '%s/' removed" % pbucket(2),
268
+ "Bucket '%s/' removed" % pbucket(3) ])
269
+
270
+
271
+ ## ====== Create one bucket (EU)
272
+ test_s3cmd("Create one bucket (EU)", ['mb', '--bucket-location=EU', pbucket(1)],
273
+ must_find = "Bucket '%s/' created" % pbucket(1))
274
+
275
+
276
+
277
+ ## ====== Create multiple buckets
278
+ test_s3cmd("Create multiple buckets", ['mb', pbucket(2), pbucket(3)],
279
+ must_find = [ "Bucket '%s/' created" % pbucket(2), "Bucket '%s/' created" % pbucket(3)])
280
+
281
+
282
+ ## ====== Invalid bucket name
283
+ test_s3cmd("Invalid bucket name", ["mb", "--bucket-location=EU", pbucket('EU')],
284
+ retcode = 1,
285
+ must_find = "ERROR: Parameter problem: Bucket name '%s' contains disallowed character" % bucket('EU'),
286
+ must_not_find_re = "Bucket.*created")
287
+
288
+
289
+ ## ====== Buckets list
290
+ test_s3cmd("Buckets list", ["ls"],
291
+ must_find = [ "autotest-1", "autotest-2", "Autotest-3" ], must_not_find_re = "autotest-EU")
292
+
293
+
294
+ ## ====== Sync to S3
295
+ test_s3cmd("Sync to S3", ['sync', 'testsuite/', pbucket(1) + '/xyz/', '--exclude', 'demo/*', '--exclude', '*.png', '--no-encrypt', '--exclude-from', 'testsuite/exclude.encodings' ],
296
+ must_find = [ "WARNING: 32 non-printable characters replaced in: crappy-file-name/non-printables ^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_^? +-[\]^<>%%\"'#{}`&?.end",
297
+ "WARNING: File can not be uploaded: testsuite/permission-tests/permission-denied.txt: Permission denied",
298
+ "stored as '%s/xyz/crappy-file-name/non-printables ^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_^? +-[\\]^<>%%%%\"'#{}`&?.end'" % pbucket(1) ],
299
+ must_not_find_re = [ "demo/", "\.png$", "permission-denied-dir" ])
300
+
301
+ if have_encoding:
302
+ ## ====== Sync UTF-8 / GBK / ... to S3
303
+ test_s3cmd("Sync %s to S3" % encoding, ['sync', 'testsuite/encodings/' + encoding, '%s/xyz/encodings/' % pbucket(1), '--exclude', 'demo/*', '--no-encrypt' ],
304
+ must_find = [ u"File 'testsuite/encodings/%(encoding)s/%(pattern)s' stored as '%(pbucket)s/xyz/encodings/%(encoding)s/%(pattern)s'" % { 'encoding' : encoding, 'pattern' : enc_pattern , 'pbucket' : pbucket(1)} ])
305
+
306
+
307
+ ## ====== List bucket content
308
+ test_s3cmd("List bucket content", ['ls', '%s/xyz/' % pbucket(1) ],
309
+ must_find_re = [ u"DIR %s/xyz/binary/$" % pbucket(1) , u"DIR %s/xyz/etc/$" % pbucket(1) ],
310
+ must_not_find = [ u"random-crap.md5", u"/demo" ])
311
+
312
+
313
+ ## ====== List bucket recursive
314
+ must_find = [ u"%s/xyz/binary/random-crap.md5" % pbucket(1) ]
315
+ if have_encoding:
316
+ must_find.append(u"%(pbucket)s/xyz/encodings/%(encoding)s/%(pattern)s" % { 'encoding' : encoding, 'pattern' : enc_pattern, 'pbucket' : pbucket(1) })
317
+
318
+ test_s3cmd("List bucket recursive", ['ls', '--recursive', pbucket(1)],
319
+ must_find = must_find,
320
+ must_not_find = [ "logo.png" ])
321
+
322
+ ## ====== FIXME
323
+ # test_s3cmd("Recursive put", ['put', '--recursive', 'testsuite/etc', '%s/xyz/' % pbucket(1) ])
324
+
325
+
326
+ ## ====== Clean up local destination dir
327
+ test_flushdir("Clean testsuite-out/", "testsuite-out")
328
+
329
+
330
+ ## ====== Sync from S3
331
+ must_find = [ "File '%s/xyz/binary/random-crap.md5' stored as 'testsuite-out/xyz/binary/random-crap.md5'" % pbucket(1) ]
332
+ if have_encoding:
333
+ must_find.append(u"File '%(pbucket)s/xyz/encodings/%(encoding)s/%(pattern)s' stored as 'testsuite-out/xyz/encodings/%(encoding)s/%(pattern)s' " % { 'encoding' : encoding, 'pattern' : enc_pattern, 'pbucket' : pbucket(1) })
334
+ test_s3cmd("Sync from S3", ['sync', '%s/xyz' % pbucket(1), 'testsuite-out'],
335
+ must_find = must_find)
336
+
337
+
338
+ ## ====== Remove 'demo' directory
339
+ test_rmdir("Remove 'dir-test/'", "testsuite-out/xyz/dir-test/")
340
+
341
+
342
+ ## ====== Create dir with name of a file
343
+ test_mkdir("Create file-dir dir", "testsuite-out/xyz/dir-test/file-dir")
344
+
345
+
346
+ ## ====== Skip dst dirs
347
+ test_s3cmd("Skip over dir", ['sync', '%s/xyz' % pbucket(1), 'testsuite-out'],
348
+ must_find = "WARNING: testsuite-out/xyz/dir-test/file-dir is a directory - skipping over")
349
+
350
+
351
+ ## ====== Clean up local destination dir
352
+ test_flushdir("Clean testsuite-out/", "testsuite-out")
353
+
354
+
355
+ ## ====== Put public, guess MIME
356
+ test_s3cmd("Put public, guess MIME", ['put', '--guess-mime-type', '--acl-public', 'testsuite/etc/logo.png', '%s/xyz/etc/logo.png' % pbucket(1)],
357
+ must_find = [ "stored as '%s/xyz/etc/logo.png'" % pbucket(1) ])
358
+
359
+
360
+ ## ====== Retrieve from URL
361
+ if have_wget:
362
+ test("Retrieve from URL", ['wget', '-O', 'testsuite-out/logo.png', 'http://%s.s3.amazonaws.com/xyz/etc/logo.png' % bucket(1)],
363
+ must_find_re = [ 'logo.png.*saved \[22059/22059\]' ])
364
+
365
+
366
+ ## ====== Change ACL to Private
367
+ test_s3cmd("Change ACL to Private", ['setacl', '--acl-private', '%s/xyz/etc/l*.png' % pbucket(1)],
368
+ must_find = [ "logo.png: ACL set to Private" ])
369
+
370
+
371
+ ## ====== Verify Private ACL
372
+ if have_wget:
373
+ test("Verify Private ACL", ['wget', '-O', 'testsuite-out/logo.png', 'http://%s.s3.amazonaws.com/xyz/etc/logo.png' % bucket(1)],
374
+ retcode = 8,
375
+ must_find_re = [ 'ERROR 403: Forbidden' ])
376
+
377
+
378
+ ## ====== Change ACL to Public
379
+ test_s3cmd("Change ACL to Public", ['setacl', '--acl-public', '--recursive', '%s/xyz/etc/' % pbucket(1) , '-v'],
380
+ must_find = [ "logo.png: ACL set to Public" ])
381
+
382
+
383
+ ## ====== Verify Public ACL
384
+ if have_wget:
385
+ test("Verify Public ACL", ['wget', '-O', 'testsuite-out/logo.png', 'http://%s.s3.amazonaws.com/xyz/etc/logo.png' % bucket(1)],
386
+ must_find_re = [ 'logo.png.*saved \[22059/22059\]' ])
387
+
388
+
389
+ ## ====== Sync more to S3
390
+ test_s3cmd("Sync more to S3", ['sync', 'testsuite/', 's3://%s/xyz/' % bucket(1), '--no-encrypt' ],
391
+ must_find = [ "File 'testsuite/demo/some-file.xml' stored as '%s/xyz/demo/some-file.xml' " % pbucket(1) ],
392
+ must_not_find = [ "File 'testsuite/etc/linked.png' stored as '%s/xyz/etc/linked.png" % pbucket(1) ])
393
+
394
+
395
+ ## ====== Don't check MD5 sum on Sync
396
+ test_copy("Change file cksum1.txt", "testsuite/checksum/cksum2.txt", "testsuite/checksum/cksum1.txt")
397
+ test_copy("Change file cksum33.txt", "testsuite/checksum/cksum2.txt", "testsuite/checksum/cksum33.txt")
398
+ test_s3cmd("Don't check MD5", ['sync', 'testsuite/', 's3://%s/xyz/' % bucket(1), '--no-encrypt', '--no-check-md5'],
399
+ must_find = [ "cksum33.txt" ],
400
+ must_not_find = [ "cksum1.txt" ])
401
+
402
+
403
+ ## ====== Check MD5 sum on Sync
404
+ test_s3cmd("Check MD5", ['sync', 'testsuite/', 's3://%s/xyz/' % bucket(1), '--no-encrypt', '--check-md5'],
405
+ must_find = [ "cksum1.txt" ])
406
+
407
+
408
+ ## ====== Rename within S3
409
+ test_s3cmd("Rename within S3", ['mv', '%s/xyz/etc/logo.png' % pbucket(1), '%s/xyz/etc2/Logo.PNG' % pbucket(1)],
410
+ must_find = [ 'File %s/xyz/etc/logo.png moved to %s/xyz/etc2/Logo.PNG' % (pbucket(1), pbucket(1))])
411
+
412
+
413
+ ## ====== Rename (NoSuchKey)
414
+ test_s3cmd("Rename (NoSuchKey)", ['mv', '%s/xyz/etc/logo.png' % pbucket(1), '%s/xyz/etc2/Logo.PNG' % pbucket(1)],
415
+ retcode = 1,
416
+ must_find_re = [ 'ERROR:.*NoSuchKey' ],
417
+ must_not_find = [ 'File %s/xyz/etc/logo.png moved to %s/xyz/etc2/Logo.PNG' % (pbucket(1), pbucket(1)) ])
418
+
419
+
420
+ ## ====== Sync more from S3
421
+ test_s3cmd("Sync more from S3", ['sync', '--delete-removed', '%s/xyz' % pbucket(1), 'testsuite-out'],
422
+ must_find = [ "deleted: testsuite-out/logo.png",
423
+ "File '%s/xyz/etc2/Logo.PNG' stored as 'testsuite-out/xyz/etc2/Logo.PNG' (22059 bytes" % pbucket(1),
424
+ "File '%s/xyz/demo/some-file.xml' stored as 'testsuite-out/xyz/demo/some-file.xml' " % pbucket(1) ],
425
+ must_not_find_re = [ "not-deleted.*etc/logo.png" ])
426
+
427
+
428
+ ## ====== Make dst dir for get
429
+ test_rmdir("Remove dst dir for get", "testsuite-out")
430
+
431
+
432
+ ## ====== Get multiple files
433
+ test_s3cmd("Get multiple files", ['get', '%s/xyz/etc2/Logo.PNG' % pbucket(1), '%s/xyz/etc/AtomicClockRadio.ttf' % pbucket(1), 'testsuite-out'],
434
+ retcode = 1,
435
+ must_find = [ 'Destination must be a directory or stdout when downloading multiple sources.' ])
436
+
437
+
438
+ ## ====== Make dst dir for get
439
+ test_mkdir("Make dst dir for get", "testsuite-out")
440
+
441
+
442
+ ## ====== Get multiple files
443
+ test_s3cmd("Get multiple files", ['get', '%s/xyz/etc2/Logo.PNG' % pbucket(1), '%s/xyz/etc/AtomicClockRadio.ttf' % pbucket(1), 'testsuite-out'],
444
+ must_find = [ u"saved as 'testsuite-out/Logo.PNG'", u"saved as 'testsuite-out/AtomicClockRadio.ttf'" ])
445
+
446
+ ## ====== Upload files differing in capitalisation
447
+ test_s3cmd("blah.txt / Blah.txt", ['put', '-r', 'testsuite/blahBlah', pbucket(1)],
448
+ must_find = [ '%s/blahBlah/Blah.txt' % pbucket(1), '%s/blahBlah/blah.txt' % pbucket(1)])
449
+
450
+ ## ====== Copy between buckets
451
+ test_s3cmd("Copy between buckets", ['cp', '%s/xyz/etc2/Logo.PNG' % pbucket(1), '%s/xyz/etc2/logo.png' % pbucket(3)],
452
+ must_find = [ "File %s/xyz/etc2/Logo.PNG copied to %s/xyz/etc2/logo.png" % (pbucket(1), pbucket(3)) ])
453
+
454
+ ## ====== Recursive copy
455
+ test_s3cmd("Recursive copy, set ACL", ['cp', '-r', '--acl-public', '%s/xyz/' % pbucket(1), '%s/copy' % pbucket(2), '--exclude', 'demo/dir?/*.txt', '--exclude', 'non-printables*'],
456
+ must_find = [ "File %s/xyz/etc2/Logo.PNG copied to %s/copy/etc2/Logo.PNG" % (pbucket(1), pbucket(2)),
457
+ "File %s/xyz/blahBlah/Blah.txt copied to %s/copy/blahBlah/Blah.txt" % (pbucket(1), pbucket(2)),
458
+ "File %s/xyz/blahBlah/blah.txt copied to %s/copy/blahBlah/blah.txt" % (pbucket(1), pbucket(2)) ],
459
+ must_not_find = [ "demo/dir1/file1-1.txt" ])
460
+
461
+ ## ====== Verify ACL and MIME type
462
+ test_s3cmd("Verify ACL and MIME type", ['info', '%s/copy/etc2/Logo.PNG' % pbucket(2) ],
463
+ must_find_re = [ "MIME type:.*image/png",
464
+ "ACL:.*\*anon\*: READ",
465
+ "URL:.*http://%s.s3.amazonaws.com/copy/etc2/Logo.PNG" % bucket(2) ])
466
+
467
+ ## ====== Rename within S3
468
+ test_s3cmd("Rename within S3", ['mv', '%s/copy/etc2/Logo.PNG' % pbucket(2), '%s/copy/etc/logo.png' % pbucket(2)],
469
+ must_find = [ 'File %s/copy/etc2/Logo.PNG moved to %s/copy/etc/logo.png' % (pbucket(2), pbucket(2))])
470
+
471
+ ## ====== Sync between buckets
472
+ test_s3cmd("Sync remote2remote", ['sync', '%s/xyz/' % pbucket(1), '%s/copy/' % pbucket(2), '--delete-removed', '--exclude', 'non-printables*'],
473
+ must_find = [ "File %s/xyz/demo/dir1/file1-1.txt copied to %s/copy/demo/dir1/file1-1.txt" % (pbucket(1), pbucket(2)),
474
+ "remote copy: etc/logo.png -> etc2/Logo.PNG",
475
+ "deleted: '%s/copy/etc/logo.png'" % pbucket(2) ],
476
+ must_not_find = [ "blah.txt" ])
477
+
478
+ ## ====== Don't Put symbolic link
479
+ test_s3cmd("Don't put symbolic links", ['put', 'testsuite/etc/linked1.png', 's3://%s/xyz/' % bucket(1),],
480
+ must_not_find_re = [ "linked1.png"])
481
+
482
+ ## ====== Put symbolic link
483
+ test_s3cmd("Put symbolic links", ['put', 'testsuite/etc/linked1.png', 's3://%s/xyz/' % bucket(1),'--follow-symlinks' ],
484
+ must_find = [ "File 'testsuite/etc/linked1.png' stored as '%s/xyz/linked1.png'" % pbucket(1)])
485
+
486
+ ## ====== Sync symbolic links
487
+ test_s3cmd("Sync symbolic links", ['sync', 'testsuite/', 's3://%s/xyz/' % bucket(1), '--no-encrypt', '--follow-symlinks' ],
488
+ must_find = ["remote copy: etc2/Logo.PNG -> etc/linked.png"],
489
+ # Don't want to recursively copy linked directories!
490
+ must_not_find_re = ["etc/more/linked-dir/more/give-me-more.txt",
491
+ "etc/brokenlink.png"],
492
+ )
493
+
494
+ ## ====== Multi source move
495
+ test_s3cmd("Multi-source move", ['mv', '-r', '%s/copy/blahBlah/Blah.txt' % pbucket(2), '%s/copy/etc/' % pbucket(2), '%s/moved/' % pbucket(2)],
496
+ must_find = [ "File %s/copy/blahBlah/Blah.txt moved to %s/moved/Blah.txt" % (pbucket(2), pbucket(2)),
497
+ "File %s/copy/etc/AtomicClockRadio.ttf moved to %s/moved/AtomicClockRadio.ttf" % (pbucket(2), pbucket(2)),
498
+ "File %s/copy/etc/TypeRa.ttf moved to %s/moved/TypeRa.ttf" % (pbucket(2), pbucket(2)) ],
499
+ must_not_find = [ "blah.txt" ])
500
+
501
+ ## ====== Verify move
502
+ test_s3cmd("Verify move", ['ls', '-r', pbucket(2)],
503
+ must_find = [ "%s/moved/Blah.txt" % pbucket(2),
504
+ "%s/moved/AtomicClockRadio.ttf" % pbucket(2),
505
+ "%s/moved/TypeRa.ttf" % pbucket(2),
506
+ "%s/copy/blahBlah/blah.txt" % pbucket(2) ],
507
+ must_not_find = [ "%s/copy/blahBlah/Blah.txt" % pbucket(2),
508
+ "%s/copy/etc/AtomicClockRadio.ttf" % pbucket(2),
509
+ "%s/copy/etc/TypeRa.ttf" % pbucket(2) ])
510
+
511
+ ## ====== Simple delete
512
+ test_s3cmd("Simple delete", ['del', '%s/xyz/etc2/Logo.PNG' % pbucket(1)],
513
+ must_find = [ "File %s/xyz/etc2/Logo.PNG deleted" % pbucket(1) ])
514
+
515
+
516
+ ## ====== Recursive delete
517
+ test_s3cmd("Recursive delete", ['del', '--recursive', '--exclude', 'Atomic*', '%s/xyz/etc' % pbucket(1)],
518
+ must_find = [ "File %s/xyz/etc/TypeRa.ttf deleted" % pbucket(1) ],
519
+ must_find_re = [ "File .*/etc/logo.png deleted" ],
520
+ must_not_find = [ "AtomicClockRadio.ttf" ])
521
+
522
+ ## ====== Recursive delete all
523
+ test_s3cmd("Recursive delete all", ['del', '--recursive', '--force', pbucket(1)],
524
+ must_find_re = [ "File .*binary/random-crap deleted" ])
525
+
526
+
527
+ ## ====== Remove empty bucket
528
+ test_s3cmd("Remove empty bucket", ['rb', pbucket(1)],
529
+ must_find = [ "Bucket '%s/' removed" % pbucket(1) ])
530
+
531
+
532
+ ## ====== Remove remaining buckets
533
+ test_s3cmd("Remove remaining buckets", ['rb', '--recursive', pbucket(2), pbucket(3)],
534
+ must_find = [ "Bucket '%s/' removed" % pbucket(2),
535
+ "Bucket '%s/' removed" % pbucket(3) ])
536
+
537
+ # vim:et:ts=4:sts=4:ai