diff --git a/src/Shared/ReferenceItemExtensions.cs b/src/Shared/ReferenceItemExtensions.cs index 5179bb8..183852a 100644 --- a/src/Shared/ReferenceItemExtensions.cs +++ b/src/Shared/ReferenceItemExtensions.cs @@ -14,6 +14,18 @@ public static string ToFileLine(this ReferenceItem item) public static void SaveToFile(this List items, string outputFile) { + if (File.Exists(outputFile)) + { + var currentContents = File.ReadAllLines(outputFile); + var newContents = items.Select(item => item.ToFileLine()).ToArray(); + // Assuming order is the same for incremental builds, no sorting needed + if (currentContents.SequenceEqual(newContents)) + { + // No changes, skip writing to avoid updating the timestamp, which will trigger unnecessary rebuilds + return; + } + } + File.WriteAllLines(outputFile, items.Select(item => item.ToFileLine())); } diff --git a/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.TestBase.cs b/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.TestBase.cs index 3b4d2f4..85a95c4 100644 --- a/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.TestBase.cs +++ b/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.TestBase.cs @@ -143,7 +143,7 @@ internal async Task Build(string additionalArgs = "") { string buildArgs = $"build dirs.proj " + - $"-m:1 -t:Rebuild -restore -nologo -nodeReuse:false -noAutoResponse " + + $"-m:1 -restore -nologo -nodeReuse:false -noAutoResponse " + $"/p:Configuration=Debug " + $"/p:ReferenceProtectorTaskAssembly={Path.Combine(Directory.GetCurrentDirectory(), "ReferenceProtector.Tasks.dll")} " + $"/v:m" + diff --git a/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.Tests.cs b/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.Tests.cs index 4dbe857..7a6ea21 100644 --- a/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.Tests.cs +++ b/src/Tasks/ReferenceProtector.Tasks.IntegrationTests/ReferenceProtector.Tasks.Tests.cs @@ -126,4 +126,28 @@ public async Task CollectAllReferences_PackageReferences_AreIncluded() Assert.Equal(expectedReferences, references); } + + /// + /// Verifies that the CollectAllReferences task does not update the reference file timestamp if no changes were made. + /// + [Fact] + public async Task CollectAllReferences_IncrememtalBuild_ReferenceTimestampIsNotUpdated() + { + CreateProject("A"); + CreateProject("B"); + await AddProjectReference("A", "B"); + await Build(); + + var generatedFiles1 = GetGeneratedReferencesFiles(); + var timeStamps1 = generatedFiles1.Select(File.GetLastWriteTimeUtc).ToList(); + + // Rebuild without any changes + await Build(); + + var generatedFiles2 = GetGeneratedReferencesFiles(); + var timeStamps2 = generatedFiles2.Select(File.GetLastWriteTimeUtc).ToList(); + + Assert.Equal(generatedFiles1, generatedFiles2); + Assert.Equal(timeStamps1, timeStamps2); + } } \ No newline at end of file diff --git a/src/Tasks/ReferenceProtector.Tasks/CollectAllReferences.cs b/src/Tasks/ReferenceProtector.Tasks/CollectAllReferences.cs index c48df6b..274bbfc 100644 --- a/src/Tasks/ReferenceProtector.Tasks/CollectAllReferences.cs +++ b/src/Tasks/ReferenceProtector.Tasks/CollectAllReferences.cs @@ -82,7 +82,9 @@ public override bool Execute() if (OutputFile is not null) { - references.SaveToFile(OutputFile); + // Is sorted to ensure consistent ordering for easier testing and to avoid unnecessary diffs + // May not needed, if msbuild guarantees a consistent order + references.OrderBy(x => (x.Source, x.Target, x.LinkType)).ToList().SaveToFile(OutputFile); return true; }