From 16f1755a808ed59adaf7c7707e29d69f6ef3ff61 Mon Sep 17 00:00:00 2001 From: Lana Parezanin Date: Wed, 20 Nov 2024 14:34:57 -0800 Subject: [PATCH 01/12] Fixing gallery build error --- .../BlobStorageVulnerabilityWriterFacts.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs b/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs index 12791043e2..0c4ec02aa6 100644 --- a/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs +++ b/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs @@ -165,6 +165,11 @@ public override Task> ListAsync(bool getMetadata, C return _storage.ListAsync(getMetadata, cancellationToken); } + public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) + { + return _storage.ListAsync(getMetadata, cancellationToken); + } + public override Task SetMetadataAsync(Uri resourceUri, IDictionary metadata) { return _storage.SetMetadataAsync(resourceUri, metadata); From 9155726fb0cac8b3fa62046c80a5c77ea53e6112 Mon Sep 17 00:00:00 2001 From: Lana Parezanin Date: Wed, 20 Nov 2024 14:15:15 -0800 Subject: [PATCH 02/12] Testfix --- .../DetailedReportPostProcessorFacts.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Stats.PostProcessReports.Tests/DetailedReportPostProcessorFacts.cs b/tests/Stats.PostProcessReports.Tests/DetailedReportPostProcessorFacts.cs index 67d77e7f38..8acd723d96 100644 --- a/tests/Stats.PostProcessReports.Tests/DetailedReportPostProcessorFacts.cs +++ b/tests/Stats.PostProcessReports.Tests/DetailedReportPostProcessorFacts.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -33,13 +33,13 @@ public class DetailedReportPostProcessorFacts public async Task DoesntStartIfNoSuccessFile() { _sourceStorageMock - .Setup(ss => ss.ListAsync(It.IsAny(), It.IsAny())) + .Setup(ss => ss.ListTopLevelAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new List()); await _target.CopyReportsAsync(); _sourceStorageMock - .Verify(ss => ss.ListAsync(It.IsAny(), It.IsAny()), Times.Once); + .Verify(ss => ss.ListTopLevelAsync(It.IsAny(), It.IsAny()), Times.Once); _sourceStorageMock.VerifyNoOtherCalls(); _workStorageMock.VerifyNoOtherCalls(); _destinationStorageMock.VerifyNoOtherCalls(); @@ -186,7 +186,7 @@ public async Task SkipsProcessedFiles() { "FilesCreated", "123" } }; _workStorageMock - .Setup(ss => ss.ListAsync(It.IsAny(), It.IsAny())) + .Setup(ss => ss.ListTopLevelAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(() => new List(_workFiles.Select(f => Blob( _workStorageMock, f, @@ -286,7 +286,7 @@ private static void SetupStorageMock(Mock mock, string baseUrl, Func s.ListAsync(It.IsAny(), It.IsAny())) + .Setup(s => s.ListTopLevelAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(() => new List(files().Select(f => Blob(mock, f)))); mock .Setup(s => s.ResolveUri(It.IsAny())) From fabc79fc7085adc919fd3a5560b704858e29810c Mon Sep 17 00:00:00 2001 From: Lana Parezanin Date: Mon, 28 Oct 2024 11:46:48 -0700 Subject: [PATCH 03/12] Bugfix --- src/NuGet.Services.Storage/AzureStorage.cs | 24 ++++++++++++++++++- .../DetailedReportPostProcessor.cs | 12 +++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/NuGet.Services.Storage/AzureStorage.cs b/src/NuGet.Services.Storage/AzureStorage.cs index 8e54874625..1c30798c24 100644 --- a/src/NuGet.Services.Storage/AzureStorage.cs +++ b/src/NuGet.Services.Storage/AzureStorage.cs @@ -189,7 +189,29 @@ public override async Task> ListAsync(bool getMetad await foreach (BlobHierarchyItem blob in _directory.GetBlobsByHierarchyAsync(traits: blobTraits, prefix: _path)) { - blobList.Add(await GetStorageListItemAsync(_directory.GetBlockBlobClient(blob.Blob.Name))); + blobList.Add(await GetStorageListItemAsync(_directory.GetBlockBlobClient(blob.Blob.Name))); + } + + return blobList; + } + + public override async Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) + { + var prefix = _path.Trim('/') + '/'; + var blobTraits = new BlobTraits(); + if (getMetadata) + { + blobTraits |= BlobTraits.Metadata; + } + + var blobList = new List(); + + await foreach (BlobHierarchyItem blob in _directory.GetBlobsByHierarchyAsync(traits: blobTraits, prefix: prefix, delimiter: "/")) + { + if (!blob.IsPrefix) + { + blobList.Add(await GetStorageListItemAsync(_directory.GetBlockBlobClient(blob.Blob.Name))); + } } return blobList; diff --git a/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs b/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs index 8441fa4d2e..4ab9cb0a3b 100644 --- a/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs +++ b/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs @@ -120,7 +120,7 @@ private async Task ProcessBlobs(List jsonBlobs, CancellationTok foreach (var sourceBlob in jsonBlobs) { var blobName = GetBlobName(sourceBlob); - var workBlobUri = _workStorage.ResolveUri(blobName); + var workBlobUri = _workStorage.ResolveUri(_configuration.WorkPath + blobName); var sourceBlobStats = new BlobStatistics(); var individualReports = await ProcessSourceBlobAsync(sourceBlob, sourceBlobStats, totals); using (_logger.BeginScope("Processing {BlobName}", blobName)) @@ -154,7 +154,7 @@ private async Task ProcessBlobs(List jsonBlobs, CancellationTok } } } - var jobSucceededUrl = _workStorage.ResolveUri(JobSucceededFilename); + var jobSucceededUrl = _workStorage.ResolveUri(_configuration.WorkPath + JobSucceededFilename); var jobSucceededContent = new StringStorageContent("", TextContentType); await _workStorage.Save(jobSucceededUrl, jobSucceededContent, overwrite: true, cancellationToken: cancellationToken); _telemetryService.ReportTotals(totals.SourceFilesProcessed, totals.TotalLinesProcessed, totals.TotalFilesCreated, totals.TotalLinesFailed); @@ -202,13 +202,13 @@ private async Task CopySourceBlobsAsync(List jsonBlobs, Cancell foreach (var sourceBlob in jsonBlobs) { var blobName = GetBlobName(sourceBlob); - var targetUrl = _workStorage.ResolveUri(blobName); + var targetUrl = _workStorage.ResolveUri(_configuration.WorkPath + blobName); _logger.LogInformation("{SourceBlobUri} ({BlobName})", sourceBlob.Uri.AbsoluteUri, blobName); _logger.LogInformation("{WorkBlobUrl}", targetUrl); await _sourceStorage.CopyAsync(sourceBlob.Uri, _workStorage, targetUrl, destinationProperties: null, cancellationToken); } var copySucceededContent = new StringStorageContent("", TextContentType); - var copySucceededUrl = _workStorage.ResolveUri(CopySucceededFilename); + var copySucceededUrl = _workStorage.ResolveUri(_configuration.WorkPath + CopySucceededFilename); await _workStorage.Save(copySucceededUrl, copySucceededContent, overwrite: true, cancellationToken: cancellationToken); } @@ -245,7 +245,7 @@ private async Task> ProcessSourceBlobAsync( var sw = Stopwatch.StartNew(); var numLines = 0; var individualReports = new ConcurrentBag(); - var workStorageUrl = _workStorage.ResolveUri(GetBlobName(sourceBlob)); + var workStorageUrl = _workStorage.ResolveUri(_configuration.WorkPath + GetBlobName(sourceBlob)); var storageContent = await _workStorage.Load(workStorageUrl, CancellationToken.None); using (var sourceStream = storageContent.GetContentStream()) using (var streamReader = new StreamReader(sourceStream)) @@ -351,7 +351,7 @@ private async Task WriteReports( continue; } var outFilename = $"recentpopularitydetail_{data.PackageId.ToLowerInvariant()}.json"; - var destinationUri = _destinationStorage.ResolveUri(outFilename); + var destinationUri = _destinationStorage.ResolveUri(_configuration.DestinationPath + outFilename); var storageContent = new StringStorageContent(details.Data, JsonContentType); await _destinationStorage.Save(destinationUri, storageContent, overwrite: true, cancellationToken: cancellationToken); From f8c582992f52e6039eb4af771c32c133645181bd Mon Sep 17 00:00:00 2001 From: Lana Parezanin Date: Mon, 21 Oct 2024 17:22:34 -0700 Subject: [PATCH 04/12] Added TopLevel --- global.json | 4 ++-- src/NuGet.Services.Storage/AggregateStorage.cs | 7 +++++-- src/NuGet.Services.Storage/FileStorage.cs | 5 ++++- src/NuGet.Services.Storage/IStorage.cs | 4 +++- src/NuGet.Services.Storage/Storage.cs | 7 +++++++ .../DetailedReportPostProcessor.cs | 9 +++++---- 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/global.json b/global.json index 32da22419b..4c1d7e5aaa 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "8.0.303", + "version": "6.0.0", "rollForward": "latestFeature", "allowPrerelease": false } -} \ No newline at end of file +} diff --git a/src/NuGet.Services.Storage/AggregateStorage.cs b/src/NuGet.Services.Storage/AggregateStorage.cs index 4fc61ab402..788153f939 100644 --- a/src/NuGet.Services.Storage/AggregateStorage.cs +++ b/src/NuGet.Services.Storage/AggregateStorage.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -111,9 +111,12 @@ public override async Task> ListAsync(bool getMetad return await _primaryStorage.ListAsync(getMetadata, cancellationToken); } + public override async Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => + await ListAsync(getMetadata, cancellationToken); + public override Task SetMetadataAsync(Uri resourceUri, IDictionary metadata) { throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/NuGet.Services.Storage/FileStorage.cs b/src/NuGet.Services.Storage/FileStorage.cs index 32732ab85f..f6f815dfe8 100644 --- a/src/NuGet.Services.Storage/FileStorage.cs +++ b/src/NuGet.Services.Storage/FileStorage.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -57,6 +57,9 @@ public override Task> ListAsync(bool getMetadata, C return Task.FromResult>(List(getMetadata)); } + public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => + ListAsync(getMetadata, cancellationToken); + public string Path { get; diff --git a/src/NuGet.Services.Storage/IStorage.cs b/src/NuGet.Services.Storage/IStorage.cs index ccd11b146e..cb8dd46fc2 100644 --- a/src/NuGet.Services.Storage/IStorage.cs +++ b/src/NuGet.Services.Storage/IStorage.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -20,6 +20,8 @@ public interface IStorage Uri ResolveUri(string relativeUri); IEnumerable List(bool getMetadata); Task> ListAsync(bool getMetadata, CancellationToken cancellationToken); + Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken); + Task CopyAsync( Uri sourceUri, IStorage destinationStorage, diff --git a/src/NuGet.Services.Storage/Storage.cs b/src/NuGet.Services.Storage/Storage.cs index 2f428d0501..ae66aeb4fe 100644 --- a/src/NuGet.Services.Storage/Storage.cs +++ b/src/NuGet.Services.Storage/Storage.cs @@ -156,6 +156,7 @@ public async Task LoadString(Uri resourceUri, CancellationToken cancella public abstract Task ExistsAsync(string fileName, CancellationToken cancellationToken); public abstract IEnumerable List(bool getMetadata); public abstract Task> ListAsync(bool getMetadata, CancellationToken cancellationToken); + public abstract Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken); public bool Verbose { @@ -209,6 +210,12 @@ protected string GetName(Uri uri) { name = name.Substring(0, name.IndexOf("#")); } + + if (name.Contains("?")) + { + name = name.Substring(0, name.IndexOf("?")); + } + return name; } diff --git a/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs b/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs index 4ab9cb0a3b..13a720ad4a 100644 --- a/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs +++ b/src/Stats.PostProcessReports/DetailedReportPostProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -10,6 +10,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using Azure.Core; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; @@ -214,14 +215,14 @@ private async Task CopySourceBlobsAsync(List jsonBlobs, Cancell private async Task> EnumerateSourceBlobsAsync() { - var blobs = await _sourceStorage.ListAsync(getMetadata: true, cancellationToken: CancellationToken.None); + var blobs = await _sourceStorage.ListTopLevelAsync(getMetadata: true, cancellationToken: CancellationToken.None); return blobs.ToList(); } private async Task> EnumerateWorkStorageBlobsAsync() { - var blobs = await _workStorage.ListAsync(getMetadata: true, cancellationToken: CancellationToken.None); + var blobs = await _workStorage.ListTopLevelAsync(getMetadata: true, cancellationToken: CancellationToken.None); return blobs.ToList(); } @@ -311,7 +312,7 @@ private static bool BlobMetadataExists(StorageListItem sourceBlob, TotalStats to private static string GetBlobName(StorageListItem blob) { - var path = blob.Uri.AbsoluteUri; + var path = blob.Uri.GetComponents(UriComponents.Path, UriFormat.UriEscaped); var lastSlash = path.LastIndexOf('/'); if (lastSlash < 0) { From 4a4b0f16f36a5d5c23e6aa4928c7a411692dc501 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Mon, 25 Nov 2024 13:41:39 -0800 Subject: [PATCH 05/12] Has right .net sdk version now --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 4c1d7e5aaa..ce2e41208c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.0", + "version": "8.0.303", "rollForward": "latestFeature", "allowPrerelease": false } From b14c3fce7215154470fcc366f5b264d7227e0508 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Mon, 25 Nov 2024 13:42:55 -0800 Subject: [PATCH 06/12] Changed toplevel error --- src/NuGet.Services.Storage/AggregateStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NuGet.Services.Storage/AggregateStorage.cs b/src/NuGet.Services.Storage/AggregateStorage.cs index 788153f939..e7bf06e657 100644 --- a/src/NuGet.Services.Storage/AggregateStorage.cs +++ b/src/NuGet.Services.Storage/AggregateStorage.cs @@ -112,7 +112,7 @@ public override async Task> ListAsync(bool getMetad } public override async Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => - await ListAsync(getMetadata, cancellationToken); + await ListTopLevelAsync(getMetadata, cancellationToken); public override Task SetMetadataAsync(Uri resourceUri, IDictionary metadata) { From 97e310d1776f1756ef4b042dfd079321149da1f3 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Mon, 25 Nov 2024 13:44:50 -0800 Subject: [PATCH 07/12] Changed toplevel error pt 2 --- src/NuGet.Services.Storage/FileStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NuGet.Services.Storage/FileStorage.cs b/src/NuGet.Services.Storage/FileStorage.cs index f6f815dfe8..73dce3a41b 100644 --- a/src/NuGet.Services.Storage/FileStorage.cs +++ b/src/NuGet.Services.Storage/FileStorage.cs @@ -58,7 +58,7 @@ public override Task> ListAsync(bool getMetadata, C } public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => - ListAsync(getMetadata, cancellationToken); + ListTopLevelAsync(getMetadata, cancellationToken); public string Path { From 3d55f8306bcb666c67697bd50e1c0c25a7e65a79 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Mon, 25 Nov 2024 13:46:09 -0800 Subject: [PATCH 08/12] Changed toplevel error pt 3 --- .../BlobStorageVulnerabilityWriterFacts.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs b/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs index 0c4ec02aa6..f45a184924 100644 --- a/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs +++ b/tests/GitHubVulnerabilities2v3.Facts/BlobStorageVulnerabilityWriterFacts.cs @@ -167,7 +167,7 @@ public override Task> ListAsync(bool getMetadata, C public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) { - return _storage.ListAsync(getMetadata, cancellationToken); + return _storage.ListTopLevelAsync(getMetadata, cancellationToken); } public override Task SetMetadataAsync(Uri resourceUri, IDictionary metadata) From cbf5066a840dbfacbe3f2a288751a9685b2c91d7 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Fri, 13 Dec 2024 17:28:05 -0800 Subject: [PATCH 09/12] Bugfix --- src/NuGet.Services.Storage/AggregateStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NuGet.Services.Storage/AggregateStorage.cs b/src/NuGet.Services.Storage/AggregateStorage.cs index e7bf06e657..3bbf0f06dd 100644 --- a/src/NuGet.Services.Storage/AggregateStorage.cs +++ b/src/NuGet.Services.Storage/AggregateStorage.cs @@ -112,7 +112,7 @@ public override async Task> ListAsync(bool getMetad } public override async Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => - await ListTopLevelAsync(getMetadata, cancellationToken); + await _primaryStorage.ListTopLevelAsync(getMetadata, cancellationToken); public override Task SetMetadataAsync(Uri resourceUri, IDictionary metadata) { From bb807d0492e62c1f76c0293007da5b83310a6fc7 Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Fri, 13 Dec 2024 17:51:06 -0800 Subject: [PATCH 10/12] Bugfix2 --- src/NuGet.Services.Storage/FileStorage.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/NuGet.Services.Storage/FileStorage.cs b/src/NuGet.Services.Storage/FileStorage.cs index 73dce3a41b..ea724df432 100644 --- a/src/NuGet.Services.Storage/FileStorage.cs +++ b/src/NuGet.Services.Storage/FileStorage.cs @@ -57,8 +57,10 @@ public override Task> ListAsync(bool getMetadata, C return Task.FromResult>(List(getMetadata)); } - public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) => - ListTopLevelAsync(getMetadata, cancellationToken); + public override Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } public string Path { From 03e111cae88884e8cc2091cb1f69058c546c263d Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Fri, 13 Dec 2024 18:09:10 -0800 Subject: [PATCH 11/12] Added a comment --- src/NuGet.Services.Storage/IStorage.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/NuGet.Services.Storage/IStorage.cs b/src/NuGet.Services.Storage/IStorage.cs index cb8dd46fc2..f385939008 100644 --- a/src/NuGet.Services.Storage/IStorage.cs +++ b/src/NuGet.Services.Storage/IStorage.cs @@ -20,6 +20,12 @@ public interface IStorage Uri ResolveUri(string relativeUri); IEnumerable List(bool getMetadata); Task> ListAsync(bool getMetadata, CancellationToken cancellationToken); + + /// + /// Lists the top-level items in the storage. + /// Unlike , this method uses a delimiter to comply with new SDK requirements. + /// Without the trailing slash, the method would return an extra entry for the path itself. + /// Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken); Task CopyAsync( From 7693ca65b97ccda1b8fd94a9e1518276fda5626b Mon Sep 17 00:00:00 2001 From: Lanaparezanin Date: Mon, 16 Dec 2024 11:26:26 -0800 Subject: [PATCH 12/12] Clarified comment --- src/NuGet.Services.Storage/IStorage.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/NuGet.Services.Storage/IStorage.cs b/src/NuGet.Services.Storage/IStorage.cs index f385939008..6e00bceb2e 100644 --- a/src/NuGet.Services.Storage/IStorage.cs +++ b/src/NuGet.Services.Storage/IStorage.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -19,13 +20,11 @@ public interface IStorage Uri BaseAddress { get; } Uri ResolveUri(string relativeUri); IEnumerable List(bool getMetadata); + + //Lists all children of the storage(including the ones contained in subdirectories). Task> ListAsync(bool getMetadata, CancellationToken cancellationToken); - /// - /// Lists the top-level items in the storage. - /// Unlike , this method uses a delimiter to comply with new SDK requirements. - /// Without the trailing slash, the method would return an extra entry for the path itself. - /// + //Lists immediate children of the storage assuming directory-like structure Task> ListTopLevelAsync(bool getMetadata, CancellationToken cancellationToken); Task CopyAsync(