Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/MarkdownSnippets/Processing/DirectoryMarkdownProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,14 +340,36 @@ void WriteLines(string target, List<Line> lines)
// and reduces the chance of colliding with another process reading the file
// (e.g. a parallel build packing a nuget that consumes the same markdown).
if (File.Exists(target) &&
File.ReadAllText(target) == content)
ReadAllTextWithRetry(target) == content)
{
return;
}

WriteAllTextWithRetry(target, content);
}

static string? ReadAllTextWithRetry(string target)
{
const int maxAttempts = 5;
for (var attempt = 1; ; attempt++)
{
try
{
return File.ReadAllText(target);
}
catch (IOException) when (attempt < maxAttempts)
{
// Another process is writing the file. Back off briefly and retry.
Thread.Sleep(100 * attempt);
}
catch (IOException)
{
// Still locked: treat as changed and let the write path deal with it
return null;
}
}
}

static void WriteAllTextWithRetry(string target, string content)
{
const int maxAttempts = 5;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Local

snippet: sourceFile.txt

Relative Local

snippet: ./sourceFile.txt

Rooted

snippet: /sourceFile.txt

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
From Source File
3 changes: 2 additions & 1 deletion src/Tests/DirectoryMarkdownProcessorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,8 @@ public Task FileSnippetExplicitIncludeBypassesExcludeSnippetFiles()
// `begin-snippet`/`end-snippet` markers, but an explicit `snippet: sourceFile.txt`
// in a markdown file must still resolve to the whole-file contents — that lookup
// goes through allFiles, which remains unfiltered.
var root = Path.GetFullPath("DirectoryMarkdownProcessor/FileSnippet");
// Own copy of the FileSnippet fixture, so it does not race FileSnippet writing the same one.md
var root = Path.GetFullPath("DirectoryMarkdownProcessor/FileSnippetExplicitInclude");
var processor = new DirectoryMarkdownProcessor(
root,
writeHeader: false,
Expand Down
Loading