s3_cmd_bin 0.0.1

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.
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