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.

140 lines
4.7 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. namespace IPA.Patcher
  5. {
  6. /// <summary>
  7. /// A unit for backup. WIP.
  8. /// </summary>
  9. public class BackupUnit
  10. {
  11. private string Name { get; }
  12. private readonly DirectoryInfo _backupPath;
  13. private readonly PatchContext _context;
  14. private readonly List<string> _files = new List<string>();
  15. private readonly FileInfo _manifestFile;
  16. private static string _ManifestFileName = "$manifest$.txt";
  17. public BackupUnit(PatchContext context) : this(context, DateTime.Now.ToString("yyyy-MM-dd_h-mm-ss"))
  18. {
  19. }
  20. private BackupUnit(PatchContext context, string name)
  21. {
  22. Name = name;
  23. _context = context;
  24. _backupPath = new DirectoryInfo(Path.Combine(_context.BackupPath, Name));
  25. _manifestFile = new FileInfo(Path.Combine(_backupPath.FullName, _ManifestFileName));
  26. }
  27. public static BackupUnit FromDirectory(DirectoryInfo directory, PatchContext context)
  28. {
  29. var unit = new BackupUnit(context, directory.Name);
  30. // Read Manifest
  31. if (unit._manifestFile.Exists)
  32. {
  33. var manifest = File.ReadAllText(unit._manifestFile.FullName);
  34. foreach (var line in manifest.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
  35. unit._files.Add(line);
  36. }
  37. else
  38. {
  39. foreach (var file in directory.GetFiles("*", SearchOption.AllDirectories))
  40. {
  41. if (file.Name == _ManifestFileName) continue;
  42. var relativePath = file.FullName.Substring(directory.FullName.Length + 1);
  43. unit._files.Add(relativePath);
  44. }
  45. }
  46. return unit;
  47. }
  48. public void Add(string file)
  49. {
  50. Add(new FileInfo(file));
  51. }
  52. internal void Delete()
  53. {
  54. _backupPath.Delete(true);
  55. }
  56. /// <summary>
  57. /// Adds a file to the list of changed files and backups it.
  58. /// </summary>
  59. /// <param name="file">the file to add</param>
  60. public void Add(FileInfo file)
  61. {
  62. if(!file.FullName.StartsWith(_context.ProjectRoot))
  63. {
  64. Console.Error.WriteLine("Invalid file path for backup! {0}", file);
  65. return;
  66. }
  67. var relativePath = file.FullName.Substring(_context.ProjectRoot.Length + 1);
  68. var backupPath = new FileInfo(Path.Combine(_backupPath.FullName, relativePath));
  69. if(_files.Contains(relativePath))
  70. {
  71. Console.WriteLine("Skipping backup of {0}", 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. // don't do this bc its dumb
  85. }
  86. if (!File.Exists(_manifestFile.FullName))
  87. _manifestFile.Create().Close();
  88. var stream = _manifestFile.AppendText();
  89. stream.WriteLine(relativePath);
  90. stream.Close();
  91. // Add to list
  92. _files.Add(relativePath);
  93. }
  94. /// <summary>
  95. /// Reverts the changes made in this unit.
  96. /// </summary>
  97. public void Restore()
  98. {
  99. foreach(var relativePath in _files)
  100. {
  101. Console.WriteLine("Restoring {0}", relativePath);
  102. // Original version
  103. var backupFile = new FileInfo(Path.Combine(_backupPath.FullName, relativePath));
  104. var target = new FileInfo(Path.Combine(_context.ProjectRoot, relativePath));
  105. if (backupFile.Exists && backupFile.Length > 0)
  106. {
  107. Console.WriteLine(" {0} => {1}", backupFile.FullName, target.FullName);
  108. target.Directory?.Create();
  109. backupFile.CopyTo(target.FullName, true);
  110. }
  111. else
  112. {
  113. Console.WriteLine(" x {0}", target.FullName);
  114. if(target.Exists)
  115. {
  116. target.Delete();
  117. }
  118. }
  119. }
  120. }
  121. }
  122. }