UpdateUtility.cs 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using System.IO;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using SingularityGroup.HotReload.Editor.Cli;
  6. using SingularityGroup.HotReload.RuntimeDependencies;
  7. using UnityEditor;
  8. #if UNITY_EDITOR_WIN
  9. using System.Diagnostics;
  10. using Debug = UnityEngine.Debug;
  11. #endif
  12. namespace SingularityGroup.HotReload.Editor {
  13. static class UpdateUtility {
  14. public static async Task<string> Update(string version, IProgress<float> progress, CancellationToken cancellationToken) {
  15. await ThreadUtility.SwitchToThreadPool();
  16. string serverDir;
  17. if(!CliUtils.TryFindServerDir(out serverDir)) {
  18. progress?.Report(1);
  19. return "unable to locate hot reload package";
  20. }
  21. var packageDir = Path.GetDirectoryName(Path.GetFullPath(serverDir));
  22. var cacheDir = Path.GetFullPath(PackageConst.LibraryCachePath);
  23. if(Path.GetPathRoot(packageDir) != Path.GetPathRoot(cacheDir)) {
  24. progress?.Report(1);
  25. return "unable to update package because it is located on a different drive than the unity project";
  26. }
  27. var updatedPackageCopy = BackupPackage(packageDir, version);
  28. var key = $"{DownloadUtility.GetPackagePrefix(version)}/HotReload.zip";
  29. var url = DownloadUtility.GetDownloadUrl(key);
  30. var targetFileName = $"HotReload{version.Replace('.', '-')}.zip";
  31. var targetFilePath = CliUtils.GetTempDownloadFilePath(targetFileName);
  32. var proxy = new Progress<float>(f => progress?.Report(f * 0.7f));
  33. var result = await DownloadUtility.DownloadFile(url, targetFilePath, proxy, cancellationToken).ConfigureAwait(false);
  34. if(result.error != null) {
  35. progress?.Report(1);
  36. return result.error;
  37. }
  38. PackageUpdater.UpdatePackage(targetFilePath, updatedPackageCopy);
  39. progress?.Report(0.8f);
  40. var packageRecycleBinDir = PackageConst.LibraryCachePath + $"/PackageArchived-{version}-{Guid.NewGuid():N}";
  41. try {
  42. Directory.Move(packageDir, packageRecycleBinDir);
  43. Directory.Move(updatedPackageCopy, packageDir);
  44. } catch {
  45. // fallback to replacing files individually if access to the folder is denied
  46. PackageUpdater.UpdatePackage(targetFilePath, packageDir);
  47. }
  48. try {
  49. Directory.Delete(packageRecycleBinDir, true);
  50. } catch (IOException) {
  51. //ignored
  52. }
  53. progress?.Report(1);
  54. return null;
  55. }
  56. static string BackupPackage(string packageDir, string version) {
  57. var backupPath = PackageConst.LibraryCachePath + $"/PackageBackup-{version}";
  58. if(Directory.Exists(backupPath)) {
  59. Directory.Delete(backupPath, true);
  60. }
  61. DirectoryCopy(packageDir, backupPath);
  62. return backupPath;
  63. }
  64. static void DirectoryCopy(string sourceDirPath, string destDirPath) {
  65. var rootSource = new DirectoryInfo(sourceDirPath);
  66. var sourceDirs = rootSource.GetDirectories();
  67. // ensure destination directory exists
  68. Directory.CreateDirectory(destDirPath);
  69. // Get the files in the directory and copy them to the new destination
  70. var files = rootSource.GetFiles();
  71. foreach (var file in files) {
  72. string temppath = Path.Combine(destDirPath, file.Name);
  73. var copy = file.CopyTo(temppath);
  74. copy.LastWriteTimeUtc = file.LastWriteTimeUtc;
  75. }
  76. // copying subdirectories, and their contents to destination
  77. foreach (var subdir in sourceDirs) {
  78. string subDirDestPath = Path.Combine(destDirPath, subdir.Name);
  79. DirectoryCopy(subdir.FullName, subDirDestPath);
  80. }
  81. }
  82. }
  83. }