public void Install(RunningDeployment deployment)
        {
            if (deployment.Variables.GetFlag(SpecialVariables.Action.Azure.CloudServicePackageExtractionDisabled, false))
                return;

            Log.Verbose("Re-packaging cspkg.");
            var workingDirectory = deployment.CurrentDirectory;
            var originalPackagePath = deployment.Variables.Get(SpecialVariables.Action.Azure.CloudServicePackagePath);
            var newPackagePath = Path.Combine(Path.GetDirectoryName(originalPackagePath), Path.GetFileNameWithoutExtension(originalPackagePath) + "_repacked.cspkg");
            using (var originalPackage = Package.Open(originalPackagePath, FileMode.Open))
            using (var newPackage = Package.Open(newPackagePath, FileMode.CreateNew))
            {
                var originalManifest = AzureCloudServiceConventions.ReadPackageManifest(originalPackage);

                var newManifest = new PackageDefinition
                {
                    MetaData = {AzureVersion = originalManifest.MetaData.AzureVersion}
                };

                AddParts(newPackage, newManifest, Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.ServiceDefinition), 
                    AzureCloudServiceConventions.PackageFolders.ServiceDefinition);
                AddParts(newPackage, newManifest, Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.NamedStreams), 
                    AzureCloudServiceConventions.PackageFolders.NamedStreams);
                AddLocalContent(newPackage, newManifest, workingDirectory);

                AddPackageManifest(newPackage, newManifest);

                newPackage.Flush();
            }

            fileSystem.OverwriteAndDelete(originalPackagePath, newPackagePath);
        }
        void ExtractLayouts(Package package, PackageDefinition manifest, string workingDirectory)
        {
            var localContentDirectory = Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.LocalContent);
            fileSystem.EnsureDirectoryExists(localContentDirectory);

            foreach (var layout in manifest.Layouts)
            {
                if (!layout.Name.StartsWith(AzureCloudServiceConventions.RoleLayoutPrefix))
                    continue;

                var layoutDirectory = Path.Combine(localContentDirectory, layout.Name.Substring(AzureCloudServiceConventions.RoleLayoutPrefix.Length));
                fileSystem.EnsureDirectoryExists(layoutDirectory);

                foreach (var fileDefinition in layout.FileDefinitions)
                {
                    var contentDefinition =
                        manifest.GetContentDefinition(fileDefinition.Description.DataContentReference);

                    var destinationFileName = Path.Combine(layoutDirectory, fileDefinition.FilePath.TrimStart('\\'));
                    ExtractPart(
                        package.GetPart(PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative),
                            contentDefinition.Description.DataStorePath)),
                        destinationFileName);
                }
            }
        }
 void ExtractContents(Package package, PackageDefinition manifest, string contentNamePrefix, string workingDirectory)
 {
     foreach (var namedStreamsContent in manifest.Contents.Where(x => x.Name.StartsWith(contentNamePrefix)))
     {
         var destinationFileName = Path.Combine(workingDirectory, ConvertToWindowsPath(namedStreamsContent.Description.DataStorePath.ToString()).TrimStart('\\'));
         ExtractPart(package.GetPart(PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), namedStreamsContent.Description.DataStorePath)),
             destinationFileName);
     }
 }
 void AddLocalContent(Package package, PackageDefinition manifest, string workingDirectory)
 {
     foreach (var roleDirectory in fileSystem.EnumerateDirectories(Path.Combine(workingDirectory, "LocalContent")))
     {
         var layout = new LayoutDefinition {Name = "Roles/" + new DirectoryInfo(roleDirectory).Name};
         manifest.Layouts.Add(layout);
         AddLocalContentParts(package, manifest, layout, roleDirectory, "");
     }
 }
        void AddPackageManifest(Package package, PackageDefinition manifest)
        {
            var manifestPartUri = PackUriHelper.CreatePartUri(new Uri("/package.xml", UriKind.Relative));
            var manifestPart = package.CreatePart(manifestPartUri, System.Net.Mime.MediaTypeNames.Application.Octet, CompressionOption.Maximum);
            using (var manifestPartStream = manifestPart.GetStream())
            {
                manifest.ToXml().Save(manifestPartStream);
            }

            package.CreateRelationship(manifestPartUri, TargetMode.External, AzureCloudServiceConventions.CtpFormatPackageDefinitionRelationshipType);
        }
        public void ShouldProduceValidManifestXml()
        {
            var manifest = new PackageDefinition {MetaData = {AzureVersion = "2.6"}};
            manifest.Contents.Add(
                new ContentDefinition
                {
                    Name = "ServiceDefinition/ServiceDefinition.csdef",
                    Description = new ContentDescription
                    {
                        LengthInBytes = 688,
                        HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256,
                        Hash = "NMkHuVQbi+g+ny+kvjiunBgt8rLQT8Jd9FGJvWsRtZE=",
                        DataStorePath = new Uri("ServiceDefinition/ServiceDefinition.csdef", UriKind.Relative)
                    }
                });
            manifest.Contents.Add(
            new ContentDefinition
            {
                Name = "LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd",
                Description = new ContentDescription
                {
                    LengthInBytes = 19469,
                    HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256,
                    Hash = "UK4lyWPyRI6I8WNzlVP2dtiFZj+kjMIjyGieq5b4TiE=", 
                    DataStorePath = new Uri("LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd", UriKind.Relative)
                } 
            });

            var workerRoleLayout = new LayoutDefinition {Name = "Roles/WorkerRole1"};
            workerRoleLayout.FileDefinitions.Add(new FileDefinition
            {
                FilePath = "\\Cloud.uar.csman",
                Description =
                    new FileDescription
                    {
                        DataContentReference = "LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd",
                        Created = DateTime.UtcNow,
                        Modified = DateTime.UtcNow
                    }
            });
            manifest.Layouts.Add(workerRoleLayout);

            var manifestXml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
            manifestXml.Add(manifest.ToXml());

            var schemaSet = new XmlSchemaSet();
            schemaSet.Add(null, XmlReader.Create(new StringReader(GetPackageManifestSchema()), XmlUtils.DtdSafeReaderSettings));
            manifestXml.Validate(schemaSet, (o, e) =>
            {
                Assert.Fail("Xml failed to validate: " + e.Message);
            });
        }
        void AddParts(Package package, PackageDefinition manifest, string directory, string baseDataStorePath)
        {
            foreach (var file in fileSystem.EnumerateFiles(directory))
            {
                var partUri = new Uri(baseDataStorePath + "/" + Path.GetFileName(file), UriKind.Relative);
                AddContent(package, manifest, partUri, file);
            }

            foreach (var subDirectory in fileSystem.EnumerateDirectories(directory).Select(x => new DirectoryInfo(x)))
            {
               AddParts(package, manifest, subDirectory.FullName, baseDataStorePath + "/" + subDirectory.Name); 
            }
        }
        void AddLocalContentParts(Package package, PackageDefinition manifest, LayoutDefinition layout, string baseDirectory, string relativeDirectory)
        {
            var currentDirectory = Path.Combine(baseDirectory, relativeDirectory);

            foreach (var file in fileSystem.EnumerateFiles(currentDirectory)) 
            {
                var uniqueFileName = Guid.NewGuid().ToString("N");
                var partUri = new Uri("LocalContent/" + uniqueFileName, UriKind.Relative);
                AddContent(package, manifest, partUri, file);
                
                //add file definition
                var fileDate = DateTime.UtcNow; //todo: use original timestamps if un-modified
                layout.FileDefinitions.Add(
                    new FileDefinition
                    {
                        FilePath = "\\" + Path.Combine(relativeDirectory, Path.GetFileName(file)),
                        Description =
                            new FileDescription
                            {
                                DataContentReference = partUri.ToString(),
                                ReadOnly = false,
                                Created = fileDate,
                                Modified = fileDate
                            }
                    });
            }

            foreach (var subDirectory in Directory.GetDirectories(currentDirectory).Select(x => new DirectoryInfo(x)))
            {
               AddLocalContentParts(package, manifest, layout, baseDirectory, Path.Combine(relativeDirectory, subDirectory.Name)); 
            }
        }
        void AddContent(Package package, PackageDefinition manifest, Uri partUri, string file)
        {
                var part =
                    package.CreatePart(
                        PackUriHelper.CreatePartUri(partUri), System.Net.Mime.MediaTypeNames.Application.Octet, CompressionOption.Maximum);

                using (var partStream = part.GetStream())
                using (var fileStream = fileSystem.OpenFile(file, FileMode.Open))
                {
                    fileStream.CopyTo(partStream);
                    partStream.Flush();
                    fileStream.Position = 0;
                    var hashAlgorithm = new SHA256Managed();
                    hashAlgorithm.ComputeHash(fileStream);
                    manifest.Contents.Add(new ContentDefinition
                    {
                        Name = partUri.ToString(),
                        Description =
                            new ContentDescription
                            {
                                DataStorePath = partUri,
                                LengthInBytes = (int) fileStream.Length,
                                HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256,
                                Hash = Convert.ToBase64String(hashAlgorithm.Hash)
                            }
                    });
                }
        }