<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Microsoft.VisualStudio.ExtensionManager;
using Microsoft.VisualStudio.ExtensionManager.UI;

namespace ExtensionSync
{
    public class ExtensionManagerFacade
    {

        public ExtensionManagerFacade(IVsExtensionManager visualStudioExtensionManager,
                                      IVsExtensionRepository visualStudioExtensionRepository)
        {
            ExtensionManager = visualStudioExtensionManager;
            ExtensionRepository = visualStudioExtensionRepository;

            processingTimer.Elapsed += (sender, e) => ClearExtensionManagerEventHandlers();
        }

        public event Action<string> Log;

        public List<ExtensionInformation> GetInstalledExtensionsInformation()
        {
            var installedExtensions = ExtensionManager.GetInstalledExtensions();
            var userExtensions = installedExtensions.Where(ext =>
                        !ext.Header.SystemComponent && !ext.Header.InstalledByMsi)
                        .OrderBy(ext => ext.Header.Name);

            return userExtensions.Select(
                    e => new ExtensionInformation
                    {
                        Name = e.Header.Name,
                        Identifier = e.Header.Identifier,
                        Version = e.Header.Version
                    })
                    .ToList();
        }

        public void InstallExtensions(List<ExtensionInformation> extensions)
        {
            if (extensions == null || extensions.Count == 0)
                return;

            try
            {
                extensionsBeingInstalled.Clear();
                ExtensionRepository.DownloadCompleted += ExtensionRepositoryDownloadCompleted;
                ExtensionManager.InstallCompleted += ExtensionManagerInstallCompleted;

                foreach (var extension in extensions)
                {
                    extensionsBeingInstalled.Add(extension.Name);

                    var query = ExtensionRepository.CreateQuery<VSGalleryEntry>(false, true)
                                .OrderByDescending(v => v.Ranking)
                                .Skip(0)
                                .Take(25) as IVsExtensionRepositoryQuery<VSGalleryEntry>;
                    if (query == null) continue;

                    query.ExecuteCompleted += QueryExecuteCompleted;
                    query.SearchText = extension.Name;
                    query.ExecuteAsync(extension);
                }

                //Give it a a few minutes to do its work. If everything goes smoothly, event handlers should unbind.
                // Make a safety check and remove handlers if not already done
                processingTimer.Start();
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ClearExtensionManagerEventHandlers()
        {
            lock (this)
            {
                if (eventHandlersCleared) return;

                eventHandlersCleared = true;
                ExtensionRepository.DownloadCompleted -= ExtensionRepositoryDownloadCompleted;
                ExtensionManager.InstallCompleted -= ExtensionManagerInstallCompleted;

                processingTimer.Stop();
            }
        }

        public void UnInstallExtensions(List<ExtensionInformation> extensions, DateTimeOffset configUpdateDateTime)
        {
            if (extensions == null || extensions.Count == 0)
                return;

            var installedUserExtensions = ExtensionManager.GetInstalledExtensions().
                                    Where(e => !e.Header.SystemComponent).ToList();

            var extensionsInstalledAfterConfigUpdated = installedUserExtensions
                            .Where(i => i.InstalledOn > configUpdateDateTime).ToList();

            foreach (var extension in extensions)
            {
                try
                {
                    if (extension.Name.Equals("ExtensionSync", StringComparison.InvariantCultureIgnoreCase))
                        continue;

                    var extensionInformation = extension;
                    var userExtension =
                        installedUserExtensions.SingleOrDefault(e =>
                            e.Header.Name == extensionInformation.Name &&
                            e.Header.Identifier == extensionInformation.Identifier);
                    if (userExtension == null) continue;

                    if (extensionsInstalledAfterConfigUpdated.Contains(userExtension))
                    {
                        LogMessage(string.Format("Not uninstalling {0} since it was installed after last update to config file."
                            , userExtension.Header.Name));
                        continue;
                    }

                    LogMessage(string.Format("Uninstalling {0}", userExtension.Header.Name));
                    ExtensionManager.Uninstall(userExtension);
                }
                catch (Exception exception)
                {
                    LogMessage(string.Format("Error while uninstalling {0}: {1}", extension.Name, exception.Message));
                }
            }
        }

        private void QueryExecuteCompleted(object sender, ExecuteCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    LogMessage(string.Format("Error while searching online for extension: {0}", e.Error.Message));
                    return;
                }

                var extensionInformation = (ExtensionInformation)e.UserState;
                var entry =
                    e.Results.Cast<VSGalleryEntry>().SingleOrDefault(r =>
                        r.Name == extensionInformation.Name && r.VsixID == extensionInformation.Identifier);
                if (entry == null)
                {
                    LogMessage(string.Format("Could not find {0} in Online Repository", extensionInformation.Name));
                    ExtensionInstallDone(extensionInformation.Name);
                    return;
                }

                if(AutoUpdateExtensions)
                {
                    var installedExtensions = GetInstalledExtensionsInformation();
                    var installedExtension = installedExtensions.FirstOrDefault(ext => ext.Name == extensionInformation.Name
                                         &&
                                         ext.Identifier ==
                                         extensionInformation.Identifier);
                    if(installedExtension!=null && installedExtension.Version.ToString()==entry.VsixVersion)
                    {
                        ExtensionInstallDone(extensionInformation.Name);
                        return;
                    }
                }

                ExtensionRepository.DownloadAsync(entry);
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ExtensionRepositoryDownloadCompleted(object sender, DownloadCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    LogMessage(string.Format("Error while downloading extension: {0}", e.Error.Message));
                    return;
                }

                var installableExtension = e.Payload;

                var installedExtensions = GetInstalledExtensionsInformation();
                if (installedExtensions.Any(i =>
                        i.Name == installableExtension.Header.Name &&
                        i.Identifier == installableExtension.Header.Identifier &&
                        i.Version>=installableExtension.Header.Version))
                {
                    ExtensionInstallDone(installableExtension.Header.Name);
                    return;
                }

                if (installableExtension == null)
                    return;
                ExtensionManager.InstallAsync(installableExtension, false);
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ExtensionManagerInstallCompleted(object sender, InstallCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                LogMessage(string.Format("Error while installing extension: {0}", e.Error.Message));
                return;<commit_msg>Bugfix: Update extension correctly<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Microsoft.VisualStudio.ExtensionManager;
using Microsoft.VisualStudio.ExtensionManager.UI;

namespace ExtensionSync
{
    public class ExtensionManagerFacade
    {

        public ExtensionManagerFacade(IVsExtensionManager visualStudioExtensionManager,
                                      IVsExtensionRepository visualStudioExtensionRepository)
        {
            ExtensionManager = visualStudioExtensionManager;
            ExtensionRepository = visualStudioExtensionRepository;

            processingTimer.Elapsed += (sender, e) => ClearExtensionManagerEventHandlers();
        }

        public event Action<string> Log;

        public List<ExtensionInformation> GetInstalledExtensionsInformation()
        {
            var installedExtensions = ExtensionManager.GetInstalledExtensions();
            var userExtensions = installedExtensions.Where(ext =>
                        !ext.Header.SystemComponent && !ext.Header.InstalledByMsi)
                        .OrderBy(ext => ext.Header.Name);

            return userExtensions.Select(
                    e => new ExtensionInformation
                    {
                        Name = e.Header.Name,
                        Identifier = e.Header.Identifier,
                        Version = e.Header.Version
                    })
                    .ToList();
        }

        public void InstallExtensions(List<ExtensionInformation> extensions)
        {
            if (extensions == null || extensions.Count == 0)
                return;

            try
            {
                extensionsBeingInstalled.Clear();
                ExtensionRepository.DownloadCompleted += ExtensionRepositoryDownloadCompleted;
                ExtensionManager.InstallCompleted += ExtensionManagerInstallCompleted;

                foreach (var extension in extensions)
                {
                    extensionsBeingInstalled.Add(extension.Name);

                    var query = ExtensionRepository.CreateQuery<VSGalleryEntry>(false, true)
                                .OrderByDescending(v => v.Ranking)
                                .Skip(0)
                                .Take(25) as IVsExtensionRepositoryQuery<VSGalleryEntry>;
                    if (query == null) continue;

                    query.ExecuteCompleted += QueryExecuteCompleted;
                    query.SearchText = extension.Name;
                    query.ExecuteAsync(extension);
                }

                //Give it a a few minutes to do its work. If everything goes smoothly, event handlers should unbind.
                // Make a safety check and remove handlers if not already done
                processingTimer.Start();
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ClearExtensionManagerEventHandlers()
        {
            lock (this)
            {
                if (eventHandlersCleared) return;

                eventHandlersCleared = true;
                ExtensionRepository.DownloadCompleted -= ExtensionRepositoryDownloadCompleted;
                ExtensionManager.InstallCompleted -= ExtensionManagerInstallCompleted;

                processingTimer.Stop();
            }
        }

        public void UnInstallExtensions(List<ExtensionInformation> extensions, DateTimeOffset configUpdateDateTime)
        {
            if (extensions == null || extensions.Count == 0)
                return;

            var installedUserExtensions = ExtensionManager.GetInstalledExtensions().
                                    Where(e => !e.Header.SystemComponent).ToList();

            var extensionsInstalledAfterConfigUpdated = installedUserExtensions
                            .Where(i => i.InstalledOn > configUpdateDateTime).ToList();

            foreach (var extension in extensions)
            {
                try
                {
                    var extensionInformation = extension;
                    var userExtension =
                        installedUserExtensions.SingleOrDefault(e =>
                            e.Header.Name == extensionInformation.Name &&
                            e.Header.Identifier == extensionInformation.Identifier);
                    if (userExtension == null) continue;

                    if (extensionsInstalledAfterConfigUpdated.Contains(userExtension))
                    {
                        LogMessage(string.Format("Not uninstalling {0} since it was installed after last update to config file."
                            , userExtension.Header.Name));
                        continue;
                    }

                    LogMessage(string.Format("Uninstalling {0}", userExtension.Header.Name));
                    ExtensionManager.Uninstall(userExtension);
                }
                catch (Exception exception)
                {
                    LogMessage(string.Format("Error while uninstalling {0}: {1}", extension.Name, exception.Message));
                }
            }
        }

        private void QueryExecuteCompleted(object sender, ExecuteCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    LogMessage(string.Format("Error while searching online for extension: {0}", e.Error.Message));
                    return;
                }

                var extensionInformation = (ExtensionInformation)e.UserState;
                var entry =
                    e.Results.Cast<VSGalleryEntry>().SingleOrDefault(r =>
                        r.Name == extensionInformation.Name && r.VsixID == extensionInformation.Identifier);
                if (entry == null)
                {
                    LogMessage(string.Format("Could not find {0} in Online Repository", extensionInformation.Name));
                    ExtensionInstallDone(extensionInformation.Name);
                    return;
                }

                if (AutoUpdateExtensions)
                {
                    var installedExtensions = GetInstalledExtensionsInformation();
                    var installedExtension = installedExtensions.FirstOrDefault(ext => ext.Name == extensionInformation.Name
                                         &&
                                         ext.Identifier ==
                                         extensionInformation.Identifier);
                    if (installedExtension != null && installedExtension.Version.ToString() == entry.VsixVersion)
                    {
                        ExtensionInstallDone(extensionInformation.Name);
                        return;
                    }
                }

                ExtensionRepository.DownloadAsync(entry);
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ExtensionRepositoryDownloadCompleted(object sender, DownloadCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    LogMessage(string.Format("Error while downloading extension: {0}", e.Error.Message));
                    return;
                }

                var installableExtension = e.Payload;
                if (installableExtension == null)
                    return;

                var installedExtensions = GetInstalledExtensionsInformation();
                var installedExtension = installedExtensions.FirstOrDefault(i =>
                                                                            i.Name == installableExtension.Header.Name &&
                                                                            i.Identifier ==
                                                                            installableExtension.Header.Identifier);

                if (installedExtension != null)
                {
                    if (installedExtension.Version >= installableExtension.Header.Version)
                    {
                        ExtensionInstallDone(installableExtension.Header.Name);
                        return;
                    }
                    //extension needs to be updated - uninstall and install again
                    LogMessage(string.Format("{0} has an update available.", installableExtension.Header.Name));
                    UnInstallExtensions(new List<ExtensionInformation> { installedExtension }, DateTime.Now);
                }

                ExtensionManager.InstallAsync(installableExtension, false);
            }
            catch (Exception exception)
            {
                LogMessage(string.Format("Error while installing extensions: {0}", exception.Message));
            }
        }

        private void ExtensionManagerInstallCompleted(object sender, InstallCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                LogMessage(string.Format("Error while installing extension: {0}", e.Error.Message));
                return;
{'fraction_non_alphanumeric': 0.0723807425360802, 'fraction_numerical': 0.0018177812052440233, 'mean_word_length': 1.450398164394655, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 39, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2136965', 'n_tokens_mistral': 3744, 'n_tokens_neox': 3422, 'n_words': 751}