/// <summary>
        /// Determines whether a file up to date.
        /// </summary>
        /// <param name="manifest">The manifest.</param>
        /// <returns>
        ///   <c>true</c> if the file is up to date; otherwise, <c>false</c>.
        /// </returns>
        private bool IsFileUpToDate(ManifestJson manifest)
        {
            string workingDir = GetCorrectDownloadDirectory(manifest.filename);
            string filePath   = workingDir + manifest.filename;

            return(File.Exists(filePath) && Hashing.CalculateSHA256(filePath) == manifest.sha256);
        }
        public bool HasNonCompatiblePackagesCombination(bool isCoverage, out string message)
        {
            message = string.Empty;

            if (myUnityVersion.GetActualVersionForSolution() < new Version("2019.2"))
            {
                return(false);
            }

            var manifestJsonFile = mySolution.SolutionDirectory.Combine("Packages/manifest.json");

            if (manifestJsonFile.ExistsFile)
            {
                var text     = manifestJsonFile.ReadAllText2().Text;
                var packages = ManifestJson.FromJson(text);

                var testFrameworkPackageId     = "com.unity.test-framework";
                var riderPackageId             = "com.unity.ide.rider";
                var testFrameworkMarketingName = "Test Framework";
                var riderMarketingName         = "Rider Editor";

                if (PackageIsMissing(ref message, packages, testFrameworkPackageId, testFrameworkMarketingName))
                {
                    return(true);
                }
                if (PackageIsMissing(ref message, packages, riderPackageId, riderMarketingName))
                {
                    return(true);
                }

                var riderPackageVersion  = packages[riderPackageId];
                var testFrameworkVersion = packages[testFrameworkPackageId];
                if (IsOldPackage(ref message, riderPackageVersion, riderMarketingName, "1.1.1"))
                {
                    return(true);
                }
                if (IsOldPackage(ref message, testFrameworkVersion, testFrameworkMarketingName, "1.1.1"))
                {
                    return(true);
                }

                if (isCoverage && packages.ContainsKey(riderPackageId) && packages.ContainsKey(testFrameworkPackageId))
                {
                    // https://youtrack.jetbrains.com/issue/RIDER-35880
                    if (riderPackageVersion != null && riderPackageVersion < new Version("1.2.0") &&
                        testFrameworkVersion != null &&
                        testFrameworkVersion >= new Version("1.1.5"))
                    {
                        message = $"Update {riderMarketingName} package to v.1.2.0 or later in Unity Package Manager. {HelpLink}";
                        return(true);
                    }
                }
            }

            // todo: package may be installed locally, ignore this possibility for now
            // var localPackage = mySolution.SolutionDirectory.Combine("Packages/com.unity.ide.rider/package.json");

            return(false);
        }
        private void VerifyFile(ManifestJson manifest, int totalFiles)
        {
            Log.Info("Verifying file " + manifest.filename);

            _instance?.Invoke((MethodInvoker) delegate
            {
                _instance.lblNowDownloading.Text = "Verified files: " + _filesChecked + "/" + (totalFiles);
            });

            if (IsFileUpToDate(manifest))
            {
                Log.Info(manifest.filename + " : Up to date.");
            }
            else
            {
                Log.Info(manifest.filename + " : Outdated");
                _downloadList.Add(manifest.filename, manifest.url);
            }
            _filesChecked++;
        }
        private void VerifyFiles(string rawManifest)
        {
            string[] rawManifestArray = rawManifest.Split('#');

            // Remove the empty values in the array ( The last value will be removed, but just to future proof in case manifest changes )
            string[] manifestArray = rawManifestArray.Where(x => !string.IsNullOrEmpty(x)).ToArray();

            _instance?.Invoke((MethodInvoker) delegate
            {
                _instance.lblNowDownloading.Text = "Verifying game files...";
            });

            ParallelOptions options = new ParallelOptions
            {
                MaxDegreeOfParallelism = (int)Math.Ceiling(Environment.ProcessorCount / 2d) // Cores / 2 50% cpu usage. Round up if we get dec vals
            };

            Parallel.ForEach(manifestArray, options, x =>
            {
                ManifestJson manifest = JsonConvert.DeserializeObject <ManifestJson>(x.Replace("#", ""));
                VerifyFile(manifest, manifestArray.Length);
            });
        }