|
1 | 1 | using System; |
2 | 2 | using System.IO; |
| 3 | +using System.Reflection; |
3 | 4 | using Testably.Abstractions.Testing.FileSystemInitializer; |
| 5 | +using Testably.Abstractions.Testing.Helpers; |
4 | 6 |
|
5 | 7 | namespace Testably.Abstractions.Testing; |
6 | 8 |
|
@@ -56,4 +58,113 @@ public static IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory( |
56 | 58 | { |
57 | 59 | return new DirectoryCleaner(fileSystem, prefix, logger); |
58 | 60 | } |
| 61 | + |
| 62 | + /// <summary> |
| 63 | + /// </summary> |
| 64 | + /// <param name="fileSystem">The file system.</param> |
| 65 | + /// <param name="assembly">The assembly in which the embedded resource files are located.</param> |
| 66 | + /// <param name="directoryPath">The directory path in which the found resource files are created.</param> |
| 67 | + /// <param name="relativePath">The relative path of the embedded resources in the <paramref name="assembly" />.</param> |
| 68 | + /// <param name="searchPattern"> |
| 69 | + /// The search string to match against the names of embedded resources in the <paramref name="assembly" /> under |
| 70 | + /// <paramref name="relativePath" />.<br /> |
| 71 | + /// This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't |
| 72 | + /// support regular expressions. |
| 73 | + /// </param> |
| 74 | + /// <param name="searchOption"> |
| 75 | + /// One of the enumeration values that specifies whether the search operation should include only the |
| 76 | + /// <paramref name="relativePath" /> or should include all subdirectories.<br /> |
| 77 | + /// The default value is <see cref="SearchOption.AllDirectories" />. |
| 78 | + /// </param> |
| 79 | + public static void InitializeEmbeddedResourcesFromAssembly(this IFileSystem fileSystem, |
| 80 | + string directoryPath, |
| 81 | + Assembly assembly, |
| 82 | + string? relativePath = null, |
| 83 | + string searchPattern = "*", |
| 84 | + SearchOption searchOption = SearchOption.AllDirectories) |
| 85 | + { |
| 86 | + EnumerationOptions enumerationOptions = |
| 87 | + EnumerationOptionsHelper.FromSearchOption(searchOption); |
| 88 | + |
| 89 | + string[] resourcePaths = assembly.GetManifestResourceNames(); |
| 90 | + string assemblyNamePrefix = $"{assembly.GetName().Name ?? ""}."; |
| 91 | + |
| 92 | + if (relativePath != null) |
| 93 | + { |
| 94 | + relativePath = relativePath.Replace( |
| 95 | + Path.AltDirectorySeparatorChar, |
| 96 | + Path.DirectorySeparatorChar); |
| 97 | + relativePath = relativePath.TrimEnd(Path.DirectorySeparatorChar); |
| 98 | + relativePath += Path.DirectorySeparatorChar; |
| 99 | + } |
| 100 | + |
| 101 | + foreach (string resourcePath in resourcePaths) |
| 102 | + { |
| 103 | + string fileName = resourcePath; |
| 104 | + if (fileName.StartsWith(assemblyNamePrefix)) |
| 105 | + { |
| 106 | + fileName = fileName.Substring(assemblyNamePrefix.Length); |
| 107 | + } |
| 108 | + |
| 109 | + fileName = fileName.Replace('.', Path.DirectorySeparatorChar); |
| 110 | + int lastSeparator = fileName.LastIndexOf(Path.DirectorySeparatorChar); |
| 111 | + if (lastSeparator > 0) |
| 112 | + { |
| 113 | + fileName = fileName.Substring(0, lastSeparator) + "." + |
| 114 | + fileName.Substring(lastSeparator + 1); |
| 115 | + } |
| 116 | + |
| 117 | + if (relativePath != null) |
| 118 | + { |
| 119 | + if (!fileName.StartsWith(relativePath)) |
| 120 | + { |
| 121 | + continue; |
| 122 | + } |
| 123 | + |
| 124 | + fileName = fileName.Substring(relativePath.Length); |
| 125 | + } |
| 126 | + |
| 127 | + if (!enumerationOptions.RecurseSubdirectories && |
| 128 | + fileName.IndexOf(Path.DirectorySeparatorChar) >= 0) |
| 129 | + { |
| 130 | + continue; |
| 131 | + } |
| 132 | + |
| 133 | + if (EnumerationOptionsHelper.MatchesPattern(enumerationOptions, |
| 134 | + fileName, searchPattern)) |
| 135 | + { |
| 136 | + string filePath = fileSystem.Path.Combine(directoryPath, fileName); |
| 137 | + fileSystem.InitializeFileFromEmbeddedResource(filePath, assembly, resourcePath); |
| 138 | + } |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + private static void InitializeFileFromEmbeddedResource(this IFileSystem fileSystem, |
| 143 | + string path, |
| 144 | + Assembly assembly, |
| 145 | + string embeddedResourcePath) |
| 146 | + { |
| 147 | + using (Stream? embeddedResourceStream = assembly |
| 148 | + .GetManifestResourceStream(embeddedResourcePath)) |
| 149 | + { |
| 150 | + if (embeddedResourceStream == null) |
| 151 | + { |
| 152 | + throw new ArgumentException( |
| 153 | + $"Resource '{embeddedResourcePath}' not found in assembly '{assembly.FullName}'", |
| 154 | + nameof(embeddedResourcePath)); |
| 155 | + } |
| 156 | + |
| 157 | + using (BinaryReader streamReader = new(embeddedResourceStream)) |
| 158 | + { |
| 159 | + byte[] fileData = streamReader.ReadBytes((int)embeddedResourceStream.Length); |
| 160 | + string? directoryPath = fileSystem.Path.GetDirectoryName(path); |
| 161 | + if (!string.IsNullOrEmpty(directoryPath)) |
| 162 | + { |
| 163 | + fileSystem.Directory.CreateDirectory(directoryPath); |
| 164 | + } |
| 165 | + |
| 166 | + fileSystem.File.WriteAllBytes(path, fileData); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
59 | 170 | } |
0 commit comments