Esempio n. 1
0
        public async Task <ILibraryOperationResult> InstallAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(LibraryOperationResult.FromCancelled(desiredState));
            }

            //Expand the files property if needed
            ILibraryOperationResult updateResult = await UpdateStateAsync(desiredState, cancellationToken);

            if (!updateResult.Success)
            {
                return(updateResult);
            }

            desiredState = updateResult.InstallationState;

            // Refresh cache if needed
            ILibraryOperationResult cacheUpdateResult = await RefreshCacheAsync(desiredState, cancellationToken);

            if (!cacheUpdateResult.Success)
            {
                return(cacheUpdateResult);
            }

            // Check if Library is already up tp date
            if (IsLibraryUpToDate(desiredState, cancellationToken))
            {
                return(LibraryOperationResult.FromUpToDate(desiredState));
            }

            // Write files to destination
            return(await WriteToFilesAsync(desiredState, cancellationToken));
        }
        /// <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));
        }
Esempio n. 3
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="Microsoft.Web.LibraryManager.Contracts.ILibraryOperationResult" /> from the installation process.
        /// </returns>
        public override async Task <ILibraryOperationResult> InstallAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(LibraryOperationResult.FromCancelled(desiredState));
            }

            try
            {
                ILibraryOperationResult result = await UpdateStateAsync(desiredState, cancellationToken);

                if (!result.Success)
                {
                    return(result);
                }

                desiredState = result.InstallationState;

                foreach (string file in desiredState.Files)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(LibraryOperationResult.FromCancelled(desiredState));
                    }

                    if (string.IsNullOrEmpty(file))
                    {
                        return(new LibraryOperationResult(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 LibraryOperationResult(desiredState, PredefinedErrors.CouldNotWriteFile(file)));
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                return(new LibraryOperationResult(desiredState, PredefinedErrors.PathOutsideWorkingDirectory()));
            }
            catch (ResourceDownloadException ex)
            {
                return(new LibraryOperationResult(desiredState, PredefinedErrors.FailedToDownloadResource(ex.Url)));
            }
            catch (Exception ex)
            {
                HostInteraction.Logger.Log(ex.ToString(), LogLevel.Error);
                return(new LibraryOperationResult(desiredState, PredefinedErrors.UnknownException()));
            }

            return(LibraryOperationResult.FromSuccess(desiredState));
        }
Esempio n. 4
0
        public void FromCancelled()
        {
            Mocks.LibraryInstallationState state = GetState();
            var result = LibraryOperationResult.FromCancelled(state);

            Assert.AreEqual(state, result.InstallationState);
            Assert.AreEqual(0, result.Errors.Count);
            Assert.IsFalse(result.Success);
            Assert.IsTrue(result.Cancelled);
        }
        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);
            }
        }
Esempio n. 6
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));
            }
        }
        /// <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>
        /// 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));
            }

            try
            {
                ILibraryCatalog catalog = GetCatalog();
                ILibrary        library = await catalog.GetLibraryAsync(desiredState.LibraryId, cancellationToken).ConfigureAwait(false);

                if (library == null)
                {
                    return(new LibraryOperationResult(desiredState, PredefinedErrors.UnableToResolveSource(desiredState.LibraryId, Id)));
                }

                if (desiredState.Files != null && desiredState.Files.Count > 0)
                {
                    return(LibraryOperationResult.FromSuccess(desiredState));
                }

                desiredState = new LibraryInstallationState
                {
                    ProviderId      = Id,
                    LibraryId       = desiredState.LibraryId,
                    DestinationPath = desiredState.DestinationPath,
                    Files           = library.Files.Keys.ToList(),
                };
            }
            catch (InvalidLibraryException)
            {
                return(new LibraryOperationResult(desiredState, PredefinedErrors.UnableToResolveSource(desiredState.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));
        }
Esempio n. 9
0
        public void Constructor()
        {
            Mocks.LibraryInstallationState state = GetState();

            var ctor1 = new LibraryOperationResult(state);

            Assert.AreEqual(state, ctor1.InstallationState);
            Assert.AreEqual(0, ctor1.Errors.Count);
            Assert.IsTrue(ctor1.Success);
            Assert.IsFalse(ctor1.Cancelled);

            var ctor2 = new LibraryOperationResult(state, PredefinedErrors.ManifestMalformed());

            Assert.AreEqual(state, ctor2.InstallationState);
            Assert.AreEqual(1, ctor2.Errors.Count);
            Assert.IsFalse(ctor2.Success);
            Assert.IsFalse(ctor2.Cancelled);
        }
Esempio n. 10
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));
        }
Esempio n. 11
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));
        }
Esempio n. 12
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));
        }
Esempio n. 13
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));
        }
        private async Task UninstallLibraryAsync(string configFilePath, string libraryId, CancellationToken cancellationToken)
        {
            Logger.LogEventsHeader(OperationType.Uninstall, libraryId);

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();

                var      dependencies = Dependencies.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(libraryId, async (filesPaths) => await hostInteraction.DeleteFilesAsync(filesPaths, cancellationToken), cancellationToken).ConfigureAwait(false);
                }

                sw.Stop();

                Logger.LogEventsSummary(new List <ILibraryOperationResult> {
                    result
                }, OperationType.Uninstall, sw.Elapsed);
                Telemetry.TrackUserTask("libraryuninstall");
            }
            catch (OperationCanceledException)
            {
                Logger.LogEvent(string.Format(LibraryManager.Resources.Text.Uninstall_LibraryCancelled, libraryId), LogLevel.Task);
            }
        }
Esempio n. 15
0
        /// <inheritdoc />
        public virtual async Task <ILibraryOperationResult> UpdateStateAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(LibraryOperationResult.FromCancelled(desiredState));
            }

            string libraryId = LibraryNamingScheme.GetLibraryId(desiredState.Name, desiredState.Version);

            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)
                {
                    // expand any potential file patterns
                    IEnumerable <string> updatedFiles = FileGlobbingUtility.ExpandFileGlobs(desiredState.Files, library.Files.Keys);
                    var processedState = new LibraryInstallationState
                    {
                        Name                      = desiredState.Name,
                        Version                   = desiredState.Version,
                        ProviderId                = desiredState.ProviderId,
                        DestinationPath           = desiredState.DestinationPath,
                        IsUsingDefaultDestination = desiredState.IsUsingDefaultDestination,
                        IsUsingDefaultProvider    = desiredState.IsUsingDefaultProvider,
                        Files                     = updatedFiles.ToList(),
                    };

                    return(CheckForInvalidFiles(processedState, libraryId, library));
                }

                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));
        }
Esempio n. 16
0
 protected override ILibraryOperationResult CheckForInvalidFiles(ILibraryInstallationState desiredState, string libraryId, ILibrary library)
 {
     return(LibraryOperationResult.FromSuccess(desiredState));
 }