Ejemplo n.º 1
0
        /// <summary>
        /// Reads the existing backup manifests matching the given source directory.
        /// </summary>
        /// <remarks>
        /// Manifests are matched by comparing their source directories to <paramref name="sourcePath"/>. <br/>
        /// The comparison ignores case, so this only works on Windows. <br/>
        /// The comparison only considers the literal path, e.g. symbolic links are not resolved.
        /// </remarks>
        /// <param name="sourcePath">The source directory to match.</param>
        /// <param name="targetPath">The target directory which is being examined.</param>
        /// <param name="index">The backup index detailing all the existing backups in <paramref name="targetPath"/>.
        /// If <c>null</c>, no manifests are matched.</param>
        /// <returns>A list of the matched backups, in unspecified order.</returns>
        private List <BackupMetadata> ReadPreviousBackups(string sourcePath, string targetPath, BackupIndex?index)
        {
            if (index is null)
            {
                return(new());
            }

            List <BackupMetadata> previousBackups = new();

            foreach (var pair in index.Backups)
            {
                var backupName       = pair.Key;
                var backupSourcePath = pair.Value;

                // Paths are assumed to be already normalised.
                if (Utility.PathEqual(sourcePath, backupSourcePath))
                {
                    var backupPath = Path.Join(targetPath, backupName);

                    var             startInfoFilePath = BackupMeta.StartInfoFilePath(backupPath);
                    BackupStartInfo startInfo;
                    try {
                        startInfo = BackupStartInfoReader.Read(startInfoFilePath);
                    }
                    catch (BackupStartInfoFileException e) {
                        Logger.Warning($"Failed to read metadata of previous backup \"{backupName}\": {e.Message}");
                        continue;
                    }

                    // We could just assume the index file and start info file are consistent, but it might be a
                    // good idea to check just in case something goes particularly wrong.
                    if (!Utility.PathEqual(sourcePath, startInfo.SourcePath))
                    {
                        Logger.Warning(
                            $"Source directory of backup start info in previous backup \"{backupName}\" doesn't match backup index");
                        continue;
                    }

                    var            manifestFilePath = BackupMeta.ManifestFilePath(backupPath);
                    BackupManifest manifest;
                    try {
                        manifest = BackupManifestReader.Read(manifestFilePath);
                    }
                    catch (BackupManifestFileException e) {
                        Logger.Warning($"Failed to read metadata of previous backup \"{backupName}\": {e.Message}");
                        continue;
                    }

                    previousBackups.Add(new(backupName, startInfo, manifest));
                }
            }

            Logger.Info(
                $"{previousBackups.Count} previous backups found in target directory for this source directory");
            return(previousBackups);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates the backup directory, the log file, the start info file, and the manifest writer.
        /// </summary>
        /// <param name="sourcePath">The path of the backup source directory.</param>
        /// <param name="targetPath">The path of the backup target directory.</param>
        /// <returns>A tuple of the backup directory name and manifest writer.</returns>
        /// <exception cref="ApplicationRuntimeError">If the backup directory, start info file, or manifest writer
        /// can't be created.</exception>
        public (string, BackupManifestWriter) InitialiseBackup(string sourcePath, string targetPath)
        {
            string backupName;

            try {
                backupName = BackupMeta.CreateBackupDirectory(targetPath);
            }
            catch (BackupDirectoryCreateException) {
                throw new ApplicationRuntimeError("Failed to create new backup directory");
            }
            Logger.Info($"Backup name: {backupName}");
            var backupPath = BackupMeta.BackupPath(targetPath, backupName);

            Logger.Info($"Created backup directory \"{backupPath}\"");

            var logFilePath = BackupMeta.LogFilePath(backupPath);

            try {
                Logger.FileHandler = new(logFilePath);
                Logger.Info($"Created log file \"{logFilePath}\"");
            }
            catch (LoggingException e) {
                // Not much we can do if we can't create the log file, just ignore and continue.
                Logger.Warning(e.Message);
            }

            var manifestFilePath = BackupMeta.ManifestFilePath(backupPath);
            BackupManifestWriter manifestWriter;

            try {
                manifestWriter = new(manifestFilePath);
            }
            catch (BackupManifestFileIOException e) {
                throw new ApplicationRuntimeError(
                          $"Failed to create backup manifest file \"{manifestFilePath}\": {e.InnerException.Reason}");
            }
            Logger.Info($"Created backup manifest file \"{manifestFilePath}\"");

            BackupStartInfo startInfo         = new(sourcePath, DateTime.UtcNow);
            var             startInfoFilePath = BackupMeta.StartInfoFilePath(backupPath);

            try {
                BackupStartInfoWriter.Write(startInfoFilePath, startInfo);
            }
            catch (BackupStartInfoFileIOException e) {
                throw new ApplicationRuntimeError(
                          $"Failed to write backup start info file \"{startInfoFilePath}\": {e.InnerException.Reason}");
            }
            Logger.Info($"Created backup start info file \"{startInfoFilePath}\"");

            return(backupName, manifestWriter);
        }