Skip to content

Commit

Permalink
Merge pull request #74 from stewart-r/path-property-pr
Browse files Browse the repository at this point in the history
Proposed Fix for #57
  • Loading branch information
isaacabraham authored Jun 23, 2016
2 parents beb09ed + cdd95a2 commit e9fb9f0
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 22 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,6 @@ nuget/*.nupkg

.paket/paket.exe
paket-files/

#Fake build files
.fake
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ let rec private createBlobItem (domainType : ProvidedTypeDefinition) connectionS
let fileTypeDefinition =
match properties.BlobType, path with
| BlobType.PageBlob, _ -> "PageBlob"
| _, ContainerBuilder.XML -> "XmlBlob"
| _, ContainerBuilder.Binary | _, ContainerBuilder.Text -> "BlockBlob"
| _, BlobBuilder.XML -> "XmlBlob"
| _, BlobBuilder.Binary | _, BlobBuilder.Text -> "BlockBlob"
|> fun typeName -> domainType.GetMember(typeName).[0] :?> ProvidedTypeDefinition

match properties.BlobType, properties.Length with
| _, 0L -> None
| BlobType.PageBlob, _ -> Some <| ProvidedProperty(name, fileTypeDefinition, GetterCode = fun _ -> <@@ ContainerBuilder.createPageBlobFile connectionString containerName path @@>)
| BlobType.BlockBlob, _ -> Some <| ProvidedProperty(name, fileTypeDefinition, GetterCode = fun _ -> <@@ ContainerBuilder.createBlockBlobFile connectionString containerName path @@>)
| BlobType.PageBlob, _ -> Some <| ProvidedProperty(name, fileTypeDefinition, GetterCode = fun _ -> <@@ BlobBuilder.createPageBlobFile connectionString containerName path @@>)
| BlobType.BlockBlob, _ -> Some <| ProvidedProperty(name, fileTypeDefinition, GetterCode = fun _ -> <@@ BlobBuilder.createBlockBlobFile connectionString containerName path @@>)
| _ -> None

let private createContainerType (domainType : ProvidedTypeDefinition) connectionString (container : LightweightContainer) =
Expand Down
11 changes: 11 additions & 0 deletions src/FSharp.Azure.StorageTypeProvider/Blob/BlobRepository.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ let rec private getContainerStructure wildcard (container : CloudBlobContainer)
| _ -> None)
|> Seq.toArray

let listBlobs incSubDirs (container:CloudBlobContainer) prefix =
container.ListBlobs(prefix, incSubDirs)
|> Seq.map(fun b ->
match b with
| :? ICloudBlob as blob ->
let path, name = getItemName blob.Name blob.Parent
Some(Blob(path, name, blob.Properties))
| _ -> None) //can safely ignore folder types as we have a flat structure if & only if we want to include items from sub directories
|> Seq.filter(fun b -> b.IsSome)
|> Seq.map(fun b -> b.Value)

let getBlobStorageAccountManifest connection =
(getBlobClient connection).ListContainers()
|> Seq.toList
Expand Down
58 changes: 42 additions & 16 deletions src/FSharp.Azure.StorageTypeProvider/Blob/ProvidedBlobTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,55 @@ type XmlFile internal (defaultConnectionString, container, file) =
return XDocument.Parse text
}

module BlobBuilder =
let internal (|Text|Binary|XML|) (name : string) =
let endsWith extension = name.EndsWith(extension, StringComparison.InvariantCultureIgnoreCase)
match name with
| _ when [ ".txt"; ".csv" ] |> Seq.exists endsWith -> Text
| _ when endsWith ".xml" -> XML
| _ -> Binary

/// Creates a block blob file object.
let createBlockBlobFile connectionString containerName path =
let details = connectionString, containerName, path
match path with
| XML -> XmlFile(details) :> BlockBlobFile
| Text | Binary -> BlockBlobFile(details)

/// Creates a page blob file object.
let createPageBlobFile connectionString containerName path =
PageBlobFile(connectionString, containerName, path)

/// Represents a pseudo-folder in blob storage.
type BlobFolder internal (defaultConnectionString, container, file) =
/// Downloads the entire folder contents to the local file system asynchronously.
member __.Download(path, ?connectionString) =
let connectionDetails = defaultArg connectionString defaultConnectionString, container, file
downloadFolder (connectionDetails, path)

/// The Path of the current folder
member __.Path =
file

/// Lists all blobs contained in this folder
member __.ListBlobs(?includeBlobsInSubFolders) =
let incSubFolders = defaultArg includeBlobsInSubFolders false
let container = getContainerRef (defaultConnectionString,container)
listBlobs incSubFolders container file
|> Seq.map (fun b ->
match b with
| Blob(path, name, properties) ->
match properties.BlobType with
| BlobType.PageBlob ->
(BlobBuilder.createPageBlobFile defaultConnectionString container.Name path) :> BlobFile
| _ ->
(BlobBuilder.createBlockBlobFile defaultConnectionString container.Name path) :> BlobFile
|> Some
| _ -> None)
|> Seq.filter(fun x -> x.IsSome)
|> Seq.map(fun x -> x.Value)


/// Represents a container in blob storage.
type BlobContainer internal (defaultConnectionString, container) =
/// Gets a handle to the Azure SDK client for this container.
Expand All @@ -127,23 +169,7 @@ module internal ProvidedTypeGenerator =
/// Builder methods to construct blobs etc..
/// [omit]
module ContainerBuilder =
let internal (|Text|Binary|XML|) (name : string) =
let endsWith extension = name.EndsWith(extension, StringComparison.InvariantCultureIgnoreCase)
match name with
| _ when [ ".txt"; ".csv" ] |> Seq.exists endsWith -> Text
| _ when endsWith ".xml" -> XML
| _ -> Binary

/// Creates a block blob file object.
let createBlockBlobFile connectionString containerName path =
let details = connectionString, containerName, path
match path with
| XML -> XmlFile(details) :> BlockBlobFile
| Text | Binary -> BlockBlobFile(details)

/// Creates a page blob file object.
let createPageBlobFile connectionString containerName path =
PageBlobFile(connectionString, containerName, path)

/// Creates a blob container object.
let createContainer connectionString containerName = BlobContainer(connectionString, containerName)
Expand Down
21 changes: 20 additions & 1 deletion tests/IntegrationTests/BlobUnitTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,23 @@ let testFolderDownload download expectedFiles expectedFolders =
let ``Can correctly download a folder``() = testFolderDownload container.``folder/``.Download 2 0

[<Fact>]
let ``Can correctly download a container``() = testFolderDownload container.Download 8 1
let ``Can correctly download a container``() = testFolderDownload container.Download 12 5

[<Fact>]
let ``Can access Path property on a folder`` =
let childFolder = Local.Containers.samples.``folder2/``.``child/``
Assert.Equal<string>("folder2/child/", childFolder.Path)

[<Fact>]
let ``ListBlobs method returns correct number of blobs`` =
let childFolder = Local.Containers.samples.``folder2/``.``child/``
let allBlobs = childFolder.ListBlobs()
let count = allBlobs |> Seq.length
Assert.Equal(1,count)

[<Fact>]
let ``Can access List blobs method on a folder`` =
let childFolder = Local.Containers.samples.``folder2/``.``child/``
let allBlobs = childFolder.ListBlobs(true)
let count = allBlobs |> Seq.length
Assert.Equal(4,count)
7 changes: 6 additions & 1 deletion tests/IntegrationTests/ResetTestData.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ let createData _ =
createBlockBlob "folder/childFile.txt" "child file stuff"
createBlockBlob "sample.txt" "the quick brown fox jumps over the lazy dog\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Cras malesuada.\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla porttitor."
createBlockBlob "data.xml" "<data><items><item>thing</item></items></data>"
createBlockBlob "folder2/child/grandchild1/descedant1.txt" "not important"
createBlockBlob "folder2/child/grandchild1/descedant2.txt" "not important"
createBlockBlob "folder2/child/grandchild2/descedant3.txt" "not important"
createBlockBlob "folder2/child/descedant4.txt" "not important"
createBlockBlob "folder/pageDataChild.txt" "hello from child page blob"
createPageBlob "pageData.bin" "hello from page blob"
createPageBlob "folder/pageDataChild.txt" "hello from child page blob"


createData |> logWith "blob"

Expand Down

0 comments on commit e9fb9f0

Please sign in to comment.