Skip to content

Commit

Permalink
ContentItemsPredictor: Add support for ContentWithTargetPath items (#124
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dfederm authored Jan 7, 2025
1 parent 155f160 commit 557f0c7
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 12 deletions.
10 changes: 8 additions & 2 deletions src/BuildPrediction/MsBuildHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,22 @@ public static bool ShouldCopyToOutputDirectory(this ProjectItemInstance item)
}

/// <summary>
/// Determins what the TargetPath metadata would be set to after calling the AssignTargetPath task.
/// Determines what the TargetPath metadata would be set to after calling the AssignTargetPath task.
/// </summary>
/// <remarks>
/// See: https://github.com/microsoft/msbuild/blob/master/src/Tasks/AssignTargetPath.cs.
/// </remarks>
public static string GetTargetPath(this ProjectItemInstance item)
{
string link = item.GetMetadataValue("Link");
// If TargetPath is already set, it takes priority.
string targetPath = item.GetMetadataValue("TargetPath");
if (!string.IsNullOrEmpty(targetPath))
{
return targetPath;
}

// If file has a link, use that.
string link = item.GetMetadataValue("Link");
if (!string.IsNullOrEmpty(link))
{
return link;
Expand Down
16 changes: 16 additions & 0 deletions src/BuildPrediction/Predictors/ContentItemsPredictor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public sealed class ContentItemsPredictor : IProjectPredictor
{
internal const string OutDirPropertyName = "OutDir";
internal const string ContentItemName = "Content";
internal const string ContentWithTargetPathItemName = "ContentWithTargetPath";

/// <inheritdoc/>
public void PredictInputsAndOutputs(
Expand All @@ -34,6 +35,21 @@ public void PredictInputsAndOutputs(
}
}
}

foreach (ProjectItemInstance item in projectInstance.GetItems(ContentWithTargetPathItemName))
{
predictionReporter.ReportInputFile(item.EvaluatedInclude);

if (!string.IsNullOrEmpty(outDir) && item.ShouldCopyToOutputDirectory())
{
// Note: Using TargetPath directly instead of GetTargetPath since ContentWithTargetPath items don't have AssignTargetPath called on them.
string targetPath = item.GetMetadataValue("TargetPath");
if (!string.IsNullOrEmpty(targetPath))
{
predictionReporter.ReportOutputFile(Path.Combine(outDir, targetPath));
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private static void PredictInputsAndOutputs(

// Process each item type considered in GetCopyToOutputDirectoryItems. Yes, Compile is considered.
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, ContentItemsPredictor.ContentItemName, outDir, predictionReporter);
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, ContentItemsPredictor.ContentWithTargetPathItemName, outDir, predictionReporter);
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, EmbeddedResourceItemsPredictor.EmbeddedResourceItemName, outDir, predictionReporter);
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, CompileItemsPredictor.CompileItemName, outDir, predictionReporter);
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, NoneItemsPredictor.NoneItemName, outDir, predictionReporter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private static void ReportCopyToPublishDirectoryItems(
{
// Process each item type considered in GetCopyToPublishDirectoryItems. Yes, Compile is considered.
ReportCopyToPublishDirectoryItems(projectInstance, ContentItemsPredictor.ContentItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, ContentItemsPredictor.ContentWithTargetPathItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, EmbeddedResourceItemsPredictor.EmbeddedResourceItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, CompileItemsPredictor.CompileItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, NoneItemsPredictor.NoneItemName, publishDir, predictionReporter);
Expand Down
13 changes: 9 additions & 4 deletions src/BuildPredictionTests/MsBuildHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,26 @@ public void ShouldCopyToOutputDirectory(string copyToOutputDirectoryValue, bool

[Theory]
[InlineData("Foo.xml", null, "Foo.xml")]
[InlineData("Foo.xml", @"Bar\Baz.xml", @"Bar\Baz.xml")]
[InlineData("Foo.xml", @"Link=Bar\Baz.xml", @"Bar\Baz.xml")]
[InlineData("Foo.xml", @"TargetPath=Bar\Baz.xml;Link=ShouldNotBeUsed.xml", @"Bar\Baz.xml")]
[InlineData(@".\.\.\X\.\.\.\.\Foo.xml", null, @"X\Foo.xml")]
[InlineData(@"{ProjectDir}\X\Foo.xml", null, @"X\Foo.xml")]
[InlineData(@"{ProjectDir}\.\.\.\.\X\.\.\.\Foo.xml", null, @"X\Foo.xml")]
[InlineData(@"{ProjectDir}\..\..\..\X\Y\Z\Foo.xml", null, @"Foo.xml")]
public void GetTargetPath(string itemIdentity, string linkValue, string expectedResult)
public void GetTargetPath(string itemIdentity, string properties, string expectedResult)
{
ProjectRootElement projectRootElement = ProjectRootElement.Create();

itemIdentity = itemIdentity.Replace("{ProjectDir}", projectRootElement.DirectoryPath, StringComparison.Ordinal);
ProjectItemElement item = projectRootElement.AddItem("Foo", itemIdentity);

if (!string.IsNullOrEmpty(linkValue))
if (properties is not null)
{
item.AddMetadata("Link", linkValue);
foreach (string property in properties.Split(';'))
{
string[] propertyParts = property.Split(['='], 2);
item.AddMetadata(propertyParts[0], propertyParts[1]);
}
}

ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);
Expand Down
38 changes: 32 additions & 6 deletions src/BuildPredictionTests/Predictors/ContentItemsPredictorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,25 @@ public void NoCopy()
{
ProjectRootElement projectRootElement = ProjectRootElement.Create();
projectRootElement.AddProperty(ContentItemsPredictor.OutDirPropertyName, @"bin\");
projectRootElement.AddItem(ContentItemsPredictor.ContentItemName, "Foo.xml");

ProjectItemElement item1 = projectRootElement.AddItem(ContentItemsPredictor.ContentItemName, "Foo.xml");

ProjectItemElement item2 = projectRootElement.AddItem(ContentItemsPredictor.ContentWithTargetPathItemName, "Bar.xml");
item2.AddMetadata("TargetPath", @"bin\Bar.xml");

ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);

PredictedItem[] expectedInputFiles =
[
new PredictedItem("Foo.xml", nameof(ContentItemsPredictor)),
new PredictedItem("Bar.xml", nameof(ContentItemsPredictor)),
];

new ContentItemsPredictor()
.GetProjectPredictions(projectInstance)
.AssertPredictions(
projectInstance,
new[] { new PredictedItem("Foo.xml", nameof(ContentItemsPredictor)) },
expectedInputFiles,
null,
null,
null);
Expand All @@ -35,18 +45,34 @@ public void WithCopy()
ProjectRootElement projectRootElement = ProjectRootElement.Create();
projectRootElement.AddProperty(ContentItemsPredictor.OutDirPropertyName, @"bin\");

ProjectItemElement item = projectRootElement.AddItem(ContentItemsPredictor.ContentItemName, "Foo.xml");
item.AddMetadata("CopyToOutputDirectory", "PreserveNewest");
ProjectItemElement item1 = projectRootElement.AddItem(ContentItemsPredictor.ContentItemName, "Foo.xml");
item1.AddMetadata("CopyToOutputDirectory", "PreserveNewest");

ProjectItemElement item2 = projectRootElement.AddItem(ContentItemsPredictor.ContentWithTargetPathItemName, "Bar.xml");
item2.AddMetadata("CopyToOutputDirectory", "PreserveNewest");
item2.AddMetadata("TargetPath", @"Bar\Bar.xml");

ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);

PredictedItem[] expectedInputFiles =
[
new PredictedItem("Foo.xml", nameof(ContentItemsPredictor)),
new PredictedItem("Bar.xml", nameof(ContentItemsPredictor)),
];

PredictedItem[] expectedOutputFiles =
[
new PredictedItem(@"bin\Foo.xml", nameof(ContentItemsPredictor)),
new PredictedItem(@"bin\Bar\Bar.xml", nameof(ContentItemsPredictor)),
];

new ContentItemsPredictor()
.GetProjectPredictions(projectInstance)
.AssertPredictions(
projectInstance,
new[] { new PredictedItem("Foo.xml", nameof(ContentItemsPredictor)) },
expectedInputFiles,
null,
new[] { new PredictedItem(@"bin\Foo.xml", nameof(ContentItemsPredictor)) },
expectedOutputFiles,
null);
}
}
Expand Down

0 comments on commit 557f0c7

Please sign in to comment.