internal static bool IsPackageVersionCompatible(string ver0Str, PackageVersion ver1, out PackageVersion ver0)
        {
            bool parsed = PackageVersion.TryParse(ver0Str, out ver0);

            if (!parsed)
            {
                return(false);
            }

            return(ver0.GetMajor() == ver1.GetMajor() && ver0.GetMinor() == ver1.GetMinor());
        }
        public IEnumerator CheckPluginVersionCompatibility()
        {
            ListRequest list = Client.List(true, false);

            while (!list.IsCompleted)
            {
                yield return(null);
            }

            PackageVersion pluginVersion = MeshSyncEditorConstants.GetPluginVersion();

            int?pluginMajor = pluginVersion.GetMajor();
            int?pluginMinor = pluginVersion.GetMinor();
            int?pluginPatch = pluginVersion.GetPatch();

            Assert.IsNotNull(pluginMajor);
            Assert.IsNotNull(pluginMinor);

            bool pluginVersionValid = !(pluginMajor == 0 && pluginMinor == 0 && pluginPatch == 0);

            Assert.IsTrue(pluginVersionValid, $"Plugin version is not valid: {pluginVersion}");

            foreach (PackageInfo packageInfo in list.Result)
            {
                if (packageInfo.name != MeshSyncConstants.PACKAGE_NAME)
                {
                    continue;
                }

                bool parsed = PackageVersion.TryParse(packageInfo.version, out PackageVersion packageVersion);
                Assert.IsTrue(parsed);

                //Based on our rule to increase the major/minor version whenever we change any plugin code,
                //it's ok for the patch version to be different.
                Assert.AreEqual(pluginMajor, packageVersion.GetMajor(), $"Major: {pluginMajor} !={packageVersion.GetMajor()}");
                Assert.AreEqual(pluginMinor, packageVersion.GetMinor(), $"Minor: {pluginMinor} !={packageVersion.GetMinor()}");
                yield break;
            }
        }
        void UpdateLatestCompatibleDCCPlugin(VersionsInfo versionsInfo)
        {
            PackageVersion pluginVer = MeshSyncEditorConstants.GetPluginVersion();

            foreach (string dccPluginVer in versionsInfo.all)
            {
                bool parsed = PackageVersion.TryParse(dccPluginVer, out PackageVersion dccPluginPackageVersion);
                Assert.IsTrue(parsed);

                //Skip incompatible versions
                if (dccPluginPackageVersion.GetMajor() != pluginVer.GetMajor() ||
                    dccPluginPackageVersion.GetMinor() != pluginVer.GetMinor())
                {
                    continue;
                }

                if (null == m_latestCompatibleDCCPluginVersion ||
                    dccPluginPackageVersion.GetPatch() > m_latestCompatibleDCCPluginVersion.GetPatch())
                {
                    m_latestCompatibleDCCPluginVersion = dccPluginPackageVersion;
                }
            }
        }
//----------------------------------------------------------------------------------------------------------------------
        void UpdateDCCPluginStatusLabel(Label statusLabel)
        {
            BaseDCCIntegrator dccIntegrator = statusLabel.userData as BaseDCCIntegrator;

            Assert.IsNotNull(dccIntegrator);
            DCCPluginInstallInfo installInfo = dccIntegrator.FindInstallInfo();

            const string NOT_INSTALLED = "MeshSync Plugin not installed";

            if (null == installInfo)
            {
                statusLabel.text = NOT_INSTALLED;
                return;
            }

            DCCToolInfo dccToolInfo = dccIntegrator.GetDCCToolInfo();
            string      installedPluginVersionStr = installInfo.GetPluginVersion(dccToolInfo.AppPath);

            if (string.IsNullOrEmpty(installedPluginVersionStr))
            {
                statusLabel.text = NOT_INSTALLED;
                return;
            }

            //Remove all known classes
            const string PLUGIN_INCOMPATIBLE_CLASS  = "plugin-incompatible";
            const string PLUGIN_INSTALLED_OLD_CLASS = "plugin-installed-old";
            const string PLUGIN_INSTALLED_CLASS     = "plugin-installed";

            statusLabel.RemoveFromClassList(PLUGIN_INCOMPATIBLE_CLASS);
            statusLabel.RemoveFromClassList(PLUGIN_INSTALLED_CLASS);
            statusLabel.RemoveFromClassList(PLUGIN_INSTALLED_OLD_CLASS);

            PackageVersion pluginVer = MeshSyncEditorConstants.GetPluginVersion();

            //[TODO-sin: 2021-10-28] this TryParse() check is called more than once in this file. Refactor this code
            //The DCC Plugin is installed, and we need to check if it's compatible with this version of MeshSync
            bool parsed = PackageVersion.TryParse(installedPluginVersionStr, out PackageVersion installedPluginVersion);

            if (!parsed ||
                installedPluginVersion.GetMajor() != pluginVer.GetMajor() ||
                installedPluginVersion.GetMinor() != pluginVer.GetMinor())
            {
                statusLabel.AddToClassList(PLUGIN_INCOMPATIBLE_CLASS);
                statusLabel.text = "Installed MeshSync Plugin is incompatible. Version: " + installedPluginVersionStr;
                return;
            }

            //Check if we have newer compatible DCCPlugin
            if (null != m_latestCompatibleDCCPluginVersion &&
                installedPluginVersion.GetPatch() < m_latestCompatibleDCCPluginVersion.GetPatch())
            {
                statusLabel.AddToClassList(PLUGIN_INSTALLED_OLD_CLASS);
                statusLabel.text = $"Plugin {installedPluginVersionStr} installed. " +
                                   $"({m_latestCompatibleDCCPluginVersion} is available)";
                return;
            }

            statusLabel.AddToClassList(PLUGIN_INSTALLED_CLASS);
            statusLabel.text = $"Plugin {installedPluginVersionStr} installed";
        }