/// <summary> /// Moves a file from one location to another if the destination file does not already exist. /// </summary> /// <param name="sourceFile">The source file to move.</param> /// <param name="destinationFile">The destination where the source file will be moved.</param> protected void MoveFile(string sourceFile, string destinationFile) { if (!File.Exists(destinationFile)) { FileAccessRetrier.RetryOnMoveAccessFailure(() => File.Move(sourceFile, destinationFile)); Log?.LogMessage($"Moved '{sourceFile}' to '{destinationFile}'"); } }
private async Task UpdateAdvertisingManifestAsync(ManifestId manifestId, bool includePreviews) { string packagePath = null; string extractionPath = null; try { var adManifestPath = GetAdvertisingManifestPath(_sdkFeatureBand, manifestId); try { packagePath = await _nugetPackageDownloader.DownloadPackageAsync(GetManifestPackageId(_sdkFeatureBand, manifestId), includePreview : includePreviews); } catch (NuGetPackageNotFoundException) { _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestPackageDoesNotExist, manifestId)); } extractionPath = Path.Combine(_userHome, ".dotnet", "sdk-advertising-temp", $"{manifestId}-extracted"); Directory.CreateDirectory(extractionPath); var resultingFiles = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(extractionPath)); if (Directory.Exists(adManifestPath)) { Directory.Delete(adManifestPath, true); } Directory.CreateDirectory(Path.GetDirectoryName(adManifestPath)); FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(Path.Combine(extractionPath, "data"), adManifestPath)); _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestUpdated, manifestId)); } catch (Exception e) { _reporter.WriteLine(string.Format(LocalizableStrings.FailedAdManifestUpdate, manifestId, e.Message)); } finally { if (!string.IsNullOrEmpty(extractionPath) && Directory.Exists(extractionPath)) { Directory.Delete(extractionPath, true); } if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath)) { File.Delete(packagePath); } var versionDir = Path.GetDirectoryName(packagePath); if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any()) { Directory.Delete(versionDir); var idDir = Path.GetDirectoryName(versionDir); if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any()) { Directory.Delete(idDir); } } } }
public void Uninstall() { var rootDirectory = PackageDirectory.GetParentPath(); string tempPackageDirectory = null; TransactionalAction.Run( action: () => { try { if (Directory.Exists(PackageDirectory.Value)) { // Use the staging directory for uninstall // This prevents cross-device moves when temp is mounted to a different device var tempPath = _store.GetRandomStagingDirectory().Value; FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(PackageDirectory.Value, tempPath)); tempPackageDirectory = tempPath; } if (Directory.Exists(rootDirectory.Value) && !Directory.EnumerateFileSystemEntries(rootDirectory.Value).Any()) { Directory.Delete(rootDirectory.Value, false); } } catch (Exception ex) when(ex is UnauthorizedAccessException || ex is IOException) { throw new ToolPackageException( string.Format( CommonLocalizableStrings.FailedToUninstallToolPackage, Id, ex.Message), ex); } }, commit: () => { if (tempPackageDirectory != null) { Directory.Delete(tempPackageDirectory, true); } }, rollback: () => { if (tempPackageDirectory != null) { Directory.CreateDirectory(rootDirectory.Value); FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempPackageDirectory, PackageDirectory.Value)); } }); }
public static void CreateIfNotExists(this IFileSystem fileSystem, string filePath) { // retry if there is 2 CLI process trying to create file (for example sentinel file) // at the same time FileAccessRetrier.RetryOnIOException(() => { var parentDirectory = Path.GetDirectoryName(filePath); if (!fileSystem.File.Exists(filePath)) { if (!fileSystem.Directory.Exists(parentDirectory)) { fileSystem.Directory.CreateDirectory(parentDirectory); } fileSystem.File.CreateEmptyFile(filePath); } }); }
/// <summary> /// To make NuGet honor the user's NuGet config file. /// Copying instead of using the file directoy to avoid existing file being set higher permission /// Try to delete the existing NuGet config file in "/tmp/dotnet_sudo_home/" /// to avoid different user's NuGet config getting mixed. /// </summary> private static void CopyUserNuGetConfigToOverriddenHome(string homeBeforeOverride) { // https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Common/PathUtil/NuGetEnvironment.cs#L139 // home is cache in NuGet we cannot directly use the call var userSettingsDir = Path.Combine(homeBeforeOverride, ".nuget", "NuGet"); string userNuGetConfig = Settings.OrderedSettingsFileNames .Select(fileName => Path.Combine(userSettingsDir, fileName)) .FirstOrDefault(f => File.Exists(f)); var overridenSettingsDir = NuGetEnvironment.GetFolderPath(NuGetFolderPath.UserSettingsDirectory); var overridenNugetConfig = Path.Combine(overridenSettingsDir, Settings.DefaultSettingsFileName); if (File.Exists(overridenNugetConfig)) { try { FileAccessRetrier.RetryOnIOException( () => File.Delete(overridenNugetConfig)); } catch { // best effort to remove } } if (userNuGetConfig != default) { try { FileAccessRetrier.RetryOnIOException( () => File.Copy(userNuGetConfig, overridenNugetConfig, overwrite: true)); } catch { // best effort to copy } } }
public void RemoveShim(ToolCommandName commandName) { var files = new Dictionary <string, string>(); TransactionalAction.Run( action: () => { try { foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value))) { var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(file.Value, tempPath)); files[file.Value] = tempPath; } } catch (Exception ex) when(ex is UnauthorizedAccessException || ex is IOException) { throw new ShellShimException( string.Format( CommonLocalizableStrings.FailedToRemoveShellShim, commandName.ToString(), ex.Message ), ex); } }, commit: () => { foreach (var value in files.Values) { _fileSystem.File.Delete(value); } }, rollback: () => { foreach (var kvp in files) { FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(kvp.Value, kvp.Key)); } }); }
public IToolPackage InstallPackage( PackageLocation packageLocation, PackageId packageId, VersionRange versionRange = null, string targetFramework = null, string verbosity = null) { var packageRootDirectory = _store.GetRootPackageDirectory(packageId); string rollbackDirectory = null; return(TransactionalAction.Run <IToolPackage>( action: () => { try { var stageDirectory = _store.GetRandomStagingDirectory(); Directory.CreateDirectory(stageDirectory.Value); rollbackDirectory = stageDirectory.Value; var tempProject = CreateTempProject( packageId: packageId, versionRange: versionRange, targetFramework: targetFramework ?? BundledTargetFramework.GetTargetFrameworkMoniker(), restoreDirectory: stageDirectory, assetJsonOutputDirectory: stageDirectory, rootConfigDirectory: packageLocation.RootConfigDirectory, additionalFeeds: packageLocation.AdditionalFeeds); try { _projectRestorer.Restore( tempProject, packageLocation, verbosity: verbosity); } finally { File.Delete(tempProject.Value); } var version = _store.GetStagedPackageVersion(stageDirectory, packageId); var packageDirectory = _store.GetPackageDirectory(packageId, version); if (Directory.Exists(packageDirectory.Value)) { throw new ToolPackageException( string.Format( CommonLocalizableStrings.ToolPackageConflictPackageId, packageId, version.ToNormalizedString())); } Directory.CreateDirectory(packageRootDirectory.Value); FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(stageDirectory.Value, packageDirectory.Value)); rollbackDirectory = packageDirectory.Value; return new ToolPackageInstance(packageId, version, packageDirectory); } catch (Exception ex) when(ex is UnauthorizedAccessException || ex is IOException) { throw new ToolPackageException( string.Format( CommonLocalizableStrings.FailedToInstallToolPackage, packageId, ex.Message), ex); } }, rollback: () => { if (!string.IsNullOrEmpty(rollbackDirectory) && Directory.Exists(rollbackDirectory)) { Directory.Delete(rollbackDirectory, true); } // Delete the root if it is empty if (Directory.Exists(packageRootDirectory.Value) && !Directory.EnumerateFileSystemEntries(packageRootDirectory.Value).Any()) { Directory.Delete(packageRootDirectory.Value, false); } })); }
public void InstallWorkloadPack(PackInfo packInfo, SdkFeatureBand sdkFeatureBand, DirectoryPath?offlineCache = null) { _reporter.WriteLine(string.Format(LocalizableStrings.InstallingPackVersionMessage, packInfo.Id, packInfo.Version)); var tempDirsToDelete = new List <string>(); var tempFilesToDelete = new List <string>(); try { TransactionalAction.Run( action: () => { if (!PackIsInstalled(packInfo)) { string packagePath; if (offlineCache == null || !offlineCache.HasValue) { packagePath = _nugetPackageDownloader .DownloadPackageAsync(new PackageId(packInfo.ResolvedPackageId), new NuGetVersion(packInfo.Version), _packageSourceLocation).GetAwaiter().GetResult(); tempFilesToDelete.Add(packagePath); } else { _reporter.WriteLine(string.Format(LocalizableStrings.UsingCacheForPackInstall, packInfo.Id, packInfo.Version, offlineCache)); packagePath = Path.Combine(offlineCache.Value.Value, $"{packInfo.ResolvedPackageId}.{packInfo.Version}.nupkg"); if (!File.Exists(packagePath)) { throw new Exception(string.Format(LocalizableStrings.CacheMissingPackage, packInfo.ResolvedPackageId, packInfo.Version, offlineCache)); } } if (!Directory.Exists(Path.GetDirectoryName(packInfo.Path))) { Directory.CreateDirectory(Path.GetDirectoryName(packInfo.Path)); } if (IsSingleFilePack(packInfo)) { File.Copy(packagePath, packInfo.Path); } else { var tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{packInfo.Id}-{packInfo.Version}-extracted"); tempDirsToDelete.Add(tempExtractionDir); Directory.CreateDirectory(tempExtractionDir); var packFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(tempExtractionDir)).GetAwaiter().GetResult(); FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(tempExtractionDir, packInfo.Path)); } } else { _reporter.WriteLine(string.Format(LocalizableStrings.WorkloadPackAlreadyInstalledMessage, packInfo.Id, packInfo.Version)); } WritePackInstallationRecord(packInfo, sdkFeatureBand); }, rollback: () => { try { _reporter.WriteLine(string.Format(LocalizableStrings.RollingBackPackInstall, packInfo.Id)); RollBackWorkloadPackInstall(packInfo, sdkFeatureBand, offlineCache); } catch (Exception e) { // Don't hide the original error if roll back fails _reporter.WriteLine(string.Format(LocalizableStrings.RollBackFailedMessage, e.Message)); } }); } finally { // Delete leftover dirs and files foreach (var file in tempFilesToDelete) { if (File.Exists(file)) { File.Delete(file); } } foreach (var dir in tempDirsToDelete) { if (Directory.Exists(dir)) { Directory.Delete(dir, true); } } } }
public void InstallWorkloadManifest(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand, DirectoryPath?offlineCache = null, bool isRollback = false) { string packagePath = null; string tempExtractionDir = null; string tempBackupDir = null; string rootInstallDir = WorkloadFileBasedInstall.IsUserLocal(_dotnetDir, sdkFeatureBand.ToString()) ? _userProfileDir : _dotnetDir; var manifestPath = Path.Combine(rootInstallDir, "sdk-manifests", sdkFeatureBand.ToString(), manifestId.ToString()); _reporter.WriteLine(string.Format(LocalizableStrings.InstallingWorkloadManifest, manifestId, manifestVersion)); try { TransactionalAction.Run( action: () => { if (offlineCache == null || !offlineCache.HasValue) { packagePath = _nugetPackageDownloader.DownloadPackageAsync(WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId), new NuGetVersion(manifestVersion.ToString()), _packageSourceLocation).GetAwaiter().GetResult(); } else { packagePath = Path.Combine(offlineCache.Value.Value, $"{WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId)}.{manifestVersion}.nupkg"); if (!File.Exists(packagePath)) { throw new Exception(string.Format(LocalizableStrings.CacheMissingPackage, WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId), manifestVersion, offlineCache)); } } tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-extracted"); Directory.CreateDirectory(tempExtractionDir); var manifestFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(tempExtractionDir)).GetAwaiter().GetResult(); if (Directory.Exists(manifestPath) && Directory.GetFileSystemEntries(manifestPath).Any()) { // Backup existing manifest data for roll back purposes tempBackupDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-backup"); if (Directory.Exists(tempBackupDir)) { Directory.Delete(tempBackupDir, true); } FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(manifestPath, tempBackupDir)); } Directory.CreateDirectory(Path.GetDirectoryName(manifestPath)); FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(Path.Combine(tempExtractionDir, "data"), manifestPath)); }, rollback: () => { if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir)) { FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(tempBackupDir, manifestPath)); } }); // Delete leftover dirs and files if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath) && (offlineCache == null || !offlineCache.HasValue)) { File.Delete(packagePath); } var versionDir = Path.GetDirectoryName(packagePath); if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any()) { Directory.Delete(versionDir); var idDir = Path.GetDirectoryName(versionDir); if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any()) { Directory.Delete(idDir); } } if (!string.IsNullOrEmpty(tempExtractionDir) && Directory.Exists(tempExtractionDir)) { Directory.Delete(tempExtractionDir, true); } if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir)) { Directory.Delete(tempBackupDir, true); } } catch (Exception e) { throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadManifest, manifestId, manifestVersion, e.Message)); } }
private async Task UpdateAdvertisingManifestAsync(ManifestId manifestId, bool includePreviews, DirectoryPath?offlineCache = null) { string packagePath = null; string extractionPath = null; try { var adManifestPath = GetAdvertisingManifestPath(_sdkFeatureBand, manifestId); if (offlineCache == null || !offlineCache.HasValue) { try { packagePath = await _nugetPackageDownloader.DownloadPackageAsync( GetManifestPackageId(_sdkFeatureBand, manifestId), packageSourceLocation : _packageSourceLocation, includePreview : includePreviews); } catch (NuGetPackageNotFoundException) { _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestPackageDoesNotExist, manifestId)); } } else { packagePath = Directory.GetFiles(offlineCache.Value.Value) .Where(path => path.EndsWith(".nupkg")) .Where(path => Path.GetFileName(path).StartsWith(GetManifestPackageId(_sdkFeatureBand, manifestId).ToString())) .Max(); if (!File.Exists(packagePath)) { throw new Exception(string.Format(LocalizableStrings.CacheMissingPackage, GetManifestPackageId(_sdkFeatureBand, manifestId), "*", offlineCache)); } } extractionPath = Path.Combine(_tempDirPath, "dotnet-sdk-advertising-temp", $"{manifestId}-extracted"); Directory.CreateDirectory(extractionPath); var resultingFiles = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(extractionPath)); if (Directory.Exists(adManifestPath)) { Directory.Delete(adManifestPath, true); } Directory.CreateDirectory(Path.GetDirectoryName(adManifestPath)); FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(Path.Combine(extractionPath, "data"), adManifestPath)); _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestUpdated, manifestId)); } catch (Exception e) { _reporter.WriteLine(string.Format(LocalizableStrings.FailedAdManifestUpdate, manifestId, e.Message)); } finally { if (!string.IsNullOrEmpty(extractionPath) && Directory.Exists(extractionPath)) { Directory.Delete(extractionPath, true); } if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath) && (offlineCache == null || !offlineCache.HasValue)) { File.Delete(packagePath); } var versionDir = Path.GetDirectoryName(packagePath); if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any()) { Directory.Delete(versionDir); var idDir = Path.GetDirectoryName(versionDir); if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any()) { Directory.Delete(idDir); } } } }
public void InstallWorkloadPack(PackInfo packInfo, SdkFeatureBand sdkFeatureBand, bool useOfflineCache = false) { if (useOfflineCache) { throw new NotImplementedException(); } _reporter.WriteLine(string.Format(LocalizableStrings.InstallingPackVersionMessage, packInfo.Id, packInfo.Version)); var tempDirsToDelete = new List <string>(); var tempFilesToDelete = new List <string>(); try { TransactionalAction.Run( action: () => { if (!PackIsInstalled(packInfo)) { var packagePath = _nugetPackageInstaller.DownloadPackageAsync(new PackageId(packInfo.Id), new NuGetVersion(packInfo.Version)).Result; tempFilesToDelete.Add(packagePath); if (!Directory.Exists(Path.GetDirectoryName(packInfo.Path))) { Directory.CreateDirectory(Path.GetDirectoryName(packInfo.Path)); } if (IsSingleFilePack(packInfo)) { File.Copy(packagePath, packInfo.Path); } else { var tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{packInfo.Id}-{packInfo.Version}-extracted"); tempDirsToDelete.Add(tempExtractionDir); Directory.CreateDirectory(tempExtractionDir); var packFiles = _nugetPackageInstaller.ExtractPackageAsync(packagePath, tempExtractionDir).Result; FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempExtractionDir, packInfo.Path)); } } else { _reporter.WriteLine(string.Format(LocalizableStrings.WorkloadPackAlreadyInstalledMessage, packInfo.Id, packInfo.Version)); } WritePackInstallationRecord(packInfo, sdkFeatureBand); }, rollback: () => { RollBackWorkloadPackInstall(packInfo, sdkFeatureBand); }); } finally { // Delete leftover dirs and files foreach (var file in tempFilesToDelete) { if (File.Exists(file)) { File.Delete(file); } } foreach (var dir in tempDirsToDelete) { if (Directory.Exists(dir)) { Directory.Delete(dir, true); } } } }
private async Task UpdateAdvertisingManifestAsync(WorkloadManifestInfo manifest, bool includePreviews, DirectoryPath?offlineCache = null) { string packagePath = null; string extractionPath = null; var manifestId = new ManifestId(manifest.Id); string currentFeatureBand = _sdkFeatureBand.ToString(); try { var adManifestPath = GetAdvertisingManifestPath(_sdkFeatureBand, manifestId); bool success; (success, packagePath) = await GetManifestPackageUpdate(_sdkFeatureBand, manifestId, includePreviews, offlineCache); if (!success) { if (!(manifest.ManifestFeatureBand).Equals(_sdkFeatureBand)) { (success, packagePath) = await GetManifestPackageUpdate(new SdkFeatureBand(manifest.ManifestFeatureBand), manifestId, includePreviews, offlineCache); currentFeatureBand = manifest.ManifestFeatureBand.ToString(); } } if (!success) { _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestPackageDoesNotExist, manifestId)); return; } extractionPath = Path.Combine(_tempDirPath, "dotnet-sdk-advertising-temp", $"{manifestId}-extracted"); Directory.CreateDirectory(extractionPath); var resultingFiles = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(extractionPath)); if (Directory.Exists(adManifestPath)) { Directory.Delete(adManifestPath, true); } Directory.CreateDirectory(Path.GetDirectoryName(adManifestPath)); FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(Path.Combine(extractionPath, "data"), adManifestPath)); // add file that contains the advertisted manifest feature band so GetAdvertisingManifestVersionAndWorkloads will use correct feature band, regardless of if rollback occurred or not File.WriteAllText(Path.Combine(adManifestPath, "AdvertisedManifestFeatureBand.txt"), currentFeatureBand); if (_displayManifestUpdates) { _reporter.WriteLine(string.Format(LocalizableStrings.AdManifestUpdated, manifestId)); } } catch (Exception e) { _reporter.WriteLine(string.Format(LocalizableStrings.FailedAdManifestUpdate, manifestId, e.Message)); } finally { if (!string.IsNullOrEmpty(extractionPath) && Directory.Exists(extractionPath)) { Directory.Delete(extractionPath, true); } if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath) && (offlineCache == null || !offlineCache.HasValue)) { File.Delete(packagePath); } if (!string.IsNullOrEmpty(packagePath) && (offlineCache == null || !offlineCache.HasValue)) { var versionDir = Path.GetDirectoryName(packagePath); if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any()) { Directory.Delete(versionDir); var idDir = Path.GetDirectoryName(versionDir); if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any()) { Directory.Delete(idDir); } } } } }
public void InstallWorkloadManifest(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand) { string packagePath = null; string tempExtractionDir = null; string tempBackupDir = null; var manifestPath = Path.Combine(_dotnetDir, "sdk-manifests", sdkFeatureBand.ToString(), manifestId.ToString()); _reporter.WriteLine(string.Format(LocalizableStrings.InstallingWorkloadManifest, manifestId, manifestVersion)); try { TransactionalAction.Run( action: () => { packagePath = _nugetPackageDownloader.DownloadPackageAsync(WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId), new NuGetVersion(manifestVersion.ToString())).Result; tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-extracted"); Directory.CreateDirectory(tempExtractionDir); var manifestFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(tempExtractionDir)).Result; if (Directory.Exists(manifestPath) && Directory.GetFileSystemEntries(manifestPath).Any()) { // Backup existing manifest data for roll back purposes tempBackupDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-backup"); if (Directory.Exists(tempBackupDir)) { Directory.Delete(tempBackupDir, true); } FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(manifestPath, tempBackupDir)); } Directory.CreateDirectory(Path.GetDirectoryName(manifestPath)); FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(Path.Combine(tempExtractionDir, "data"), manifestPath)); }, rollback: () => { if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir)) { FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempBackupDir, manifestPath)); } }); // Delete leftover dirs and files if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath)) { File.Delete(packagePath); } var versionDir = Path.GetDirectoryName(packagePath); if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any()) { Directory.Delete(versionDir); var idDir = Path.GetDirectoryName(versionDir); if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any()) { Directory.Delete(idDir); } } if (!string.IsNullOrEmpty(tempExtractionDir) && Directory.Exists(tempExtractionDir)) { Directory.Delete(tempExtractionDir, true); } if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir)) { Directory.Delete(tempBackupDir, true); } } catch (Exception e) { throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadManifest, manifestId, manifestVersion, e.Message)); } }