Example #1
0
        private static bool UpdateFromArchive(ZipArchive archive, string targetDirectory)
        {
            if ((archive == null) || string.IsNullOrEmpty(targetDirectory))
            {
                ArchiLogger.LogNullError(nameof(archive) + " || " + nameof(targetDirectory));

                return(false);
            }

            // Firstly we'll move all our existing files to a backup directory
            string backupDirectory = Path.Combine(targetDirectory, SharedInfo.UpdateDirectory);

            foreach (string file in Directory.EnumerateFiles(targetDirectory, "*", SearchOption.AllDirectories))
            {
                string fileName = Path.GetFileName(file);

                if (string.IsNullOrEmpty(fileName))
                {
                    ArchiLogger.LogNullError(nameof(fileName));

                    return(false);
                }

                string relativeFilePath = RuntimeCompatibility.Path.GetRelativePath(targetDirectory, file);

                if (string.IsNullOrEmpty(relativeFilePath))
                {
                    ArchiLogger.LogNullError(nameof(relativeFilePath));

                    return(false);
                }

                string relativeDirectoryName = Path.GetDirectoryName(relativeFilePath);

                switch (relativeDirectoryName)
                {
                case null:
                    ArchiLogger.LogNullError(nameof(relativeDirectoryName));

                    return(false);

                case "":
                    // No directory, root folder
                    switch (fileName)
                    {
                    case SharedInfo.LogFile:
                    case "NLog.config":
                        // Files with those names in root directory we want to keep
                        continue;
                    }

                    break;

                case SharedInfo.ArchivalLogsDirectory:
                case SharedInfo.ConfigDirectory:
                case SharedInfo.DebugDirectory:
                case SharedInfo.PluginsDirectory:
                case SharedInfo.UpdateDirectory:
                    // Files in those directories we want to keep in their current place
                    continue;

                default:
                    // Files in subdirectories of those directories we want to keep as well
                    if (Utilities.RelativeDirectoryStartsWith(relativeDirectoryName, SharedInfo.ArchivalLogsDirectory, SharedInfo.ConfigDirectory, SharedInfo.DebugDirectory, SharedInfo.PluginsDirectory, SharedInfo.UpdateDirectory))
                    {
                        continue;
                    }

                    break;
                }

                string targetBackupDirectory = relativeDirectoryName.Length > 0 ? Path.Combine(backupDirectory, relativeDirectoryName) : backupDirectory;
                Directory.CreateDirectory(targetBackupDirectory);

                string targetBackupFile = Path.Combine(targetBackupDirectory, fileName);
                File.Move(file, targetBackupFile);
            }

            // We can now get rid of directories that are empty
            Utilities.DeleteEmptyDirectoriesRecursively(targetDirectory);

            if (!Directory.Exists(targetDirectory))
            {
                Directory.CreateDirectory(targetDirectory);
            }

            // Now enumerate over files in the zip archive, skip directory entries that we're not interested in (we can create them ourselves if needed)
            foreach (ZipArchiveEntry zipFile in archive.Entries.Where(zipFile => !string.IsNullOrEmpty(zipFile.Name)))
            {
                string file = Path.Combine(targetDirectory, zipFile.FullName);

                if (File.Exists(file))
                {
                    // This is possible only with files that we decided to leave in place during our backup function
                    // Those files should never be overwritten with anything, ignore
                    continue;
                }

                // Check if this file requires its own folder
                if (zipFile.Name != zipFile.FullName)
                {
                    string directory = Path.GetDirectoryName(file);

                    if (string.IsNullOrEmpty(directory))
                    {
                        ArchiLogger.LogNullError(nameof(directory));

                        return(false);
                    }

                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    // We're not interested in extracting placeholder files (but we still want directories created for them, done above)
                    switch (zipFile.Name)
                    {
                    case ".gitkeep":
                        continue;
                    }
                }

                zipFile.ExtractToFile(file);
            }

            return(true);
        }