Exemplo n.º 1
0
        public async Task <IEnumerable <IPackage> > GetCatalogPackagesAsync(string filterText, Uri registryUrl = null)
        {
            IEnumerable <IPackage> packages = null;

            using (var semaphore = GetDatabaseSemaphore()) {
                // Wait until file is downloaded/parsed if another download is already in session.
                // Allows user to open multiple npm windows and show progress bar without file-in-use errors.
                bool success = semaphore.WaitOne(10);
                if (!success)
                {
                    OnOutputLogged(Resources.ErrorCatalogInUse);
                    // Return immediately so that the user can explicitly decide to refresh on failure.
                    return(null);
                }

                try {
                    registryUrl = registryUrl ?? await GetRegistryUrl();

                    RegistryFileMapping registryFileMapping = null;
                    using (var db = new SQLiteConnection(DatabaseCacheFilePath)) {
                        registryFileMapping = db.Table <RegistryFileMapping>().FirstOrDefault(info => info.RegistryUrl == registryUrl.ToString());
                    }

                    if (registryFileMapping != null)
                    {
                        string registryFileLocation = Path.Combine(CachePath, registryFileMapping.DbFileLocation, RegistryCacheFilename);

                        var packagesEnumerable = new DatabasePackageCatalogFilter(registryFileLocation).Filter(filterText);
                        packages = await Task.Run(() => packagesEnumerable.ToList());
                    }
                } catch (Exception e) {
                    OnOutputLogged(e.ToString());
                    throw;
                } finally {
                    semaphore.Release();
                }
            }
            return(packages);
        }
Exemplo n.º 2
0
        public override async Task <bool> ExecuteAsync()
        {
            var    dbFilename             = DatabaseCacheFilePath;
            bool   catalogUpdated         = false;
            string filename               = null;
            string registryCacheDirectory = null;
            string registryCachePath      = null;
            string registryCacheFilePath  = null;

            // Use a semaphore instead of a mutex because await may return to a thread other than the calling thread.
            using (var semaphore = GetDatabaseSemaphore()) {
                // Wait until file is downloaded/parsed if another download is already in session.
                // Allows user to open multiple npm windows and show progress bar without file-in-use errors.
                bool success = await Task.Run(() => semaphore.WaitOne(TimeSpan.FromMinutes(5)));

                if (!success)
                {
                    // Return immediately so that the user can explicitly decide to refresh on failure.
                    return(false);
                }

                Uri registryUrl = await GetRegistryUrl();

                OnOutputLogged(string.Format(Resources.InfoRegistryUrl, registryUrl));

                try {
                    DbVersion           version             = null;
                    RegistryInfo        registryInfo        = null;
                    RegistryFileMapping registryFileMapping = null;

                    Directory.CreateDirectory(Path.GetDirectoryName(dbFilename));

                    using (var db = new SQLiteConnection(dbFilename)) {
                        // prevent errors from occurring when table doesn't exist
                        db.CreateCatalogTableIfNotExists();
                        version             = db.Table <DbVersion>().FirstOrDefault();
                        registryFileMapping = db.Table <RegistryFileMapping>().FirstOrDefault(info => info.RegistryUrl == registryUrl.ToString());
                    }

                    registryCacheDirectory = registryFileMapping != null ? registryFileMapping.DbFileLocation : Guid.NewGuid().ToString();
                    registryCachePath      = Path.Combine(CachePath, registryCacheDirectory);
                    registryCacheFilePath  = Path.Combine(registryCachePath, RegistryCacheFilename);

                    Directory.CreateDirectory(Path.GetDirectoryName(registryCacheFilePath));

                    if (File.Exists(registryCacheFilePath))
                    {
                        using (var registryDb = new SQLiteConnection(registryCacheFilePath)) {
                            // prevent errors from occurring when table doesn't exist
                            registryDb.CreateRegistryTableIfNotExists();
                            registryInfo = registryDb.Table <RegistryInfo>().FirstOrDefault();
                        }
                    }

                    bool correctDatabaseSchema = version != null && version.Id == _databaseSchemaVersion;
                    bool incrementalUpdate     = correctDatabaseSchema && _forceDownload && registryInfo != null && registryInfo.Revision > 0;
                    bool fullUpdate            = correctDatabaseSchema && (registryInfo == null || registryInfo.Revision <= 0);

                    if (!correctDatabaseSchema)
                    {
                        OnOutputLogged(Resources.InfoCatalogUpgrade);
                        SafeDeleteFolder(CachePath);

                        CreateCatalogDatabaseAndInsertEntries(dbFilename, registryUrl, registryCacheDirectory);

                        filename = await UpdatePackageCache(registryUrl, CachePath);

                        catalogUpdated = true;
                    }
                    else if (incrementalUpdate)
                    {
                        filename = await UpdatePackageCache(registryUrl, registryCachePath, registryInfo.Revision);

                        catalogUpdated = true;
                    }
                    else if (fullUpdate)
                    {
                        CreateCatalogDatabaseAndInsertEntries(dbFilename, registryUrl, registryCacheDirectory);

                        filename = await UpdatePackageCache(registryUrl, registryCachePath);

                        catalogUpdated = true;
                    }

                    if (catalogUpdated)
                    {
                        var fileInfo = new FileInfo(filename);
                        OnOutputLogged(String.Format(Resources.InfoReadingBytesFromPackageCache, fileInfo.Length, filename, fileInfo.LastWriteTime));

                        using (var reader = new StreamReader(filename)) {
                            await Task.Run(() => ParseResultsAndAddToDatabase(reader, registryCacheFilePath, registryUrl.ToString()));
                        }
                    }

                    using (var db = new SQLiteConnection(registryCacheFilePath)) {
                        db.CreateRegistryTableIfNotExists();
                        ResultsCount = db.Table <CatalogEntry>().Count();
                    }
                } catch (Exception ex) {
                    if (ex is StackOverflowException ||
                        ex is OutOfMemoryException ||
                        ex is ThreadAbortException ||
                        ex is AccessViolationException)
                    {
                        throw;
                    }
                    // assume the results are corrupted
                    OnOutputLogged(ex.ToString());
                    throw;
                } finally {
                    if (ResultsCount == null)
                    {
                        OnOutputLogged(string.Format(Resources.DownloadOrParsingFailed, CachePath));
                        SafeDeleteFolder(registryCacheDirectory);
                    }
                    else if (ResultsCount <= 0)
                    {
                        // Database file exists, but is corrupt. Delete database, so that we can download the file next time arround.
                        OnOutputLogged(string.Format(Resources.DatabaseCorrupt, dbFilename));
                        SafeDeleteFolder(registryCacheDirectory);
                    }

                    semaphore.Release();
                }
            }

            LastRefreshed = File.GetLastWriteTime(registryCacheFilePath);

            OnOutputLogged(String.Format(Resources.InfoCurrentTime, DateTime.Now));
            OnOutputLogged(String.Format(Resources.InfoLastRefreshed, LastRefreshed));
            if (ResultsCount != null)
            {
                OnOutputLogged(String.Format(Resources.InfoNumberOfResults, ResultsCount));
            }

            return(true);
        }