You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.6 KiB

  1. using IPA.Logging;
  2. using IPA.Utilities;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.Specialized;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. namespace IPA.Updating.Backup
  10. {
  11. /// <summary>
  12. /// A unit for backup. WIP.
  13. /// </summary>
  14. internal class BackupUnit
  15. {
  16. public string Name { get; private set; }
  17. private DirectoryInfo _BackupPath;
  18. private List<string> _Files = new List<string>();
  19. private FileInfo _ManifestFile;
  20. private static string _ManifestFileName = "$manifest$.txt";
  21. public BackupUnit(string path) : this(path, DateTime.Now.ToString("yyyy-MM-dd_h-mm-ss"))
  22. {
  23. }
  24. internal BackupUnit(string path, string name)
  25. {
  26. Name = name;
  27. _BackupPath = new DirectoryInfo(Path.Combine(path, Name));
  28. _ManifestFile = new FileInfo(Path.Combine(_BackupPath.FullName, _ManifestFileName));
  29. }
  30. public static BackupUnit FromDirectory(DirectoryInfo directory, string backupPath)
  31. {
  32. var unit = new BackupUnit(backupPath, directory.Name);
  33. // Read Manifest
  34. if (unit._ManifestFile.Exists)
  35. {
  36. string manifest = File.ReadAllText(unit._ManifestFile.FullName);
  37. foreach (var line in manifest.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
  38. unit._Files.Add(line);
  39. }
  40. else
  41. {
  42. foreach (var file in directory.GetFiles("*", SearchOption.AllDirectories))
  43. {
  44. if (file.Name == _ManifestFileName) continue;
  45. var relativePath = file.FullName.Substring(directory.FullName.Length + 1);
  46. unit._Files.Add(relativePath);
  47. }
  48. }
  49. return unit;
  50. }
  51. public void Add(string file)
  52. {
  53. Add(new FileInfo(file));
  54. }
  55. internal void Delete()
  56. {
  57. if (_BackupPath.Exists)
  58. _BackupPath.Delete(true);
  59. }
  60. /// <summary>
  61. /// Adds a file to the list of changed files and backups it.
  62. /// </summary>
  63. /// <param name="file"></param>
  64. public void Add(FileInfo file)
  65. {
  66. var relativePath = LoneFunctions.GetRelativePath(file.FullName, Environment.CurrentDirectory);
  67. var backupPath = new FileInfo(Path.Combine(_BackupPath.FullName, relativePath));
  68. Logger.updater.Debug($"rp={relativePath}, bp={backupPath}");
  69. if (_Files.Contains(relativePath))
  70. {
  71. Logger.updater.Debug($"Skipping backup of {relativePath}");
  72. return;
  73. }
  74. // Copy over
  75. backupPath.Directory.Create();
  76. if (file.Exists)
  77. {
  78. file.CopyTo(backupPath.FullName);
  79. }
  80. else
  81. {
  82. // Make empty file
  83. backupPath.Create().Close();
  84. }
  85. if (!File.Exists(_ManifestFile.FullName))
  86. _ManifestFile.Create().Close();
  87. var stream = _ManifestFile.AppendText();
  88. stream.WriteLine(relativePath);
  89. stream.Close();
  90. // Add to list
  91. _Files.Add(relativePath);
  92. }
  93. /// <summary>
  94. /// Reverts the changes made in this unit.
  95. /// </summary>
  96. public void Restore()
  97. {
  98. foreach (var relativePath in _Files)
  99. {
  100. Logger.updater.Debug($"Restoring {relativePath}");
  101. // Original version
  102. var backupFile = new FileInfo(Path.Combine(_BackupPath.FullName, relativePath));
  103. var target = new FileInfo(Path.Combine(Environment.CurrentDirectory, relativePath));
  104. if (backupFile.Exists)
  105. {
  106. if (backupFile.Length > 0)
  107. {
  108. Logger.updater.Debug($" {backupFile.FullName} => {target.FullName}");
  109. target.Directory.Create();
  110. backupFile.CopyTo(target.FullName, true);
  111. }
  112. else
  113. {
  114. Logger.updater.Debug($" x {target.FullName}");
  115. if (target.Exists)
  116. {
  117. target.Delete();
  118. }
  119. }
  120. }
  121. else
  122. {
  123. Logger.updater.Error("Backup not found!");
  124. }
  125. }
  126. }
  127. }
  128. }