Skip to content

Commit eaa7a45

Browse files
committed
chore: add fast template file copy path
1 parent e2c7415 commit eaa7a45

File tree

1 file changed

+54
-6
lines changed

1 file changed

+54
-6
lines changed

src/Docfx.Build/TemplateProcessors/TemplateProcessor.cs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Concurrent;
5-
5+
using System.Diagnostics;
66
using Docfx.Common;
77
using Docfx.Plugins;
88

@@ -107,26 +107,45 @@ private void CopyTemplateResources(string outputDirectory, IEnumerable<TemplateB
107107
{
108108
foreach (var resourceInfo in templateBundles.SelectMany(s => s.Resources).Distinct())
109109
{
110+
var resourceKey = resourceInfo.ResourceKey;
111+
110112
try
111113
{
112-
using var stream = _resourceProvider.GetResourceStream(resourceInfo.ResourceKey);
113-
CopyTemplateResource(stream, outputDirectory, resourceInfo.ResourceKey);
114+
using var stream = _resourceProvider.GetResourceStream(resourceKey);
115+
116+
if (stream is FileStream fileStream)
117+
{
118+
CopyTemplateResourceFile(new FileInfo(fileStream.Name), outputDirectory, resourceKey);
119+
}
120+
else
121+
{
122+
CopyTemplateResourceStream(stream, outputDirectory, resourceKey);
123+
}
114124
}
115125
catch (Exception e)
116126
{
117-
Logger.Log(LogLevel.Info, $"Unable to get relative resource for {resourceInfo.ResourceKey}: {e.Message}");
127+
Logger.Log(LogLevel.Info, $"Unable to get relative resource for {resourceKey}: {e.Message}");
118128
}
119129
}
120130
}
121131

122-
private static void CopyTemplateResource(Stream stream, string outputDirectory, string filePath)
132+
/// <summary>
133+
/// Copy template resource from stream.
134+
/// </summary>
135+
private static void CopyTemplateResourceStream(Stream stream, string outputDirectory, string filePath)
123136
{
124137
if (stream != null)
125138
{
126139
var path = Path.Combine(outputDirectory, filePath);
127140
Directory.CreateDirectory(Path.GetFullPath(Path.GetDirectoryName(path)));
128141

129-
using (var writer = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
142+
using (var writer = new FileStream(path, new FileStreamOptions
143+
{
144+
Mode = FileMode.Create,
145+
Access = FileAccess.Write,
146+
Share = FileShare.None,
147+
PreallocationSize = stream.Length,
148+
}))
130149
{
131150
stream.CopyTo(writer);
132151
}
@@ -139,6 +158,35 @@ private static void CopyTemplateResource(Stream stream, string outputDirectory,
139158
}
140159
}
141160

161+
/// <summary>
162+
/// Copy template resource as file.
163+
/// </summary>
164+
private static void CopyTemplateResourceFile(FileInfo inputFileInfo, string outputDirectory, string filePath)
165+
{
166+
Debug.Assert(inputFileInfo.Exists);
167+
168+
var path = Path.Combine(outputDirectory, filePath);
169+
var outputFileInfo = new FileInfo(path);
170+
outputFileInfo.Directory.Create();
171+
172+
bool isOverwrite = outputFileInfo.Exists;
173+
174+
// Skip file copy if following condition met.
175+
bool skipFileCopy = isOverwrite // Output file is already exists.
176+
&& inputFileInfo.Length == outputFileInfo.Length // File's lengths are identical.
177+
&& inputFileInfo.LastWriteTimeUtc == outputFileInfo.LastWriteTimeUtc; // File's LastWriteTimeUtc are identical.
178+
if (skipFileCopy)
179+
{
180+
Logger.Log(LogLevel.Verbose, $"Skipped resource {filePath} that template dependants on to {outputFileInfo.FullName}");
181+
return;
182+
}
183+
else
184+
{
185+
File.Copy(inputFileInfo.FullName, outputFileInfo.FullName, isOverwrite); // Use `File.Copy` API to preserve LastWriteTime.
186+
Logger.Log(LogLevel.Verbose, $"Saved resource {filePath} that template dependants on to {outputFileInfo.FullName}");
187+
}
188+
}
189+
142190
private List<ManifestItem> ProcessCore(List<InternalManifestItem> items, ApplyTemplateSettings settings, IDictionary<string, object> globals)
143191
{
144192
var manifest = new ConcurrentBag<ManifestItem>();

0 commit comments

Comments
 (0)