Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: third_party/gsutil/gslib/commands/ls.py

Issue 12042069: Scripts to download files from google storage based on sha1 sums (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Removed gsutil/tests and gsutil/docs Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2011 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from boto.s3.deletemarker import DeleteMarker
16 from gslib.bucket_listing_ref import BucketListingRef
17 from gslib.command import Command
18 from gslib.command import COMMAND_NAME
19 from gslib.command import COMMAND_NAME_ALIASES
20 from gslib.command import CONFIG_REQUIRED
21 from gslib.command import FILE_URIS_OK
22 from gslib.command import MAX_ARGS
23 from gslib.command import MIN_ARGS
24 from gslib.command import PROVIDER_URIS_OK
25 from gslib.command import SUPPORTED_SUB_ARGS
26 from gslib.command import URIS_START_ARG
27 from gslib.exception import CommandException
28 from gslib.help_provider import HELP_NAME
29 from gslib.help_provider import HELP_NAME_ALIASES
30 from gslib.help_provider import HELP_ONE_LINE_SUMMARY
31 from gslib.help_provider import HELP_TEXT
32 from gslib.help_provider import HelpType
33 from gslib.help_provider import HELP_TYPE
34 from gslib.plurality_checkable_iterator import PluralityCheckableIterator
35 from gslib.util import ListingStyle
36 from gslib.util import MakeHumanReadable
37 from gslib.util import NO_MAX
38 from gslib.wildcard_iterator import ContainsWildcard
39 import boto
40
41 _detailed_help_text = ("""
42 <B>SYNOPSIS</B>
43 gsutil ls [-a] [-b] [-l] [-L] [-R] [-p proj_id] uri...
44
45
46 <B>LISTING PROVIDERS, BUCKETS, SUBDIRECTORIES, AND OBJECTS</B>
47 If you run gsutil ls without URIs, it lists all of the Google Cloud Storage
48 buckets under your default project ID:
49
50 gsutil ls
51
52 (For details about projects, see "gsutil help projects" and also the -p
53 option in the OPTIONS section below.)
54
55 If you specify one or more provider URIs, gsutil ls will list buckets at
56 each listed provider:
57
58 gsutil ls gs://
59
60 If you specify bucket URIs, gsutil ls will list objects at the top level of
61 each bucket, along with the names of each subdirectory. For example:
62
63 gsutil ls gs://bucket
64
65 might produce output like:
66
67 gs://bucket/obj1.htm
68 gs://bucket/obj2.htm
69 gs://bucket/images1/
70 gs://bucket/images2/
71
72 The "/" at the end of the last 2 URIs tells you they are subdirectories,
73 which you can list using:
74
75 gsutil ls gs://bucket/images*
76
77 If you specify object URIs, gsutil ls will list the specified objects. For
78 example:
79
80 gsutil ls gs://bucket/*.txt
81
82 will list all files whose name matches the above wildcard at the top level
83 of the bucket.
84
85 See "gsutil help wildcards" for more details on working with wildcards.
86
87
88 <B>DIRECTORY BY DIRECTORY, FLAT, and RECURSIVE LISTINGS</B>
89 Listing a bucket or subdirectory (as illustrated near the end of the previous
90 section) only shows the objects and names of subdirectories it contains. You
91 can list all objects in a bucket by using the -R option. For example:
92
93 gsutil ls -R gs://bucket
94
95 will list the top-level objects and buckets, then the objects and
96 buckets under gs://bucket/images1, then those under gs://bucket/images2, etc.
97
98 If you want to see all objects in the bucket in one "flat" listing use the
99 recursive ("**") wildcard, like:
100
101 gsutil ls -R gs://bucket/**
102
103 or, for a flat listing of a subdirectory:
104
105 gsutil ls -R gs://bucket/dir/**
106
107
108 <B>LISTING OBJECT DETAILS</B>
109 If you specify the -l option, gsutil will output additional information
110 about each matching provider, bucket, subdirectory, or object. For example,
111
112 gsutil ls -l gs://bucket/*.txt
113
114 will print the object size, creation time stamp, and name of each matching
115 object, along with the total count and sum of sizes of all matching objects:
116
117 2276224 2012-03-02T19:25:17 gs://bucket/obj1
118 3914624 2012-03-02T19:30:27 gs://bucket/obj2
119 TOTAL: 2 objects, 6190848 bytes (5.9 MB)
120
121 Note that the total listed in parentheses above is in mebibytes (or gibibytes,
122 tebibytes, etc.), which corresponds to the unit of billing measurement for
123 Google Cloud Storage.
124
125 You can get a listing of all the objects in the top-level bucket directory
126 (along with the total count and sum of sizes) using a command like:
127
128 gsutil ls -l gs://bucket
129
130 To print additional detail about objects and buckets use the gsutil ls -L
131 option. For example:
132
133 gsutil ls -L gs://bucket/obj1
134
135 will print something like:
136
137 gs://bucket/obj1:
138 Creation Time: Fri, 02 Mar 2012 19:25:17 GMT
139 Size: 2276224
140 Cache-Control: private, max-age=0
141 Content-Type: application/x-executable
142 ETag: 5ca6796417570a586723b7344afffc81
143 ACL: <Owner:00b4903a97163d99003117abe64d292561d2b4074fc90ce5c 0e35ac45f66ad70, <<UserById: 00b4903a97163d99003117abe64d292561d2b4074fc90ce5c0e 35ac45f66ad70>: u'FULL_CONTROL'>>
144 TOTAL: 1 objects, 2276224 bytes (2.17 MB)
145
146 Note that the -L option is slower and more costly to use than the -l option,
147 because it makes a bucket listing request followed by a HEAD request for
148 each individual object (rather than just parsing the information it needs
149 out of a single bucket listing, the way the -l option does).
150
151 See also "gsutil help getacl" for getting a more readable version of the ACL.
152
153
154 <B>LISTING BUCKET DETAILS</B>
155 If you want to see information about the bucket itself, use the -b
156 option. For example:
157
158 gsutil ls -L -b gs://bucket
159
160 will print something like:
161
162 gs://bucket/ :
163 24 objects, 29.83 KB
164 LocationConstraint: US
165 StorageClass: STANDARD
166 ACL: <Owner:00b4903a9740e42c29800f53bd5a9a62a2f96eb3f64a4313a115df3f 3a776bf7, <<GroupById: 00b4903a9740e42c29800f53bd5a9a62a2f96eb3f64a4313a115df3f3 a776bf7>: u'FULL_CONTROL'>>
167 Default ACL: <>
168 TOTAL: 24 objects, 30544 bytes (29.83 KB)
169
170
171 <B>OPTIONS</B>
172 -l Prints long listing (owner, length).
173
174 -L Prints even more detail than -L. This is a separate option because
175 it makes additional service requests (so, takes longer and adds
176 requests costs).
177
178 -b Prints info about the bucket when used with a bucket URI.
179
180 -p proj_id Specifies the project ID to use for listing buckets.
181
182 -R, -r Requests a recursive listing.
183
184 -a Includes non-current object versions / generations in the listing
185 (only useful with a versioning-enabled bucket).
186 """)
187
188
189 class LsCommand(Command):
190 """Implementation of gsutil ls command."""
191
192 # Command specification (processed by parent class).
193 command_spec = {
194 # Name of command.
195 COMMAND_NAME : 'ls',
196 # List of command name aliases.
197 COMMAND_NAME_ALIASES : ['dir', 'list'],
198 # Min number of args required by this command.
199 MIN_ARGS : 0,
200 # Max number of args required by this command, or NO_MAX.
201 MAX_ARGS : NO_MAX,
202 # Getopt-style string specifying acceptable sub args.
203 SUPPORTED_SUB_ARGS : 'ablLp:rR',
204 # True if file URIs acceptable for this command.
205 FILE_URIS_OK : False,
206 # True if provider-only URIs acceptable for this command.
207 PROVIDER_URIS_OK : True,
208 # Index in args of first URI arg.
209 URIS_START_ARG : 0,
210 # True if must configure gsutil before running command.
211 CONFIG_REQUIRED : True,
212 }
213 help_spec = {
214 # Name of command or auxiliary help info for which this help applies.
215 HELP_NAME : 'ls',
216 # List of help name aliases.
217 HELP_NAME_ALIASES : ['dir', 'list'],
218 # Type of help:
219 HELP_TYPE : HelpType.COMMAND_HELP,
220 # One line summary of this help.
221 HELP_ONE_LINE_SUMMARY : 'List providers, buckets, or objects',
222 # The full help text.
223 HELP_TEXT : _detailed_help_text,
224 }
225
226 def _PrintBucketInfo(self, bucket_uri, listing_style):
227 """Print listing info for given bucket.
228
229 Args:
230 bucket_uri: StorageUri being listed.
231 listing_style: ListingStyle enum describing type of output desired.
232
233 Returns:
234 Tuple (total objects, total bytes) in the bucket.
235 """
236 bucket_objs = 0
237 bucket_bytes = 0
238 if listing_style == ListingStyle.SHORT:
239 print bucket_uri
240 else:
241 for obj in self.WildcardIterator(
242 bucket_uri.clone_replace_name('**')).IterKeys():
243 bucket_objs += 1
244 bucket_bytes += obj.size
245 if listing_style == ListingStyle.LONG:
246 print '%s : %s objects, %s' % (
247 bucket_uri, bucket_objs, MakeHumanReadable(bucket_bytes))
248 else: # listing_style == ListingStyle.LONG_LONG:
249 location_constraint = bucket_uri.get_location(validate=False,
250 headers=self.headers)
251 location_output = ''
252 if location_constraint:
253 location_output = '\n\tLocationConstraint: %s' % location_constraint
254 storage_class = bucket_uri.get_storage_class(validate=False,
255 headers=self.headers)
256 self.proj_id_handler.FillInProjectHeaderIfNeeded(
257 'get_acl', bucket_uri, self.headers)
258 print('%s :\n\t%d objects, %s\n\tStorageClass: %s%s\n\tACL: %s\n'
259 '\tDefault ACL: %s' % (
260 bucket_uri, bucket_objs, MakeHumanReadable(bucket_bytes),
261 storage_class, location_output,
262 bucket_uri.get_acl(False, self.headers),
263 bucket_uri.get_def_acl(False, self.headers)))
264 return (bucket_objs, bucket_bytes)
265
266 def _UriStrForObj(self, uri, obj):
267 """Constructs a URI string for the given object.
268
269 For example if we were iterating gs://*, obj could be an object in one
270 of the user's buckets enumerated by the ls command.
271
272 Args:
273 uri: base StorageUri being iterated.
274 obj: object (Key) being listed.
275
276 Returns:
277 URI string.
278 """
279 version_info = ''
280 if self.all_versions:
281 if uri.get_provider().name == 'google' and obj.generation:
282 version_info = '#%s.%s' % (obj.generation , obj.meta_generation)
283 elif uri.get_provider().name == 'aws' and obj.version_id:
284 if isinstance(obj, DeleteMarker):
285 version_info = '#<DeleteMarker>' + str(obj.version_id)
286 else:
287 version_info = '#' + str(obj.version_id)
288 else:
289 version_info = ''
290 return '%s://%s/%s%s' % (uri.scheme, obj.bucket.name, obj.name, version_info )
291
292 def _PrintInfoAboutBucketListingRef(self, bucket_listing_ref, listing_style):
293 """Print listing info for given bucket_listing_ref.
294
295 Args:
296 bucket_listing_ref: BucketListing being listed.
297 listing_style: ListingStyle enum describing type of output desired.
298
299 Returns:
300 Tuple (number of objects,
301 object length, if listing_style is one of the long listing formats)
302
303 Raises:
304 Exception: if calling bug encountered.
305 """
306 uri = bucket_listing_ref.GetUri()
307 obj = bucket_listing_ref.GetKey()
308 uri_str = self._UriStrForObj(uri, obj)
309 if listing_style == ListingStyle.SHORT:
310 print uri_str.encode('utf-8')
311 return (1, 0)
312 elif listing_style == ListingStyle.LONG:
313 # Exclude timestamp fractional secs (example: 2010-08-23T12:46:54.187Z).
314 timestamp = obj.last_modified[:19].decode('utf8').encode('ascii')
315 if not isinstance(obj, DeleteMarker):
316 print '%10s %s %s' % (obj.size, timestamp, uri_str.encode('utf-8'))
317 return (1, obj.size)
318 else:
319 print '%10s %s %s' % (0, timestamp, uri_str.encode('utf-8'))
320 return (0, 1)
321 elif listing_style == ListingStyle.LONG_LONG:
322 # Run in a try/except clause so we can continue listings past
323 # access-denied errors (which can happen because user may have READ
324 # permission on object and thus see the bucket listing data, but lack
325 # FULL_CONTROL over individual objects and thus not be able to read
326 # their ACLs).
327 try:
328 print '%s:' % uri_str.encode('utf-8')
329 suri = self.suri_builder.StorageUri(uri_str,
330 parse_version=self.all_versions)
331 obj = suri.get_key(False)
332 print '\tCreation time:\t%s' % obj.last_modified
333 if obj.cache_control:
334 print '\tCache-Control:\t%s' % obj.cache_control
335 if obj.content_disposition:
336 print '\tContent-Disposition:\t%s' % obj.content_disposition
337 if obj.content_encoding:
338 print '\tContent-Encoding:\t%s' % obj.content_encoding
339 if obj.content_language:
340 print '\tContent-Language:\t%s' % obj.content_language
341 print '\tContent-Length:\t%s' % obj.size
342 print '\tContent-Type:\t%s' % obj.content_type
343 if obj.metadata:
344 prefix = uri.get_provider().metadata_prefix
345 for name in obj.metadata:
346 print '\t%s%s:\t%s' % (prefix, name, obj.metadata[name])
347 print '\tETag:\t\t%s' % obj.etag.strip('"\'')
348 print '\tACL:\t\t%s' % (suri.get_acl(False, self.headers))
349 return (1, obj.size)
350 except boto.exception.GSResponseError as e:
351 if e.status == 403:
352 print ('\tACL:\t\tACCESS DENIED. Note: you need FULL_CONTROL '
353 'permission\n\t\t\ton the object to read its ACL.')
354 return (1, obj.size)
355 else:
356 raise e
357 else:
358 raise Exception('Unexpected ListingStyle(%s)' % listing_style)
359
360 def _ExpandUriAndPrintInfo(self, uri, listing_style, should_recurse=False):
361 """
362 Expands wildcards and directories/buckets for uri as needed, and
363 calls _PrintInfoAboutBucketListingRef() on each.
364
365 Args:
366 uri: StorageUri being listed.
367 listing_style: ListingStyle enum describing type of output desired.
368 should_recurse: bool indicator of whether to expand recursively.
369
370 Returns:
371 Tuple (number of matching objects, number of bytes across these objects).
372 """
373 # We do a two-level loop, with the outer loop iterating level-by-level from
374 # blrs_to_expand, and the inner loop iterating the matches at the current
375 # level, printing them, and adding any new subdirs that need expanding to
376 # blrs_to_expand (to be picked up in the next outer loop iteration).
377 blrs_to_expand = [BucketListingRef(uri)]
378 num_objs = 0
379 num_bytes = 0
380 expanding_top_level = True
381 printed_one = False
382 num_expanded_blrs = 0
383 while len(blrs_to_expand):
384 if printed_one:
385 print
386 blr = blrs_to_expand.pop(0)
387 if blr.HasKey():
388 blr_iterator = iter([blr])
389 elif blr.HasPrefix():
390 # Bucket subdir from a previous iteration. Print "header" line only if
391 # we're listing more than one subdir (or if it's a recursive listing),
392 # to be consistent with the way UNIX ls works.
393 if num_expanded_blrs > 1 or should_recurse:
394 print '%s:' % blr.GetUriString().encode('utf-8')
395 printed_one = True
396 blr_iterator = self.WildcardIterator( '%s/*' %
397 blr.GetRStrippedUriString(),
398 all_versions=self.all_versions)
399 elif blr.NamesBucket():
400 blr_iterator = self.WildcardIterator('%s*' % blr.GetUriString(),
401 all_versions=self.all_versions)
402 else:
403 # This BLR didn't come from a bucket listing. This case happens for
404 # BLR's instantiated from a user-provided URI.
405 blr_iterator = PluralityCheckableIterator(
406 _UriOnlyBlrExpansionIterator(
407 self, blr, all_versions=self.all_versions))
408 if blr_iterator.is_empty() and not ContainsWildcard(uri):
409 raise CommandException('No such object %s' % uri)
410 for cur_blr in blr_iterator:
411 num_expanded_blrs = num_expanded_blrs + 1
412 if cur_blr.HasKey():
413 # Object listing.
414 (no, nb) = self._PrintInfoAboutBucketListingRef(
415 cur_blr, listing_style)
416 num_objs += no
417 num_bytes += nb
418 printed_one = True
419 else:
420 # Subdir listing. If we're at the top level of a bucket subdir
421 # listing don't print the list here (corresponding to how UNIX ls
422 # dir just prints its contents, not the name followed by its
423 # contents).
424 if (expanding_top_level and not uri.names_bucket()) or should_recurse:
425 if cur_blr.GetUriString().endswith('//'):
426 # Expand gs://bucket// into gs://bucket//* so we don't infinite
427 # loop. This case happens when user has uploaded an object whose
428 # name begins with a /.
429 cur_blr = BucketListingRef(self.suri_builder.StorageUri(
430 '%s*' % cur_blr.GetUriString()), None, None, cur_blr.headers)
431 blrs_to_expand.append(cur_blr)
432 # Don't include the subdir name in the output if we're doing a
433 # recursive listing, as it will be printed as 'subdir:' when we get
434 # to the prefix expansion, the next iteration of the main loop.
435 else:
436 if listing_style == ListingStyle.LONG:
437 print '%-33s%s' % ('', cur_blr.GetUriString().encode('utf-8'))
438 else:
439 print cur_blr.GetUriString().encode('utf-8')
440 expanding_top_level = False
441 return (num_objs, num_bytes)
442
443 # Command entry point.
444 def RunCommand(self):
445 got_nomatch_errors = False
446 listing_style = ListingStyle.SHORT
447 get_bucket_info = False
448 self.recursion_requested = False
449 self.all_versions = False
450 if self.sub_opts:
451 for o, a in self.sub_opts:
452 if o == '-a':
453 self.all_versions = True
454 elif o == '-b':
455 get_bucket_info = True
456 elif o == '-l':
457 listing_style = ListingStyle.LONG
458 elif o == '-L':
459 listing_style = ListingStyle.LONG_LONG
460 elif o == '-p':
461 self.proj_id_handler.SetProjectId(a)
462 elif o == '-r' or o == '-R':
463 self.recursion_requested = True
464
465 if not self.args:
466 # default to listing all gs buckets
467 self.args = ['gs://']
468
469 total_objs = 0
470 total_bytes = 0
471 for uri_str in self.args:
472 uri = self.suri_builder.StorageUri(uri_str)
473 self.proj_id_handler.FillInProjectHeaderIfNeeded('ls', uri, self.headers)
474
475 if uri.names_provider():
476 # Provider URI: use bucket wildcard to list buckets.
477 for uri in self.WildcardIterator('%s://*' % uri.scheme).IterUris():
478 (bucket_objs, bucket_bytes) = self._PrintBucketInfo(uri,
479 listing_style)
480 total_bytes += bucket_bytes
481 total_objs += bucket_objs
482 elif uri.names_bucket():
483 # Bucket URI -> list the object(s) in that bucket.
484 if get_bucket_info:
485 # ls -b bucket listing request: List info about bucket(s).
486 for uri in self.WildcardIterator(uri).IterUris():
487 (bucket_objs, bucket_bytes) = self._PrintBucketInfo(uri,
488 listing_style)
489 total_bytes += bucket_bytes
490 total_objs += bucket_objs
491 else:
492 # Not -b request: List objects in the bucket(s).
493 (no, nb) = self._ExpandUriAndPrintInfo(uri, listing_style,
494 should_recurse=self.recursion_requested)
495 if no == 0 and ContainsWildcard(uri):
496 got_nomatch_errors = True
497 total_objs += no
498 total_bytes += nb
499 else:
500 # URI names an object or object subdir -> list matching object(s) /
501 # subdirs.
502 (exp_objs, exp_bytes) = self._ExpandUriAndPrintInfo(uri, listing_style,
503 should_recurse=self.recursion_requested)
504 if exp_objs == 0 and ContainsWildcard(uri):
505 got_nomatch_errors = True
506 total_bytes += exp_bytes
507 total_objs += exp_objs
508
509 if total_objs and listing_style != ListingStyle.SHORT:
510 print ('TOTAL: %d objects, %d bytes (%s)' %
511 (total_objs, total_bytes, MakeHumanReadable(float(total_bytes))))
512 if got_nomatch_errors:
513 raise CommandException('One or more URIs matched no objects.')
514
515 return 0
516
517 # Test specification. See definition of test_steps in base class for
518 # details on how to populate these fields.
519 num_test_buckets = 3
520 test_steps = [
521 # (test name, cmd line, ret code, (result_file, expect_file))
522 ('gen bucket expect', 'echo gs://$B0/ >$F9', 0, None),
523 ('gen obj expect', 'echo gs://$B1/$O0 >$F8', 0, None),
524 ('simple ls', 'gsutil ls', 0, None),
525 ('list empty bucket', 'gsutil ls gs://$B0', 0, None),
526 ('list empty bucket w/ -b', 'gsutil ls -b gs://$B0 >$F7', 0,
527 ('$F7', '$F9')),
528 ('list bucket contents', 'gsutil ls gs://$B1 >$F7', 0, ('$F7', '$F8')),
529 ('list object', 'gsutil ls gs://$B1/$O0 >$F7', 0, ('$F7', '$F8')),
530 ('enable versioning', 'gsutil setversioning on gs://$B2', 0, None),
531 ('add version 1', 'gsutil cp gs://$B2/$O0 gs://$B2/$O1', 0, None),
532 ('add version 2', 'gsutil cp gs://$B2/$O0 gs://$B2/$O1', 0, None),
533 ('gen expected count', 'echo 3 > $F6', 0, None),
534 ('check version list', 'gsutil ls -a gs://$B2/$O1 | wc -l > $F5', 0,
535 ('$F5', '$F6')),
536 ]
537
538
539 class _UriOnlyBlrExpansionIterator:
540 """
541 Iterator that expands a BucketListingRef that contains only a URI (i.e.,
542 didn't come from a bucket listing), yielding BucketListingRefs to which it
543 expands. This case happens for BLR's instantiated from a user-provided URI.
544
545 Note that we can't use NameExpansionIterator here because it produces an
546 iteration over the full object names (e.g., expanding "gs://bucket" to
547 "gs://bucket/dir/o1" and "gs://bucket/dir/o2"), while for the ls command
548 we need also to see the intermediate directories (like "gs://bucket/dir").
549 """
550 def __init__(self, command_instance, blr, all_versions=False):
551 self.command_instance = command_instance
552 self.blr = blr
553 self.all_versions=all_versions
554
555 def __iter__(self):
556 """
557 Args:
558 command_instance: calling instance of Command class.
559 blr: BucketListingRef to expand.
560
561 Yields:
562 List of BucketListingRef to which it expands.
563 """
564 # Do a delimited wildcard expansion so we get any matches along with
565 # whether they are keys or prefixes. That way if bucket contains a key
566 # 'abcd' and another key 'abce/x.txt' the expansion will return two BLRs,
567 # the first with HasKey()=True and the second with HasPrefix()=True.
568 rstripped_uri_str = self.blr.GetRStrippedUriString()
569 if ContainsWildcard(rstripped_uri_str):
570 for blr in self.command_instance.WildcardIterator(
571 rstripped_uri_str, all_versions=self.all_versions):
572 yield blr
573 return
574 # Build a wildcard to expand so CloudWildcardIterator will not just treat it
575 # as a key and yield the result without doing a bucket listing.
576 for blr in self.command_instance.WildcardIterator(
577 rstripped_uri_str + '*', all_versions=self.all_versions):
578 # Find the originally specified BucketListingRef in the expanded list (if
579 # present). Don't just use the expanded list, because it would also
580 # include objects whose name prefix matches the blr name (because of the
581 # wildcard match we did above). Note that there can be multiple matches,
582 # for the case where there's both an object and a subdirectory with the
583 # same name.
584 if blr.GetRStrippedUriString() == rstripped_uri_str:
585 yield blr
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698