/// <summary> /// Expands the files property for each library /// </summary> /// <param name="libraries"></param> /// <param name="dependencies"></param> /// <param name="defaultDestination"></param> /// <param name="defaultProvider"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private static async Task <IEnumerable <ILibraryOperationResult> > ExpandLibrariesAsync( IEnumerable <ILibraryInstallationState> libraries, IDependencies dependencies, string defaultDestination, string defaultProvider, CancellationToken cancellationToken) { List <ILibraryOperationResult> expandedLibraries = new List <ILibraryOperationResult>(); foreach (ILibraryInstallationState library in libraries) { cancellationToken.ThrowIfCancellationRequested(); string installDestination = string.IsNullOrEmpty(library.DestinationPath) ? defaultDestination : library.DestinationPath; string providerId = string.IsNullOrEmpty(library.ProviderId) ? defaultProvider : library.ProviderId; IProvider provider = dependencies.GetProvider(providerId); if (provider == null) { return(new[] { LibraryOperationResult.FromError(PredefinedErrors.ProviderIsUndefined()) }); } ILibraryOperationResult desiredState = await provider.UpdateStateAsync(library, cancellationToken); if (!desiredState.Success) { return(new[] { desiredState }); } expandedLibraries.Add(desiredState); } return(expandedLibraries); }
public void VsTextViewCreated(IVsTextView textViewAdapter) { IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); if (!DocumentService.TryGetTextDocument(textView.TextBuffer, out ITextDocument doc)) { return; } string fileName = Path.GetFileName(doc.FilePath); if (!fileName.Equals(Constants.ConfigFileName, StringComparison.OrdinalIgnoreCase)) { return; } new CompletionController(textViewAdapter, textView, CompletionBroker); _dependencies = Dependencies.FromConfigFile(doc.FilePath); _manifest = Manifest.FromFileAsync(doc.FilePath, _dependencies, CancellationToken.None).Result; _manifestPath = doc.FilePath; _project = VsHelpers.GetDTEProjectFromConfig(_manifestPath); if (_manifest == null) { AddErrorToList(PredefinedErrors.ManifestMalformed()); } doc.FileActionOccurred += OnFileSaved; textView.Closed += OnViewClosed; }
protected async Task <Manifest> CreateManifestAsync(string defaultProvider, string defaultDestination, EnvironmentSettings settings, CancellationToken cancellationToken) { if (File.Exists(Settings.ManifestFileName)) { throw new InvalidOperationException(Resources.Text.InitFailedLibmanJsonFileExists); } Manifest manifest = await Manifest.FromFileAsync(Settings.ManifestFileName, ManifestDependencies, cancellationToken); manifest.AddVersion(Manifest.SupportedVersions.Last().ToString()); manifest.DefaultDestination = string.IsNullOrEmpty(defaultDestination) ? null : defaultDestination; defaultProvider = string.IsNullOrEmpty(defaultProvider) ? HostEnvironment.InputReader.GetUserInputWithDefault(nameof(settings.DefaultProvider), settings.DefaultProvider) : defaultProvider; if (ManifestDependencies.GetProvider(defaultProvider) == null) { IError unknownProviderError = PredefinedErrors.ProviderUnknown(defaultProvider); string message = string.Format(Resources.Text.InitFailedUnknownProvider, unknownProviderError.Code, unknownProviderError.Message); throw new InvalidOperationException(message); } manifest.DefaultProvider = defaultProvider; await manifest.SaveAsync(Settings.ManifestFileName, cancellationToken); return(manifest); }
/// <summary> /// Updates file set on the passed in ILibraryInstallationState in case user selected to have all files included /// </summary> /// <param name="desiredState"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <ILibraryOperationResult> UpdateStateAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(desiredState)); } string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(desiredState.Name, desiredState.Version, Id); try { ILibraryCatalog catalog = GetCatalog(); ILibrary library = await catalog.GetLibraryAsync(desiredState.Name, desiredState.Version, cancellationToken).ConfigureAwait(false); if (library == null) { return(new LibraryOperationResult(desiredState, PredefinedErrors.UnableToResolveSource(desiredState.Name, desiredState.ProviderId))); } if (desiredState.Files != null && desiredState.Files.Count > 0) { IReadOnlyList <string> invalidFiles = library.GetInvalidFiles(desiredState.Files); if (invalidFiles.Any()) { IError invalidFilesError = PredefinedErrors.InvalidFilesInLibrary(libraryId, invalidFiles, library.Files.Keys); return(new LibraryOperationResult(desiredState, invalidFilesError)); } else { return(LibraryOperationResult.FromSuccess(desiredState)); } } desiredState = new LibraryInstallationState { ProviderId = Id, Name = desiredState.Name, Version = desiredState.Version, DestinationPath = desiredState.DestinationPath, Files = library.Files.Keys.ToList(), IsUsingDefaultDestination = desiredState.IsUsingDefaultDestination, IsUsingDefaultProvider = desiredState.IsUsingDefaultProvider }; } catch (InvalidLibraryException) { return(new LibraryOperationResult(desiredState, PredefinedErrors.UnableToResolveSource(libraryId, desiredState.ProviderId))); } catch (UnauthorizedAccessException) { return(new LibraryOperationResult(desiredState, PredefinedErrors.PathOutsideWorkingDirectory())); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryOperationResult(desiredState, PredefinedErrors.UnknownException())); } return(LibraryOperationResult.FromSuccess(desiredState)); }
/// <summary> /// Uninstalls the specified library and removes it from the <see cref="Libraries"/> collection. /// </summary> /// <param name="libraryId">The library identifier.</param> /// <param name="deleteFilesFunction"></param> /// <param name="cancellationToken"></param> public async Task <ILibraryOperationResult> UninstallAsync(string libraryId, Func <IEnumerable <string>, Task <bool> > deleteFilesFunction, CancellationToken cancellationToken) { ILibraryInstallationState library = Libraries.FirstOrDefault(l => l.LibraryId == libraryId); if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(library)); } if (library != null) { try { ILibraryOperationResult result = await DeleteLibraryFilesAsync(library, deleteFilesFunction, cancellationToken).ConfigureAwait(false); if (result.Success) { _libraries.Remove(library); return(result); } } catch (OperationCanceledException) { return(LibraryOperationResult.FromCancelled(library)); } } return(LibraryOperationResult.FromError(PredefinedErrors.CouldNotDeleteLibrary(library.LibraryId))); }
public async Task <ILibraryInstallationResult> InstallAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken) { try { foreach (string file in desiredState.Files) { if (cancellationToken.IsCancellationRequested) { return(LibraryInstallationResult.FromCancelled(desiredState)); } string path = Path.Combine(desiredState.DestinationPath, file); var func = new Func <Stream>(() => GetStreamAsync(desiredState, file, cancellationToken).Result); bool writeOk = await HostInteraction.WriteFileAsync(path, func, desiredState, cancellationToken).ConfigureAwait(false); if (!writeOk) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.CouldNotWriteFile(file))); } } } catch (Exception ex) when(ex is InvalidLibraryException || ex.InnerException is InvalidLibraryException) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.UnableToResolveSource(desiredState.LibraryId, desiredState.ProviderId))); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryInstallationResult(desiredState, PredefinedErrors.UnknownException())); } return(LibraryInstallationResult.FromSuccess(desiredState)); }
/// <summary> /// Returns true if the <see cref="ILibraryInstallationState"/> is valid. /// </summary> /// <param name="state">The state to test.</param> /// <param name="errors">The errors contained in the <see cref="ILibraryInstallationState"/> if any.</param> /// <returns> /// <c>true</c> if the specified state is valid; otherwise, <c>false</c>. /// </returns> public static bool IsValid(this ILibraryInstallationState state, out IEnumerable <IError> errors) { errors = null; var list = new List <IError>(); if (state == null) { return(false); } if (string.IsNullOrEmpty(state.ProviderId)) { list.Add(PredefinedErrors.ProviderIsUndefined()); } if (string.IsNullOrEmpty(state.DestinationPath)) { list.Add(PredefinedErrors.PathIsUndefined()); } if (string.IsNullOrEmpty(state.LibraryId)) { list.Add(PredefinedErrors.LibraryIdIsUndefined()); } errors = list; return(list.Count == 0); }
private async Task <ILibraryOperationResult> RestoreLibraryAsync(ILibraryInstallationState libraryState, CancellationToken cancellationToken) { string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(libraryState.Name, libraryState.Version, libraryState.ProviderId); _hostInteraction.Logger.Log(string.Format(Resources.Text.Restore_RestoreOfLibraryStarted, libraryId, libraryState.DestinationPath), LogLevel.Operation); if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(libraryState)); } IProvider provider = _dependencies.GetProvider(libraryState.ProviderId); if (provider == null) { return(new LibraryOperationResult(libraryState, new IError[] { PredefinedErrors.ProviderUnknown(libraryState.ProviderId) })); } try { return(await provider.InstallAsync(libraryState, cancellationToken).ConfigureAwait(false)); } catch (OperationCanceledException) { return(LibraryOperationResult.FromCancelled(libraryState)); } }
public void Predefined() { TestError(PredefinedErrors.UnknownException(), "LIB000"); TestError(PredefinedErrors.ProviderUnknown("_prov_"), "LIB001", "_prov_"); TestError(PredefinedErrors.UnableToResolveSource("_libid_", "_prov_"), "LIB002", "_libid_", "_prov_"); TestError(PredefinedErrors.CouldNotWriteFile("file.js"), "LIB003", "file.js"); TestError(PredefinedErrors.ManifestMalformed(), "LIB004"); }
/// <summary> /// Installs a library as specified in the <paramref name="desiredState" /> parameter. /// </summary> /// <param name="desiredState">The details about the library to install.</param> /// <param name="cancellationToken">A token that allows for the operation to be cancelled.</param> /// <returns> /// The <see cref="T:Microsoft.Web.LibraryManager.Contracts.ILibraryInstallationResult" /> from the installation process. /// </returns> public async Task <ILibraryInstallationResult> InstallAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(LibraryInstallationResult.FromCancelled(desiredState)); } if (!desiredState.IsValid(out IEnumerable <IError> errors)) { return(new LibraryInstallationResult(desiredState, errors.ToArray())); } try { ILibraryInstallationResult result = await UpdateStateAsync(desiredState, cancellationToken); if (!result.Success) { return(result); } desiredState = result.InstallationState; foreach (string file in desiredState.Files) { if (cancellationToken.IsCancellationRequested) { return(LibraryInstallationResult.FromCancelled(desiredState)); } if (string.IsNullOrEmpty(file)) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.CouldNotWriteFile(file))); } string path = Path.Combine(desiredState.DestinationPath, file); var sourceStream = new Func <Stream>(() => GetStreamAsync(desiredState, file, cancellationToken).Result); bool writeOk = await HostInteraction.WriteFileAsync(path, sourceStream, desiredState, cancellationToken).ConfigureAwait(false); if (!writeOk) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.CouldNotWriteFile(file))); } } } catch (UnauthorizedAccessException) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.PathOutsideWorkingDirectory())); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryInstallationResult(desiredState, PredefinedErrors.UnknownException())); } return(LibraryInstallationResult.FromSuccess(desiredState)); }
private async Task <ILibraryOperationResult> DeleteLibraryFilesAsync(ILibraryInstallationState state, Func <IEnumerable <string>, Task <bool> > deleteFilesFunction, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(state.Name, state.Version, state.ProviderId); try { IProvider provider = _dependencies.GetProvider(state.ProviderId); ILibraryOperationResult updatedStateResult = await provider.UpdateStateAsync(state, CancellationToken.None).ConfigureAwait(false); if (updatedStateResult.Success) { List <string> filesToDelete = new List <string>(); state = updatedStateResult.InstallationState; foreach (string file in state.Files) { var url = new Uri(file, UriKind.RelativeOrAbsolute); if (!url.IsAbsoluteUri) { string relativePath = Path.Combine(state.DestinationPath, file).Replace('\\', '/'); filesToDelete.Add(relativePath); } } bool success = true; if (deleteFilesFunction != null) { success = await deleteFilesFunction.Invoke(filesToDelete).ConfigureAwait(false); } if (success) { return(LibraryOperationResult.FromSuccess(updatedStateResult.InstallationState)); } else { return(LibraryOperationResult.FromError(PredefinedErrors.CouldNotDeleteLibrary(libraryId))); } } return(updatedStateResult); } catch (OperationCanceledException) { return(LibraryOperationResult.FromCancelled(state)); } catch (Exception) { return(LibraryOperationResult.FromError(PredefinedErrors.CouldNotDeleteLibrary(libraryId))); } }
private async Task <(string libraryId, ILibrary library)> ValidateLibraryExistsInCatalogAsync(CancellationToken cancellationToken) { try { ILibrary libraryToInstall = await ProviderCatalog.GetLibraryAsync(LibraryId.Value, cancellationToken); if (libraryToInstall != null) { return(LibraryId.Value, libraryToInstall); } } catch { // The library id wasn't in the exact format. } IReadOnlyList <ILibraryGroup> libraryGroup = await ProviderCatalog.SearchAsync(LibraryId.Value, 5, cancellationToken); IError invalidLibraryError = PredefinedErrors.UnableToResolveSource(LibraryId.Value, ProviderId); if (libraryGroup.Count == 0) { throw new InvalidOperationException($"[{invalidLibraryError.Code}]: {invalidLibraryError.Message}"); } var sb = new StringBuilder(); foreach (ILibraryGroup libGroup in libraryGroup) { IEnumerable <string> libIds = await libGroup.GetLibraryIdsAsync(cancellationToken); if (libIds == null || !libIds.Any()) { continue; } if (libGroup.DisplayName.Equals(LibraryId.Value, StringComparison.OrdinalIgnoreCase)) { // Found a group with an exact match. string latestVersion = await ProviderCatalog.GetLatestVersion(libIds.First(), false, cancellationToken); string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(libGroup.DisplayName, latestVersion, ProviderId); ILibrary libraryToInstall = await ProviderCatalog.GetLibraryAsync(libraryId, cancellationToken); return(libraryId, libraryToInstall); } sb.AppendLine(" " + libIds.First()); } sb.Insert(0, $"[{invalidLibraryError.Code}]: {invalidLibraryError.Message} {Environment.NewLine} {Resources.SuggestedIdsMessage}{Environment.NewLine}"); throw new InvalidOperationException(sb.ToString()); }
#pragma warning restore CA1819 // Properties should not return arrays public override bool Execute() { Logger.Instance.Clear(); var configFilePath = new FileInfo(Path.Combine(ProjectDirectory, FileName)); if (!configFilePath.Exists) { Log.LogWarning(configFilePath.Name + " does not exist"); return(true); } var sw = new Stopwatch(); sw.Start(); CancellationToken token = CancellationToken.None; Log.LogMessage(MessageImportance.High, Environment.NewLine + Resources.Text.Restore_OperationStarted); var dependencies = Dependencies.FromTask(ProjectDirectory, ProviderAssemblies.Select(pa => new FileInfo(pa.ItemSpec).FullName)); Manifest manifest = Manifest.FromFileAsync(configFilePath.FullName, dependencies, token).Result; var logger = dependencies.GetHostInteractions().Logger as Logger; if (manifest == null) { sw.Stop(); LogErrors(new[] { PredefinedErrors.ManifestMalformed() }); FlushLogger(logger); return(false); } IEnumerable <ILibraryOperationResult> validationResults = manifest.GetValidationResultsAsync(token).Result; if (!validationResults.All(r => r.Success)) { sw.Stop(); LogErrors(validationResults.SelectMany(r => r.Errors)); return(false); } IEnumerable <ILibraryOperationResult> results = manifest.RestoreAsync(token).Result; sw.Stop(); FlushLogger(logger); PopulateFilesWritten(results, dependencies.GetHostInteractions()); LogResults(sw, results); return(!Log.HasLoggedErrors); }
private async Task UninstallLibraryAsync(string configFilePath, string libraryName, string version, string providerId, CancellationToken cancellationToken) { string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(libraryName, version, providerId); Logger.LogEventsHeader(OperationType.Uninstall, libraryId); try { Stopwatch sw = new Stopwatch(); sw.Start(); var dependencies = _dependenciesFactory.FromConfigFile(configFilePath); Manifest manifest = await Manifest.FromFileAsync(configFilePath, dependencies, cancellationToken).ConfigureAwait(false); ILibraryOperationResult result = null; if (manifest == null) { result = LibraryOperationResult.FromError(PredefinedErrors.ManifestMalformed()); } else { IHostInteraction hostInteraction = dependencies.GetHostInteractions(); result = await manifest.UninstallAsync(libraryName, version, async (filesPaths) => await hostInteraction.DeleteFilesAsync(filesPaths, cancellationToken), cancellationToken).ConfigureAwait(false); } sw.Stop(); if (result.Errors.Any()) { Logger.LogErrorsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall); } else { Logger.LogEventsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall, sw.Elapsed); } Telemetry.LogEventsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall, sw.Elapsed); } catch (OperationCanceledException ex) { Logger.LogEvent(string.Format(LibraryManager.Resources.Text.Uninstall_LibraryCancelled, libraryId), LogLevel.Task); Telemetry.TrackException($@"{OperationType.Uninstall}Cancelled", ex); } }
protected virtual ILibraryOperationResult CheckForInvalidFiles(ILibraryInstallationState desiredState, string libraryId, ILibrary library) { IReadOnlyList <string> invalidFiles = library.GetInvalidFiles(desiredState.Files); if (invalidFiles.Count > 0) { IError invalidFilesError = PredefinedErrors.InvalidFilesInLibrary(libraryId, invalidFiles, library.Files.Keys); return(new LibraryOperationResult(desiredState, invalidFilesError)); } else { return(LibraryOperationResult.FromSuccess(desiredState)); } }
private static IEnumerable <ILibraryOperationResult> GetDuplicateLibrariesErrors(IEnumerable <ILibraryInstallationState> libraries) { var errors = new List <ILibraryOperationResult>(); HashSet <string> duplicateLibraries = GetDuplicateLibraries(libraries); if (duplicateLibraries.Count > 0) { foreach (string libraryName in duplicateLibraries) { errors.Add(LibraryOperationResult.FromError(PredefinedErrors.DuplicateLibrariesInManifest(libraryName))); } } return(errors); }
/// <summary> /// Generates a single ILibraryOperationResult with a collection of IErros based on the collection of FileConflict /// </summary> /// <param name="fileConflicts"></param> /// <returns></returns> private static ILibraryOperationResult GetConflictErrors(IEnumerable <FileConflict> fileConflicts) { if (fileConflicts.Any()) { var errors = new List <IError>(); foreach (FileConflict conflictingLibraryGroup in fileConflicts) { errors.Add(PredefinedErrors.ConflictingFilesInManifest(conflictingLibraryGroup.File, conflictingLibraryGroup.Libraries.Select(l => l.Name).ToList())); } return(new LibraryOperationResult(errors.ToArray())); } return(LibraryOperationResult.FromSuccess(null)); }
/// <summary> /// Updates file set on the passed in ILibraryInstallationState in case user selected to have all files included /// </summary> /// <param name="desiredState"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <ILibraryInstallationResult> UpdateStateAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(LibraryInstallationResult.FromCancelled(desiredState)); } try { ILibraryCatalog catalog = GetCatalog(); ILibrary library = await catalog.GetLibraryAsync(desiredState.LibraryId, cancellationToken).ConfigureAwait(false); if (library == null) { throw new InvalidLibraryException(desiredState.LibraryId, Id); } await HydrateCacheAsync(library, cancellationToken).ConfigureAwait(false); if (desiredState.Files != null && desiredState.Files.Count > 0) { return(LibraryInstallationResult.FromSuccess(desiredState)); } desiredState = new LibraryInstallationState { ProviderId = Id, LibraryId = desiredState.LibraryId, DestinationPath = desiredState.DestinationPath, Files = library.Files.Keys.ToList(), }; } catch (Exception ex) when(ex is InvalidLibraryException || ex.InnerException is InvalidLibraryException) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.UnableToResolveSource(desiredState.LibraryId, desiredState.ProviderId))); } catch (UnauthorizedAccessException) { return(new LibraryInstallationResult(desiredState, PredefinedErrors.PathOutsideWorkingDirectory())); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryInstallationResult(desiredState, PredefinedErrors.UnknownException())); } return(LibraryInstallationResult.FromSuccess(desiredState)); }
/// <summary> /// Copies ILibraryInstallationState files to cache /// </summary> /// <param name="state"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task <ILibraryOperationResult> RefreshCacheAsync(ILibraryInstallationState state, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(state)); } var tasks = new List <Task>(); try { if (!string.IsNullOrEmpty(state.Name) && !string.IsNullOrEmpty(state.Version)) { string libraryDir = Path.Combine(CacheFolder, state.Name); List <CacheServiceMetadata> librariesMetadata = new List <CacheServiceMetadata>(); foreach (string sourceFile in state.Files) { string cacheFile = Path.Combine(libraryDir, state.Version, sourceFile); string url = string.Format(_downloadUrlFormat, state.Name, state.Version, sourceFile); CacheServiceMetadata newEntry = new CacheServiceMetadata(url, cacheFile); if (!librariesMetadata.Contains(newEntry)) { librariesMetadata.Add(new CacheServiceMetadata(url, cacheFile)); } } await _cacheService.RefreshCacheAsync(librariesMetadata, cancellationToken); } } catch (ResourceDownloadException ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.FailedToDownloadResource(ex.Url))); } catch (OperationCanceledException) { return(LibraryOperationResult.FromCancelled(state)); } catch (Exception ex) { HostInteraction.Logger.Log(ex.InnerException.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.UnknownException())); } return(LibraryOperationResult.FromSuccess(state)); }
/// <summary> /// Restores all libraries in the <see cref="Libraries"/> collection. /// </summary> /// <param name="cancellationToken">A token that allows for cancellation of the operation.</param> public async Task <IEnumerable <ILibraryInstallationResult> > RestoreAsync(CancellationToken cancellationToken) { //TODO: This should have an "undo scope" var results = new List <ILibraryInstallationResult>(); var tasks = new List <Task <ILibraryInstallationResult> >(); if (!IsValidManifestVersion(Version)) { results.Add(LibraryInstallationResult.FromErrors(new IError[] { PredefinedErrors.VersionIsNotSupported(Version) })); return(results); } foreach (ILibraryInstallationState state in Libraries) { if (cancellationToken.IsCancellationRequested) { results.Add(LibraryInstallationResult.FromCancelled(state)); _hostInteraction.Logger.Log(Resources.Text.RestoreCancelled, LogLevel.Task); return(results); } if (!state.IsValid(out IEnumerable <IError> errors)) { results.Add(new LibraryInstallationResult(state, errors.ToArray())); continue; } _hostInteraction.Logger.Log(string.Format(Resources.Text.RestoringLibrary, state.LibraryId), LogLevel.Operation); IProvider provider = _dependencies.GetProvider(state.ProviderId); if (provider != null) { tasks.Add(provider.InstallAsync(state, cancellationToken)); } else { results.Add(new LibraryInstallationResult(state, PredefinedErrors.ProviderUnknown(state.ProviderId))); } } await Task.WhenAll(tasks).ConfigureAwait(false); results.AddRange(tasks.Select(t => t.Result)); return(results); }
protected async Task <Manifest> GetManifestAsync() { if (!File.Exists(Settings.ManifestFileName)) { throw new InvalidOperationException(string.Format(Resources.Text.LibmanJsonNotFound, Settings.ManifestFileName)); } Manifest manifest = await Manifest.FromFileAsync(Settings.ManifestFileName, ManifestDependencies, CancellationToken.None); if (manifest == null) { Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Error); throw new InvalidOperationException(Resources.Text.FixManifestFile); } return(manifest); }
/// <summary> /// Creates an instance of the <see cref="Manifest"/> class based on /// the provided JSON string. /// </summary> /// <param name="json">A string of JSON in the correct format.</param> /// <param name="dependencies">The host provided dependencies.</param> /// <returns></returns> internal static Manifest FromJson(string json, IDependencies dependencies) { try { Manifest manifest = JsonConvert.DeserializeObject <Manifest>(json); manifest._dependencies = dependencies; manifest._hostInteraction = dependencies.GetHostInteractions(); UpdateLibraryProviderAndDestination(manifest); return(manifest); } catch (Exception) { dependencies.GetHostInteractions().Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Task); return(null); } }
private async Task <string> GetLatestVersionAsync(ILibraryInstallationState libraryToUpdate, CancellationToken cancellationToken) { ILibraryCatalog catalog = ManifestDependencies.GetProvider(libraryToUpdate.ProviderId)?.GetCatalog(); if (catalog == null) { throw new InvalidOperationException(PredefinedErrors.LibraryIdIsUndefined().Message); } try { return(await catalog.GetLatestVersion(libraryToUpdate.LibraryId, PreRelease.HasValue(), cancellationToken)); } catch (Exception ex) { throw new InvalidOperationException(string.Format(Resources.UnableToFindLatestVersionForLibrary, libraryToUpdate.LibraryId), ex); } }
public void Constructor() { Mocks.LibraryInstallationState state = GetState(); var ctor1 = new LibraryInstallationResult(state); Assert.AreEqual(state, ctor1.InstallationState); Assert.AreEqual(0, ctor1.Errors.Count); Assert.IsTrue(ctor1.Success); Assert.IsFalse(ctor1.Cancelled); var ctor2 = new LibraryInstallationResult(state, PredefinedErrors.ManifestMalformed()); Assert.AreEqual(state, ctor2.InstallationState); Assert.AreEqual(1, ctor2.Errors.Count); Assert.IsFalse(ctor2.Success); Assert.IsFalse(ctor2.Cancelled); }
/// <summary> /// Copy files from the download cache to the desired installation state /// </summary> /// <remarks>Precondition: all files must already exist in the cache</remarks> protected async Task <ILibraryOperationResult> WriteToFilesAsync(ILibraryInstallationState state, CancellationToken cancellationToken) { if (state.Files != null) { try { foreach (string file in state.Files) { if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(state)); } if (string.IsNullOrEmpty(file)) { string id = LibraryNamingScheme.GetLibraryId(state.Name, state.Version); return(new LibraryOperationResult(state, PredefinedErrors.FileNameMustNotBeEmpty(id))); } string sourcePath = GetCachedFileLocalPath(state, file); string destinationPath = Path.Combine(state.DestinationPath, file); bool writeOk = await HostInteraction.CopyFileAsync(sourcePath, destinationPath, cancellationToken); if (!writeOk) { return(new LibraryOperationResult(state, PredefinedErrors.CouldNotWriteFile(file))); } } } catch (UnauthorizedAccessException) { return(new LibraryOperationResult(state, PredefinedErrors.PathOutsideWorkingDirectory())); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.UnknownException())); } } return(LibraryOperationResult.FromSuccess(state)); }
private async Task <ILibraryOperationResult> WriteToFilesAsync(ILibraryInstallationState state, CancellationToken cancellationToken) { if (state.Files != null) { try { foreach (string file in state.Files) { if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(state)); } if (string.IsNullOrEmpty(file)) { return(new LibraryOperationResult(state, PredefinedErrors.CouldNotWriteFile(file))); } string destinationPath = Path.Combine(state.DestinationPath, file); var sourceStream = new Func <Stream>(() => GetStreamAsync(state, file, cancellationToken).Result); bool writeOk = await HostInteraction.WriteFileAsync(destinationPath, sourceStream, state, cancellationToken).ConfigureAwait(false); if (!writeOk) { return(new LibraryOperationResult(state, PredefinedErrors.CouldNotWriteFile(file))); } } } catch (UnauthorizedAccessException) { return(new LibraryOperationResult(state, PredefinedErrors.PathOutsideWorkingDirectory())); } catch (Exception ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.UnknownException())); } } return(LibraryOperationResult.FromSuccess(state)); }
/// <summary> /// Validates <see cref="ILibraryInstallationState"/> /// </summary> /// <param name="state">The <see cref="ILibraryInstallationState"/> to validate.</param> /// <param name="dependencies">The <see cref="IDependencies"/> used to validate <see cref="ILibraryInstallationState"/></param> /// <returns><see cref="ILibraryOperationResult"/> with the result of the validation</returns> public static async Task <ILibraryOperationResult> IsValidAsync(this ILibraryInstallationState state, IDependencies dependencies) { if (state == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.UnknownError() })); } if (string.IsNullOrEmpty(state.ProviderId)) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.ProviderIsUndefined() })); } IProvider provider = dependencies.GetProvider(state.ProviderId); if (provider == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.ProviderUnknown(state.ProviderId) })); } return(await IsValidAsync(state, provider).ConfigureAwait(false)); }
/// <summary> /// Creates an instance of the <see cref="Manifest"/> class based on /// the provided JSON string. /// </summary> /// <param name="json">A string of JSON in the correct format.</param> /// <param name="dependencies">The host provided dependencies.</param> /// <returns></returns> public static Manifest FromJson(string json, IDependencies dependencies) { try { Manifest manifest = JsonConvert.DeserializeObject <Manifest>(json); manifest._dependencies = dependencies; manifest._hostInteraction = dependencies.GetHostInteractions(); foreach (LibraryInstallationState state in manifest.Libraries.Cast <LibraryInstallationState>()) { state.ProviderId = state.ProviderId ?? manifest.DefaultProvider; } return(manifest); } catch (Exception) { dependencies.GetHostInteractions().Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Task); return(null); } }
/// <summary> /// Validates <see cref="ILibraryInstallationState"/> /// </summary> /// <param name="state">The <see cref="ILibraryInstallationState"/> to validate.</param> /// <param name="provider">The <see cref="IProvider"/> used to validate <see cref="ILibraryInstallationState"/></param> /// <returns><see cref="ILibraryOperationResult"/> with the result of the validation</returns> public static async Task <ILibraryOperationResult> IsValidAsync(this ILibraryInstallationState state, IProvider provider) { if (state == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.UnknownError() })); } if (provider == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.ProviderUnknown(provider.Id) })); } if (string.IsNullOrEmpty(state.Name)) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.LibraryIdIsUndefined() })); } ILibraryCatalog catalog = provider.GetCatalog(); try { await catalog.GetLibraryAsync(state.Name, state.Version, CancellationToken.None).ConfigureAwait(false); } catch { return(new LibraryOperationResult(state, new[] { PredefinedErrors.UnableToResolveSource(state.Name, state.Version, provider.Id) })); } if (string.IsNullOrEmpty(state.DestinationPath)) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.PathIsUndefined() })); } if (state.DestinationPath.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.DestinationPathHasInvalidCharacters(state.DestinationPath) })); } return(LibraryOperationResult.FromSuccess(state)); }
/// <summary> /// Copies ILibraryInstallationState files to cache /// </summary> /// <param name="state"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task <ILibraryOperationResult> RefreshCacheAsync(ILibraryInstallationState state, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(LibraryOperationResult.FromCancelled(state)); } string libraryDir = Path.Combine(CacheFolder, state.Name, state.Version); try { var librariesMetadata = new HashSet <CacheFileMetadata>(); foreach (string sourceFile in state.Files) { string cacheFile = Path.Combine(libraryDir, sourceFile); string url = GetDownloadUrl(state, sourceFile); var newEntry = new CacheFileMetadata(url, cacheFile); librariesMetadata.Add(newEntry); } await _cacheService.RefreshCacheAsync(librariesMetadata, HostInteraction.Logger, cancellationToken); } catch (ResourceDownloadException ex) { HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.FailedToDownloadResource(ex.Url))); } catch (OperationCanceledException) { return(LibraryOperationResult.FromCancelled(state)); } catch (Exception ex) { HostInteraction.Logger.Log(ex.InnerException.ToString(), LogLevel.Error); return(new LibraryOperationResult(state, PredefinedErrors.UnknownException())); } return(LibraryOperationResult.FromSuccess(state)); }