示例#1
0
        /// <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;
        }
示例#3
0
        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));
        }
示例#5
0
        /// <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)));
        }
示例#6
0
        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));
        }
示例#7
0
        /// <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);
        }
示例#8
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));
            }
        }
示例#9
0
 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");
 }
示例#10
0
        /// <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));
        }
示例#11
0
        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)));
            }
        }
示例#12
0
        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());
        }
示例#13
0
#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);
            }
        }
示例#15
0
        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));
            }
        }
示例#16
0
        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);
        }
示例#17
0
        /// <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));
        }
示例#18
0
        /// <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));
        }
示例#20
0
        /// <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);
        }
示例#21
0
        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);
        }
示例#22
0
        /// <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);
            }
        }
示例#23
0
        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);
        }
示例#25
0
        /// <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));
        }
示例#26
0
        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));
        }
示例#27
0
        /// <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));
        }
示例#28
0
        /// <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);
            }
        }
示例#29
0
        /// <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));
        }
示例#30
0
        /// <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));
        }