public void UpdateGameDirectory(RootDirectoryEntity updated, string outputDir, IProgress <int> progress)
        {
            ManagedGameVersion   oldMGV        = _mvs.GetManagedVersions().First(mvg => mvg.Version == updated.Version);
            RootDirectoryEntity  oldBuild      = new RootDirectoryEntityIO().Deserialize(oldMGV.GameXML);
            HashSet <FileEntity> oldFiles      = oldBuild.GetAllFileEntities(true).OfType <FileEntity>().ToHashSet();
            HashSet <FileEntity> newFiles      = updated.GetAllFileEntities(true).OfType <FileEntity>().ToHashSet();
            HashSet <FileEntity> changedFiles  = newFiles.Except(oldFiles).ToHashSet();
            HashSet <FileEntity> filesToRemove = oldFiles.Except(newFiles).ToHashSet();

            // Do not remove files that only changed location
            HashSet <string>     newFilesHashes  = newFiles.Select(x => x.Hash).ToHashSet();
            HashSet <FileEntity> movedFileHashes = filesToRemove.Where(f => newFilesHashes.Contains(f.Hash)).ToHashSet();

            filesToRemove.ExceptWith(movedFileHashes);

            string container = Settings.Default.ContainerDirectory;
            List <RootDirectoryEntity> otherVersions = new List <RootDirectoryEntity>();

            foreach (var mgv in _mvs.GetManagedVersions().Except(new List <ManagedGameVersion>()
            {
                oldMGV
            }))
            {
                RootDirectoryEntity data = new RootDirectoryEntityIO().Deserialize(mgv.GameXML);
                otherVersions.Add(data);
            }

            int            basePercent     = 0;
            Progress <int> partialProgress = new Progress <int>(percent =>
            {
                progress.Report(basePercent + percent / 2);
            });

            // Remove old unused files from cache
            GameFilesRemover.RemoveFiles(filesToRemove,
                                         otherVersions,
                                         Helpers.EntityToPath(container),
                                         _dirCache,
                                         partialProgress
                                         );
            SaveDirCache();
            basePercent = 50;
            // Remove old unused files from game directory
            foreach (FileEntity unusedFile in filesToRemove)
            {
                string path = Path.Combine(oldMGV.Path, unusedFile.RelativePath);
                try
                {
                    File.Delete(path);
                }
                catch (Exception ex) { }
            }

            // Update files in directory
            CreateGameDirectory(updated, oldMGV.Path, partialProgress);
            progress.Report(100);
        }
        private string Compare(string path1, string path2)
        {
            string formatVersion(string version, IEnumerable <FileEntity> files, IEnumerable <FileEntity> unique) =>
            string.Format("Version: {0}\nNumber of files: {1:N0}\nSize: {2:N0} MB\nUnique files: {3:N0} ({4:N0} MB)",
                          version, files.Count(), files.Select(f => f.Size).Sum() / (1024 * 1024), unique.Count(), unique.Select(f => f.Size).Sum() / (1024 * 1024));

            RootDirectoryEntity first  = new RootDirectoryEntityIO().Deserialize(path1);
            RootDirectoryEntity second = new RootDirectoryEntityIO().Deserialize(path2);

            IEnumerable <FileEntity> firstFiles  = first.GetAllFileEntities(true).OfType <FileEntity>();
            IEnumerable <FileEntity> secondFiles = second.GetAllFileEntities(true).OfType <FileEntity>();

            IEnumerable <FileEntity> firstUnique  = firstFiles.Except(secondFiles);
            IEnumerable <FileEntity> secondUnique = secondFiles.Except(firstFiles);

            string message = string.Format("{0}\n\n{1}", formatVersion(first.Version, firstFiles, firstUnique), formatVersion(second.Version, secondFiles, secondUnique));

            return(message);
        }