Project Json mapping migration support
This commit is contained in:
parent
3a567e5957
commit
362f71a94a
17 changed files with 910 additions and 201 deletions
|
@ -7,7 +7,7 @@ namespace ConsoleApplication
|
||||||
public static int Main(string[] args)
|
public static int Main(string[] args)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Hello World!");
|
Console.WriteLine("Hello World!");
|
||||||
return 100;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,30 @@
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"emitEntryPoint": true,
|
"emitEntryPoint": true,
|
||||||
"copyToOutput": {
|
"copyToOutput": {
|
||||||
"include": "testcontentfile.txt"
|
"include": "testcontentfile.txt",
|
||||||
|
"mappings": {
|
||||||
|
"dir/mappingfile.txt":{
|
||||||
|
"include": "testcontentfile2.txt"
|
||||||
|
},
|
||||||
|
"out/": {
|
||||||
|
"include": ["project.json", "Program.cs"],
|
||||||
|
"exclude": ["Program.cs"],
|
||||||
|
"includeFiles": ["Program.cs"],
|
||||||
|
"excludeFiles": ["Program.cs"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.NETCore.App": "1.0.1"
|
"Microsoft.NETCore.App": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"type": "platform"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"netcoreapp1.0": {}
|
"netcoreapp1.0": {}
|
||||||
},
|
},
|
||||||
"publishOptions": {
|
"publishOptions": {
|
||||||
"include": "testcontentfile.txt"
|
"include": "testcontentfile.txt"
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"win7-x64": {},
|
|
||||||
"win7-x86": {},
|
|
||||||
"osx.10.10-x64": {},
|
|
||||||
"osx.10.11-x64": {},
|
|
||||||
"ubuntu.14.04-x64": {},
|
|
||||||
"ubuntu.16.04-x64": {},
|
|
||||||
"centos.7-x64": {},
|
|
||||||
"rhel.7.2-x64": {},
|
|
||||||
"debian.8-x64": {},
|
|
||||||
"fedora.23-x64": {},
|
|
||||||
"opensuse.13.2-x64": {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,79 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
{
|
{
|
||||||
public static class MSBuildExtensions
|
public static class MSBuildExtensions
|
||||||
{
|
{
|
||||||
|
public static bool IsEquivalentTo(this ProjectItemElement item, ProjectItemElement otherItem)
|
||||||
|
{
|
||||||
|
// Different includes
|
||||||
|
if (item.IntersectIncludes(otherItem).Count() != item.Includes().Count())
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine("ms: includes");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different Excludes
|
||||||
|
if (item.IntersectExcludes(otherItem).Count() != item.Excludes().Count())
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine("ms: excludes");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different remove
|
||||||
|
if (item.Remove != otherItem.Remove)
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine("ms: remove");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different Metadata
|
||||||
|
var metadataTuples = otherItem.Metadata.Select(m => Tuple.Create(m, item)).Concat(
|
||||||
|
item.Metadata.Select(m => Tuple.Create(m, otherItem)));
|
||||||
|
foreach (var metadataTuple in metadataTuples)
|
||||||
|
{
|
||||||
|
var metadata = metadataTuple.Item1;
|
||||||
|
var itemToCompare = metadataTuple.Item2;
|
||||||
|
|
||||||
|
var otherMetadata = itemToCompare.GetMetadataWithName(metadata.Name);
|
||||||
|
if (otherMetadata == null)
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine($"ms: metadata doesn't exist {{ {metadata.Name} {metadata.Value} }}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!metadata.ValueEquals(otherMetadata))
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine("ms: metadata has another value {{ {metadata.Name} {metadata.Value} {otherMetadata.Value} }}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ISet<string> ConditionChain(this ProjectElement projectElement)
|
||||||
|
{
|
||||||
|
var conditionChainSet = new HashSet<string>();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(projectElement.Condition))
|
||||||
|
{
|
||||||
|
conditionChainSet.Add(projectElement.Condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var parent in projectElement.AllParents)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(parent.Condition))
|
||||||
|
{
|
||||||
|
conditionChainSet.Add(parent.Condition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conditionChainSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ConditionChainsAreEquivalent(this ProjectElement projectElement, ProjectElement otherProjectElement)
|
||||||
|
{
|
||||||
|
return projectElement.ConditionChain().SetEquals(otherProjectElement.ConditionChain());
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<ProjectPropertyElement> PropertiesWithoutConditions(
|
public static IEnumerable<ProjectPropertyElement> PropertiesWithoutConditions(
|
||||||
this ProjectRootElement projectRoot)
|
this ProjectRootElement projectRoot)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +112,12 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
return SplitSemicolonDelimitedValues(item.Exclude);
|
return SplitSemicolonDelimitedValues(item.Exclude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> Removes(
|
||||||
|
this ProjectItemElement item)
|
||||||
|
{
|
||||||
|
return SplitSemicolonDelimitedValues(item.Remove);
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<string> AllConditions(this ProjectElement projectElement)
|
public static IEnumerable<string> AllConditions(this ProjectElement projectElement)
|
||||||
{
|
{
|
||||||
return new string[] { projectElement.Condition }.Concat(projectElement.AllParents.Select(p=> p.Condition));
|
return new string[] { projectElement.Condition }.Concat(projectElement.AllParents.Select(p=> p.Condition));
|
||||||
|
@ -49,6 +128,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
return item.Includes().Intersect(otherItem.Includes());
|
return item.Includes().Intersect(otherItem.Includes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> IntersectExcludes(this ProjectItemElement item, ProjectItemElement otherItem)
|
||||||
|
{
|
||||||
|
return item.Excludes().Intersect(otherItem.Excludes());
|
||||||
|
}
|
||||||
|
|
||||||
public static void RemoveIncludes(this ProjectItemElement item, IEnumerable<string> includesToRemove)
|
public static void RemoveIncludes(this ProjectItemElement item, IEnumerable<string> includesToRemove)
|
||||||
{
|
{
|
||||||
item.Include = string.Join(";", item.Includes().Except(includesToRemove));
|
item.Include = string.Join(";", item.Includes().Except(includesToRemove));
|
||||||
|
@ -64,11 +148,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
item.Exclude = string.Join(";", item.Excludes().Union(excludesToAdd));
|
item.Exclude = string.Join(";", item.Excludes().Union(excludesToAdd));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProjectMetadataElement GetMetadataWithName(this ProjectItemElement item, string name)
|
|
||||||
{
|
|
||||||
return item.Metadata.FirstOrDefault(m => m.Name.Equals(name, StringComparison.Ordinal));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool ValueEquals(this ProjectMetadataElement metadata, ProjectMetadataElement otherMetadata)
|
public static bool ValueEquals(this ProjectMetadataElement metadata, ProjectMetadataElement otherMetadata)
|
||||||
{
|
{
|
||||||
return metadata.Value.Equals(otherMetadata.Value, StringComparison.Ordinal);
|
return metadata.Value.Equals(otherMetadata.Value, StringComparison.Ordinal);
|
||||||
|
@ -90,6 +169,24 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProjectMetadataElement GetMetadataWithName(this ProjectItemElement item, string name)
|
||||||
|
{
|
||||||
|
return item.Metadata.FirstOrDefault(m => m.Name.Equals(name, StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasConflictingMetadata(this ProjectItemElement item, ProjectItemElement otherItem)
|
||||||
|
{
|
||||||
|
foreach (var metadata in item.Metadata)
|
||||||
|
{
|
||||||
|
if (otherItem.Metadata.Any(m => m.Name == metadata.Name && m.Value != metadata.Value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static void AddMetadata(this ProjectItemElement item, ProjectMetadataElement metadata)
|
public static void AddMetadata(this ProjectItemElement item, ProjectMetadataElement metadata)
|
||||||
{
|
{
|
||||||
var existingMetadata = item.GetMetadataWithName(metadata.Name);
|
var existingMetadata = item.GetMetadataWithName(metadata.Name);
|
||||||
|
|
|
@ -18,13 +18,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
public class ProjectMigrator
|
public class ProjectMigrator
|
||||||
{
|
{
|
||||||
// TODO: Migrate PackOptions
|
// TODO: Migrate PackOptions
|
||||||
// TODO: Support Mappings in IncludeContext Transformations
|
|
||||||
// TODO: Migrate Multi-TFM projects
|
// TODO: Migrate Multi-TFM projects
|
||||||
// TODO: Tests
|
// TODO: Tests
|
||||||
// TODO: Out of Scope
|
// TODO: Out of Scope
|
||||||
// - Globs that resolve to directories: /some/path/**/somedir
|
// - Globs that resolve to directories: /some/path/**/somedir
|
||||||
// - Migrating Deprecated project.jsons
|
// - Migrating Deprecated project.jsons
|
||||||
// - Configuration dependent source exclusion
|
|
||||||
|
|
||||||
private readonly IMigrationRule _ruleSet;
|
private readonly IMigrationRule _ruleSet;
|
||||||
|
|
||||||
|
@ -85,7 +83,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
if (diagnostics.Any())
|
if (diagnostics.Any())
|
||||||
{
|
{
|
||||||
MigrationErrorCodes.MIGRATE1011(
|
MigrationErrorCodes.MIGRATE1011(
|
||||||
$"{projectDirectory}{Environment.NewLine}{string.Join(Environment.NewLine, diagnostics.Select(d => d.Message))}")
|
$"{projectDirectory}{Environment.NewLine}{string.Join(Environment.NewLine, diagnostics.Select(d => FormatDiagnosticMessage(d)))}")
|
||||||
.Throw();
|
.Throw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +97,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string FormatDiagnosticMessage(DiagnosticMessage d)
|
||||||
|
{
|
||||||
|
return $"{d.Message} (line: {d.StartLine}, file: {d.SourceFilePath})";
|
||||||
|
}
|
||||||
|
|
||||||
private void SetupOutputDirectory(string projectDirectory, string outputDirectory)
|
private void SetupOutputDirectory(string projectDirectory, string outputDirectory)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(outputDirectory))
|
if (!Directory.Exists(outputDirectory))
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
new AddPropertyTransform<CommonCompilerOptions>("OutputType", "Exe",
|
new AddPropertyTransform<CommonCompilerOptions>("OutputType", "Exe",
|
||||||
compilerOptions => compilerOptions.EmitEntryPoint != null && compilerOptions.EmitEntryPoint.Value),
|
compilerOptions => compilerOptions.EmitEntryPoint != null && compilerOptions.EmitEntryPoint.Value),
|
||||||
new AddPropertyTransform<CommonCompilerOptions>("OutputType", "Library",
|
new AddPropertyTransform<CommonCompilerOptions>("OutputType", "Library",
|
||||||
compilerOptions => compilerOptions.EmitEntryPoint == null || !compilerOptions.EmitEntryPoint.Value)
|
compilerOptions => compilerOptions.EmitEntryPoint != null && !compilerOptions.EmitEntryPoint.Value)
|
||||||
};
|
};
|
||||||
|
|
||||||
private AddPropertyTransform<CommonCompilerOptions>[] KeyFileTransforms
|
private AddPropertyTransform<CommonCompilerOptions>[] KeyFileTransforms
|
||||||
|
@ -39,12 +39,12 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
|
|
||||||
private AddPropertyTransform<CommonCompilerOptions> DefineTransform => new AddPropertyTransform<CommonCompilerOptions>(
|
private AddPropertyTransform<CommonCompilerOptions> DefineTransform => new AddPropertyTransform<CommonCompilerOptions>(
|
||||||
"DefineConstants",
|
"DefineConstants",
|
||||||
compilerOptions => string.Join(";", compilerOptions.Defines),
|
compilerOptions => "$(DefineConstants);" + string.Join(";", compilerOptions.Defines),
|
||||||
compilerOptions => compilerOptions.Defines != null && compilerOptions.Defines.Any());
|
compilerOptions => compilerOptions.Defines != null && compilerOptions.Defines.Any());
|
||||||
|
|
||||||
private AddPropertyTransform<CommonCompilerOptions> NoWarnTransform => new AddPropertyTransform<CommonCompilerOptions>(
|
private AddPropertyTransform<CommonCompilerOptions> NoWarnTransform => new AddPropertyTransform<CommonCompilerOptions>(
|
||||||
"NoWarn",
|
"NoWarn",
|
||||||
compilerOptions => string.Join(";", compilerOptions.SuppressWarnings),
|
compilerOptions => "$(NoWarn);" + string.Join(";", compilerOptions.SuppressWarnings),
|
||||||
compilerOptions => compilerOptions.SuppressWarnings != null && compilerOptions.SuppressWarnings.Any());
|
compilerOptions => compilerOptions.SuppressWarnings != null && compilerOptions.SuppressWarnings.Any());
|
||||||
|
|
||||||
private AddPropertyTransform<CommonCompilerOptions> PreserveCompilationContextTransform =>
|
private AddPropertyTransform<CommonCompilerOptions> PreserveCompilationContextTransform =>
|
||||||
|
@ -129,11 +129,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
private Func<CommonCompilerOptions, string, IEnumerable<ProjectItemElement>> CopyToOutputFilesTransformExecute =>
|
private Func<CommonCompilerOptions, string, IEnumerable<ProjectItemElement>> CopyToOutputFilesTransformExecute =>
|
||||||
(compilerOptions, projectDirectory) =>
|
(compilerOptions, projectDirectory) =>
|
||||||
CopyToOutputFilesTransform.Transform(GetCopyToOutputIncludeContext(compilerOptions, projectDirectory));
|
CopyToOutputFilesTransform.Transform(GetCopyToOutputIncludeContext(compilerOptions, projectDirectory));
|
||||||
|
|
||||||
private readonly string _configuration;
|
|
||||||
private readonly NuGetFramework _framework;
|
|
||||||
private readonly ProjectPropertyGroupElement _configurationPropertyGroup;
|
private readonly ProjectPropertyGroupElement _configurationPropertyGroup;
|
||||||
private readonly ProjectItemGroupElement _configurationItemGroup;
|
private readonly ProjectItemGroupElement _configurationItemGroup;
|
||||||
|
private readonly CommonCompilerOptions _configurationBuildOptions;
|
||||||
|
|
||||||
private List<AddPropertyTransform<CommonCompilerOptions>> _propertyTransforms;
|
private List<AddPropertyTransform<CommonCompilerOptions>> _propertyTransforms;
|
||||||
private List<Func<CommonCompilerOptions, string, IEnumerable<ProjectItemElement>>> _includeContextTransformExecutes;
|
private List<Func<CommonCompilerOptions, string, IEnumerable<ProjectItemElement>>> _includeContextTransformExecutes;
|
||||||
|
@ -147,14 +146,12 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
}
|
}
|
||||||
|
|
||||||
public MigrateBuildOptionsRule(
|
public MigrateBuildOptionsRule(
|
||||||
string configuration,
|
CommonCompilerOptions configurationBuildOptions,
|
||||||
NuGetFramework framework,
|
|
||||||
ProjectPropertyGroupElement configurationPropertyGroup,
|
ProjectPropertyGroupElement configurationPropertyGroup,
|
||||||
ProjectItemGroupElement configurationItemGroup,
|
ProjectItemGroupElement configurationItemGroup,
|
||||||
ITransformApplicator transformApplicator = null)
|
ITransformApplicator transformApplicator = null)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configurationBuildOptions = configurationBuildOptions;
|
||||||
_framework = framework;
|
|
||||||
_configurationPropertyGroup = configurationPropertyGroup;
|
_configurationPropertyGroup = configurationPropertyGroup;
|
||||||
_configurationItemGroup = configurationItemGroup;
|
_configurationItemGroup = configurationItemGroup;
|
||||||
_transformApplicator = transformApplicator ?? new TransformApplicator();
|
_transformApplicator = transformApplicator ?? new TransformApplicator();
|
||||||
|
@ -201,13 +198,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
var propertyGroup = _configurationPropertyGroup ?? migrationRuleInputs.CommonPropertyGroup;
|
var propertyGroup = _configurationPropertyGroup ?? migrationRuleInputs.CommonPropertyGroup;
|
||||||
var itemGroup = _configurationItemGroup ?? migrationRuleInputs.CommonItemGroup;
|
var itemGroup = _configurationItemGroup ?? migrationRuleInputs.CommonItemGroup;
|
||||||
|
|
||||||
var compilerOptions = projectContext.ProjectFile.GetCompilerOptions(projectContext.TargetFramework, null);
|
var compilerOptions = projectContext.ProjectFile.GetCompilerOptions(null, null);
|
||||||
var configurationCompilerOptions =
|
|
||||||
projectContext.ProjectFile.GetCompilerOptions(_framework, _configuration);
|
|
||||||
|
|
||||||
// If we're in a configuration, we need to be careful not to overwrite values from BuildOptions
|
// If we're in a configuration, we need to be careful not to overwrite values from BuildOptions
|
||||||
// without a configuration
|
// without a configuration
|
||||||
if (_configuration == null)
|
if (_configurationBuildOptions == null)
|
||||||
{
|
{
|
||||||
CleanExistingProperties(csproj);
|
CleanExistingProperties(csproj);
|
||||||
|
|
||||||
|
@ -222,7 +217,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
{
|
{
|
||||||
PerformConfigurationPropertyAndItemMappings(
|
PerformConfigurationPropertyAndItemMappings(
|
||||||
compilerOptions,
|
compilerOptions,
|
||||||
configurationCompilerOptions,
|
_configurationBuildOptions,
|
||||||
propertyGroup,
|
propertyGroup,
|
||||||
itemGroup,
|
itemGroup,
|
||||||
_transformApplicator,
|
_transformApplicator,
|
||||||
|
@ -254,47 +249,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
var nonConfigurationOutput = includeContextTransformExecute(compilerOptions, projectDirectory);
|
var nonConfigurationOutput = includeContextTransformExecute(compilerOptions, projectDirectory);
|
||||||
var configurationOutput = includeContextTransformExecute(configurationCompilerOptions, projectDirectory).ToArray();
|
var configurationOutput = includeContextTransformExecute(configurationCompilerOptions, projectDirectory).ToArray();
|
||||||
|
|
||||||
if (configurationOutput != null && nonConfigurationOutput != null)
|
transformApplicator.Execute(configurationOutput, itemGroup, mergeExisting: true);
|
||||||
{
|
|
||||||
// TODO: HACK: this is leaky, see top comments, the throw at least covers the scenario
|
|
||||||
ThrowIfConfigurationHasAdditionalExcludes(configurationOutput, nonConfigurationOutput);
|
|
||||||
RemoveCommonIncludes(configurationOutput, nonConfigurationOutput);
|
|
||||||
configurationOutput = configurationOutput.Where(i => i != null && !string.IsNullOrEmpty(i.Include)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't merge with existing items when doing a configuration
|
|
||||||
transformApplicator.Execute(configurationOutput, itemGroup, mergeExisting: false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThrowIfConfigurationHasAdditionalExcludes(IEnumerable<ProjectItemElement> configurationOutput, IEnumerable<ProjectItemElement> nonConfigurationOutput)
|
|
||||||
{
|
|
||||||
foreach (var item1 in configurationOutput)
|
|
||||||
{
|
|
||||||
if (item1 == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item2Excludes = new HashSet<string>();
|
|
||||||
foreach (var item2 in nonConfigurationOutput)
|
|
||||||
{
|
|
||||||
if (item2 != null)
|
|
||||||
{
|
|
||||||
item2Excludes.UnionWith(item2.Excludes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var configurationHasAdditionalExclude =
|
|
||||||
item1.Excludes().Any(exclude => item2Excludes.All(item2Exclude => item2Exclude != exclude));
|
|
||||||
|
|
||||||
if (configurationHasAdditionalExclude)
|
|
||||||
{
|
|
||||||
MigrationTrace.Instance.WriteLine(item1.Exclude);
|
|
||||||
MigrationTrace.Instance.WriteLine(item2Excludes.ToString());
|
|
||||||
|
|
||||||
MigrationErrorCodes.MIGRATE20012("Unable to migrate projects with excluded files in configurations.")
|
|
||||||
.Throw();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Build.Construction;
|
using Microsoft.Build.Construction;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
{
|
{
|
||||||
|
@ -13,56 +14,75 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
{
|
{
|
||||||
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
|
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
|
||||||
{
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine($"Executing rule: {nameof(MigrateConfigurationsRule)}");
|
||||||
var projectContext = migrationRuleInputs.DefaultProjectContext;
|
var projectContext = migrationRuleInputs.DefaultProjectContext;
|
||||||
var configurations = projectContext.ProjectFile.GetConfigurations().ToList();
|
var configurations = projectContext.ProjectFile.GetConfigurations().ToList();
|
||||||
|
|
||||||
var frameworks = new List<NuGetFramework>();
|
var frameworks = new List<NuGetFramework>();
|
||||||
frameworks.Add(null);
|
|
||||||
frameworks.AddRange(projectContext.ProjectFile.GetTargetFrameworks().Select(t => t.FrameworkName));
|
frameworks.AddRange(projectContext.ProjectFile.GetTargetFrameworks().Select(t => t.FrameworkName));
|
||||||
|
|
||||||
if (!configurations.Any())
|
if (!configurations.Any() && !frameworks.Any())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frameworkConfigurationCombinations = frameworks.SelectMany(f => configurations, Tuple.Create);
|
foreach (var framework in frameworks)
|
||||||
|
|
||||||
foreach (var entry in frameworkConfigurationCombinations)
|
|
||||||
{
|
{
|
||||||
var framework = entry.Item1;
|
MigrateConfiguration(projectContext.ProjectFile, framework, migrationSettings, migrationRuleInputs);
|
||||||
var configuration = entry.Item2;
|
}
|
||||||
|
|
||||||
MigrateConfiguration(configuration, framework, migrationSettings, migrationRuleInputs);
|
foreach (var configuration in configurations)
|
||||||
|
{
|
||||||
|
MigrateConfiguration(projectContext.ProjectFile, configuration, migrationSettings, migrationRuleInputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MigrateConfiguration(
|
private void MigrateConfiguration(
|
||||||
|
Project project,
|
||||||
string configuration,
|
string configuration,
|
||||||
NuGetFramework framework,
|
|
||||||
MigrationSettings migrationSettings,
|
MigrationSettings migrationSettings,
|
||||||
MigrationRuleInputs migrationRuleInputs)
|
MigrationRuleInputs migrationRuleInputs)
|
||||||
|
{
|
||||||
|
var buildOptions = project.GetRawCompilerOptions(configuration);
|
||||||
|
var configurationCondition = $" '$(Configuration)' == '{configuration}' ";
|
||||||
|
|
||||||
|
MigrateConfiguration(buildOptions, configurationCondition, migrationSettings, migrationRuleInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateConfiguration(
|
||||||
|
Project project,
|
||||||
|
NuGetFramework framework,
|
||||||
|
MigrationSettings migrationSettings,
|
||||||
|
MigrationRuleInputs migrationRuleInputs)
|
||||||
|
{
|
||||||
|
var buildOptions = project.GetRawCompilerOptions(framework);
|
||||||
|
var configurationCondition = $" '$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)' == '{framework.DotNetFrameworkName}' ";
|
||||||
|
|
||||||
|
MigrateConfiguration(buildOptions, configurationCondition, migrationSettings, migrationRuleInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateConfiguration(
|
||||||
|
CommonCompilerOptions buildOptions,
|
||||||
|
string configurationCondition,
|
||||||
|
MigrationSettings migrationSettings,
|
||||||
|
MigrationRuleInputs migrationRuleInputs)
|
||||||
{
|
{
|
||||||
var csproj = migrationRuleInputs.OutputMSBuildProject;
|
var csproj = migrationRuleInputs.OutputMSBuildProject;
|
||||||
|
|
||||||
var propertyGroup = CreatePropertyGroupAtEndOfProject(csproj);
|
var propertyGroup = CreatePropertyGroupAtEndOfProject(csproj);
|
||||||
var itemGroup = CreateItemGroupAtEndOfProject(csproj);
|
var itemGroup = CreateItemGroupAtEndOfProject(csproj);
|
||||||
|
|
||||||
var configurationCondition = $" '$(Configuration)' == '{configuration}' ";
|
|
||||||
if (framework != null)
|
|
||||||
{
|
|
||||||
configurationCondition +=
|
|
||||||
$" and '$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)' == '{framework.DotNetFrameworkName}' ";
|
|
||||||
}
|
|
||||||
propertyGroup.Condition = configurationCondition;
|
propertyGroup.Condition = configurationCondition;
|
||||||
itemGroup.Condition = configurationCondition;
|
itemGroup.Condition = configurationCondition;
|
||||||
|
|
||||||
new MigrateBuildOptionsRule(configuration, framework, propertyGroup, itemGroup)
|
new MigrateBuildOptionsRule(buildOptions, propertyGroup, itemGroup)
|
||||||
.Apply(migrationSettings, migrationRuleInputs);
|
.Apply(migrationSettings, migrationRuleInputs);
|
||||||
|
|
||||||
propertyGroup.RemoveIfEmpty();
|
propertyGroup.RemoveIfEmpty();
|
||||||
itemGroup.RemoveIfEmpty();
|
itemGroup.RemoveIfEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ProjectPropertyGroupElement CreatePropertyGroupAtEndOfProject(ProjectRootElement csproj)
|
private ProjectPropertyGroupElement CreatePropertyGroupAtEndOfProject(ProjectRootElement csproj)
|
||||||
{
|
{
|
||||||
var propertyGroup = csproj.CreatePropertyGroupElement();
|
var propertyGroup = csproj.CreatePropertyGroupElement();
|
||||||
|
|
|
@ -7,19 +7,57 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.Build.Construction;
|
using Microsoft.Build.Construction;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
using Microsoft.DotNet.ProjectJsonMigration.Models;
|
using Microsoft.DotNet.ProjectJsonMigration.Models;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
{
|
{
|
||||||
public class IncludeContextTransform : ConditionalTransform<IncludeContext, IEnumerable<ProjectItemElement>>
|
public class IncludeContextTransform : ConditionalTransform<IncludeContext, IEnumerable<ProjectItemElement>>
|
||||||
{
|
{
|
||||||
// TODO: If a directory is specified in project.json does this need to be replaced with a glob in msbuild?
|
private Func<string, AddItemTransform<IncludeContext>> IncludeFilesExcludeFilesTransformGetter =>
|
||||||
// - Partially solved, what if the resolved glob is a directory?
|
(itemName) =>
|
||||||
// TODO: Support mappings
|
new AddItemTransform<IncludeContext>(
|
||||||
|
itemName,
|
||||||
|
includeContext => FormatGlobPatternsForMsbuild(includeContext.IncludeFiles, includeContext.SourceBasePath),
|
||||||
|
includeContext => FormatGlobPatternsForMsbuild(includeContext.ExcludeFiles, includeContext.SourceBasePath),
|
||||||
|
includeContext => includeContext != null && includeContext.IncludeFiles.Count > 0);
|
||||||
|
|
||||||
|
private Func<string, AddItemTransform<IncludeContext>> IncludeExcludeTransformGetter =>
|
||||||
|
(itemName) => new AddItemTransform<IncludeContext>(
|
||||||
|
itemName,
|
||||||
|
includeContext =>
|
||||||
|
{
|
||||||
|
var fullIncludeSet = includeContext.IncludePatterns.OrEmptyIfNull()
|
||||||
|
.Union(includeContext.BuiltInsInclude.OrEmptyIfNull());
|
||||||
|
|
||||||
|
return FormatGlobPatternsForMsbuild(fullIncludeSet, includeContext.SourceBasePath);
|
||||||
|
},
|
||||||
|
includeContext =>
|
||||||
|
{
|
||||||
|
var fullExcludeSet = includeContext.ExcludePatterns.OrEmptyIfNull()
|
||||||
|
.Union(includeContext.BuiltInsExclude.OrEmptyIfNull())
|
||||||
|
.Union(includeContext.ExcludeFiles.OrEmptyIfNull());
|
||||||
|
|
||||||
|
return FormatGlobPatternsForMsbuild(fullExcludeSet, includeContext.SourceBasePath);
|
||||||
|
},
|
||||||
|
includeContext =>
|
||||||
|
{
|
||||||
|
return includeContext != null &&
|
||||||
|
(
|
||||||
|
(includeContext.IncludePatterns != null && includeContext.IncludePatterns.Count > 0)
|
||||||
|
||
|
||||||
|
(includeContext.BuiltInsInclude != null && includeContext.BuiltInsInclude.Count > 0)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
private Func<string, string, AddItemTransform<IncludeContext>> MappingsIncludeFilesExcludeFilesTransformGetter =>
|
||||||
|
(itemName, targetPath) => AddMappingToTransform(IncludeFilesExcludeFilesTransformGetter(itemName), targetPath);
|
||||||
|
|
||||||
|
private Func<string, string, AddItemTransform<IncludeContext>> MappingsIncludeExcludeTransformGetter =>
|
||||||
|
(itemName, targetPath) => AddMappingToTransform(IncludeExcludeTransformGetter(itemName), targetPath);
|
||||||
|
|
||||||
private readonly string _itemName;
|
private readonly string _itemName;
|
||||||
private bool _transformMappings;
|
private bool _transformMappings;
|
||||||
private readonly List<ItemMetadataValue<IncludeContext>> _metadata = new List<ItemMetadataValue<IncludeContext>>();
|
private readonly List<ItemMetadataValue<IncludeContext>> _metadata = new List<ItemMetadataValue<IncludeContext>>();
|
||||||
private AddItemTransform<IncludeContext>[] _transformSet;
|
|
||||||
|
|
||||||
public IncludeContextTransform(
|
public IncludeContextTransform(
|
||||||
string itemName,
|
string itemName,
|
||||||
|
@ -42,55 +80,55 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateTransformSet()
|
private IEnumerable<Tuple<AddItemTransform<IncludeContext>, IncludeContext>> CreateTransformSet(IncludeContext source)
|
||||||
{
|
{
|
||||||
var includeFilesExcludeFilesTransformation = new AddItemTransform<IncludeContext>(
|
var transformSet = new List<Tuple<AddItemTransform<IncludeContext>, IncludeContext>>
|
||||||
_itemName,
|
|
||||||
includeContext => FormatPatterns(includeContext.IncludeFiles, includeContext.SourceBasePath),
|
|
||||||
includeContext => FormatPatterns(includeContext.ExcludeFiles, includeContext.SourceBasePath),
|
|
||||||
includeContext => includeContext != null && includeContext.IncludeFiles.Count > 0);
|
|
||||||
|
|
||||||
var includeExcludeTransformation = new AddItemTransform<IncludeContext>(
|
|
||||||
_itemName,
|
|
||||||
includeContext =>
|
|
||||||
{
|
|
||||||
var fullIncludeSet = includeContext.IncludePatterns.OrEmptyIfNull()
|
|
||||||
.Union(includeContext.BuiltInsInclude.OrEmptyIfNull());
|
|
||||||
|
|
||||||
return FormatPatterns(fullIncludeSet, includeContext.SourceBasePath);
|
|
||||||
},
|
|
||||||
includeContext =>
|
|
||||||
{
|
|
||||||
var fullExcludeSet = includeContext.ExcludePatterns.OrEmptyIfNull()
|
|
||||||
.Union(includeContext.BuiltInsExclude.OrEmptyIfNull())
|
|
||||||
.Union(includeContext.ExcludeFiles.OrEmptyIfNull());
|
|
||||||
|
|
||||||
return FormatPatterns(fullExcludeSet, includeContext.SourceBasePath);
|
|
||||||
},
|
|
||||||
includeContext =>
|
|
||||||
{
|
|
||||||
return includeContext != null &&
|
|
||||||
(
|
|
||||||
(includeContext.IncludePatterns != null && includeContext.IncludePatterns.Count > 0)
|
|
||||||
||
|
|
||||||
(includeContext.BuiltInsInclude != null && includeContext.BuiltInsInclude.Count > 0)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var metadata in _metadata)
|
|
||||||
{
|
{
|
||||||
includeFilesExcludeFilesTransformation.WithMetadata(metadata);
|
Tuple.Create(IncludeFilesExcludeFilesTransformGetter(_itemName), source),
|
||||||
includeExcludeTransformation.WithMetadata(metadata);
|
Tuple.Create(IncludeExcludeTransformGetter(_itemName), source)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
return transformSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mappings must be executed before the transform set to prevent a the
|
||||||
|
// non-mapped items that will merge with mapped items from being encompassed
|
||||||
|
foreach (var mappingEntry in source.Mappings.OrEmptyIfNull())
|
||||||
|
{
|
||||||
|
var targetPath = mappingEntry.Key;
|
||||||
|
var includeContext = mappingEntry.Value;
|
||||||
|
|
||||||
|
transformSet.Insert(0,
|
||||||
|
Tuple.Create(
|
||||||
|
MappingsIncludeExcludeTransformGetter(_itemName, targetPath),
|
||||||
|
includeContext));
|
||||||
|
|
||||||
|
transformSet.Insert(0,
|
||||||
|
Tuple.Create(
|
||||||
|
MappingsIncludeFilesExcludeFilesTransformGetter(_itemName, targetPath),
|
||||||
|
includeContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
_transformSet = new []
|
foreach (var metadataElement in _metadata)
|
||||||
{
|
{
|
||||||
includeFilesExcludeFilesTransformation,
|
foreach (var transform in transformSet)
|
||||||
includeExcludeTransformation
|
{
|
||||||
};
|
transform.Item1.WithMetadata(metadataElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FormatPatterns(IEnumerable<string> patterns, string projectDirectory)
|
public override IEnumerable<ProjectItemElement> ConditionallyTransform(IncludeContext source)
|
||||||
|
{
|
||||||
|
var transformSet = CreateTransformSet(source);
|
||||||
|
return transformSet.Select(t => t.Item1.Transform(t.Item2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatGlobPatternsForMsbuild(IEnumerable<string> patterns, string projectDirectory)
|
||||||
{
|
{
|
||||||
List<string> mutatedPatterns = new List<string>(patterns.Count());
|
List<string> mutatedPatterns = new List<string>(patterns.Count());
|
||||||
|
|
||||||
|
@ -121,6 +159,16 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AddItemTransform<IncludeContext> AddMappingToTransform(
|
||||||
|
AddItemTransform<IncludeContext> addItemTransform,
|
||||||
|
string targetPath)
|
||||||
|
{
|
||||||
|
var targetIsFile = MappingsTargetPathIsFile(targetPath);
|
||||||
|
var msbuildLinkMetadataValue = ConvertTargetPathToMsbuildMetadata(targetPath, targetIsFile);
|
||||||
|
|
||||||
|
return addItemTransform.WithMetadata("Link", msbuildLinkMetadataValue);
|
||||||
|
}
|
||||||
|
|
||||||
private bool PatternIsDirectory(string pattern, string projectDirectory)
|
private bool PatternIsDirectory(string pattern, string projectDirectory)
|
||||||
{
|
{
|
||||||
// TODO: what about /some/path/**/somedir?
|
// TODO: what about /some/path/**/somedir?
|
||||||
|
@ -135,11 +183,21 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
return Directory.Exists(path);
|
return Directory.Exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<ProjectItemElement> ConditionallyTransform(IncludeContext source)
|
private string ConvertTargetPathToMsbuildMetadata(string targetPath, bool targetIsFile)
|
||||||
{
|
{
|
||||||
CreateTransformSet();
|
if (targetIsFile)
|
||||||
|
{
|
||||||
|
return targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
return _transformSet.Select(t => t.Transform(source));
|
return $"{targetPath}%(FileName)%(Extension)";
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool MappingsTargetPathIsFile(string targetPath)
|
||||||
|
{
|
||||||
|
var normalizedTargetPath = PathUtility.GetPathWithDirectorySeparator(targetPath);
|
||||||
|
|
||||||
|
return normalizedTargetPath[normalizedTargetPath.Length - 1] != Path.DirectorySeparatorChar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,34 +66,109 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Item {{ ItemType: {item.ItemType}, Condition: {item.Condition}, Include: {item.Include}, Exclude: {item.Exclude} }}");
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: ItemGroup {{ Condition: {destinationItemGroup.Condition} }}");
|
||||||
|
|
||||||
if (mergeExisting)
|
if (mergeExisting)
|
||||||
{
|
{
|
||||||
var existingItems = FindExistingItems(item, destinationItemGroup.ContainingProject);
|
item = MergeWithExistingItemsWithSameCondition(item, destinationItemGroup);
|
||||||
|
|
||||||
foreach (var existingItem in existingItems)
|
// Item will be null when it's entire set of includes has been merged.
|
||||||
|
if (item == null)
|
||||||
{
|
{
|
||||||
var mergeResult = MergeItems(item, existingItem);
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Item completely merged");
|
||||||
item = mergeResult.InputItem;
|
return;
|
||||||
|
|
||||||
// Existing Item is null when it's entire set of includes has been merged with the MergeItem
|
|
||||||
if (mergeResult.ExistingItem == null)
|
|
||||||
{
|
|
||||||
existingItem.Parent.RemoveChild(existingItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
Execute(mergeResult.MergedItem, destinationItemGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item will be null only when it's entire set of includes is merged with existing items
|
item = MergeWithExistingItemsWithDifferentCondition(item, destinationItemGroup);
|
||||||
if (item != null)
|
|
||||||
|
// Item will be null when it is equivalent to a conditionless item
|
||||||
|
if (item == null)
|
||||||
{
|
{
|
||||||
Execute(item, destinationItemGroup);
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Item c");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Execute(item, destinationItemGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProjectItemElement MergeWithExistingItemsWithDifferentCondition(ProjectItemElement item, ProjectItemGroupElement destinationItemGroup)
|
||||||
|
{
|
||||||
|
var existingItemsWithDifferentCondition =
|
||||||
|
FindExistingItemsWithDifferentCondition(item, destinationItemGroup.ContainingProject, destinationItemGroup);
|
||||||
|
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Merging Item with {existingItemsWithDifferentCondition.Count()} existing items with a different condition chain.");
|
||||||
|
|
||||||
|
foreach (var existingItem in existingItemsWithDifferentCondition)
|
||||||
{
|
{
|
||||||
Execute(item, destinationItemGroup);
|
// When the existing item encompasses this item and it's condition is empty, ignore the current item
|
||||||
|
if (item.IsEquivalentTo(existingItem))
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: equivalent {existingItem.ConditionChain().Count()}");
|
||||||
|
|
||||||
|
if (existingItem.ConditionChain().Count() == 0)
|
||||||
|
{
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Ignoring Item {{ ItemType: {existingItem.ItemType}, Condition: {existingItem.Condition}, Include: {existingItem.Include}, Exclude: {existingItem.Exclude} }}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we haven't returned, and there are existing items with a separate condition, we need to
|
||||||
|
// overwrite with those items inside the destinationItemGroup by using a Remove
|
||||||
|
// Unless this is a conditionless item, in which case this the conditioned items should be doing the
|
||||||
|
// overwriting.
|
||||||
|
if (existingItemsWithDifferentCondition.Any() &&
|
||||||
|
(item.ConditionChain().Count() > 0 || destinationItemGroup.ConditionChain().Count() > 0))
|
||||||
|
{
|
||||||
|
// Merge with the first remove if possible
|
||||||
|
var existingRemoveItem = destinationItemGroup.Items
|
||||||
|
.Where(i =>
|
||||||
|
string.IsNullOrEmpty(i.Include)
|
||||||
|
&& string.IsNullOrEmpty(i.Exclude)
|
||||||
|
&& !string.IsNullOrEmpty(i.Remove))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (existingRemoveItem != null)
|
||||||
|
{
|
||||||
|
existingRemoveItem.Remove += ";" + item.Include;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var clearPreviousItem = _projectElementGenerator.CreateItemElement(item.ItemType);
|
||||||
|
clearPreviousItem.Remove = item.Include;
|
||||||
|
|
||||||
|
Execute(clearPreviousItem, destinationItemGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProjectItemElement MergeWithExistingItemsWithSameCondition(ProjectItemElement item, ProjectItemGroupElement destinationItemGroup)
|
||||||
|
{
|
||||||
|
var existingItemsWithSameCondition =
|
||||||
|
FindExistingItemsWithSameCondition(item, destinationItemGroup.ContainingProject, destinationItemGroup);
|
||||||
|
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Merging Item with {existingItemsWithSameCondition.Count()} existing items with the same condition chain.");
|
||||||
|
|
||||||
|
foreach (var existingItem in existingItemsWithSameCondition)
|
||||||
|
{
|
||||||
|
var mergeResult = MergeItems(item, existingItem);
|
||||||
|
item = mergeResult.InputItem;
|
||||||
|
|
||||||
|
// Existing Item is null when it's entire set of includes has been merged with the MergeItem
|
||||||
|
if (mergeResult.ExistingItem == null)
|
||||||
|
{
|
||||||
|
existingItem.Parent.RemoveChild(existingItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
MigrationTrace.Instance.WriteLine($"{nameof(TransformApplicator)}: Adding Merged Item {{ ItemType: {mergeResult.MergedItem.ItemType}, Condition: {mergeResult.MergedItem.Condition}, Include: {mergeResult.MergedItem.Include}, Exclude: {mergeResult.MergedItem.Exclude} }}");
|
||||||
|
Execute(mergeResult.MergedItem, destinationItemGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(
|
public void Execute(
|
||||||
|
@ -132,9 +207,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
}
|
}
|
||||||
|
|
||||||
var commonIncludes = item.IntersectIncludes(existingItem).ToList();
|
var commonIncludes = item.IntersectIncludes(existingItem).ToList();
|
||||||
item.RemoveIncludes(commonIncludes);
|
|
||||||
existingItem.RemoveIncludes(commonIncludes);
|
|
||||||
|
|
||||||
var mergedItem = _projectElementGenerator.AddItem(item.ItemType, string.Join(";", commonIncludes));
|
var mergedItem = _projectElementGenerator.AddItem(item.ItemType, string.Join(";", commonIncludes));
|
||||||
|
|
||||||
mergedItem.UnionExcludes(existingItem.Excludes());
|
mergedItem.UnionExcludes(existingItem.Excludes());
|
||||||
|
@ -143,6 +215,9 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
mergedItem.AddMetadata(existingItem.Metadata);
|
mergedItem.AddMetadata(existingItem.Metadata);
|
||||||
mergedItem.AddMetadata(item.Metadata);
|
mergedItem.AddMetadata(item.Metadata);
|
||||||
|
|
||||||
|
item.RemoveIncludes(commonIncludes);
|
||||||
|
existingItem.RemoveIncludes(commonIncludes);
|
||||||
|
|
||||||
var mergeResult = new MergeResult
|
var mergeResult = new MergeResult
|
||||||
{
|
{
|
||||||
InputItem = string.IsNullOrEmpty(item.Include) ? null : item,
|
InputItem = string.IsNullOrEmpty(item.Include) ? null : item,
|
||||||
|
@ -153,13 +228,29 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
|
||||||
return mergeResult;
|
return mergeResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ProjectItemElement> FindExistingItems(ProjectItemElement item, ProjectRootElement project)
|
private IEnumerable<ProjectItemElement> FindExistingItemsWithSameCondition(
|
||||||
|
ProjectItemElement item,
|
||||||
|
ProjectRootElement project,
|
||||||
|
ProjectElementContainer destinationContainer)
|
||||||
{
|
{
|
||||||
return project.ItemsWithoutConditions()
|
return project.Items
|
||||||
.Where(i => string.Equals(i.ItemType, item.ItemType, StringComparison.Ordinal))
|
.Where(i => i.Condition == item.Condition)
|
||||||
|
.Where(i => i.Parent.ConditionChainsAreEquivalent(destinationContainer))
|
||||||
|
.Where(i => i.ItemType == item.ItemType)
|
||||||
.Where(i => i.IntersectIncludes(item).Any());
|
.Where(i => i.IntersectIncludes(item).Any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<ProjectItemElement> FindExistingItemsWithDifferentCondition(
|
||||||
|
ProjectItemElement item,
|
||||||
|
ProjectRootElement project,
|
||||||
|
ProjectElementContainer destinationContainer)
|
||||||
|
{
|
||||||
|
return project.Items
|
||||||
|
.Where(i => !i.ConditionChainsAreEquivalent(item) || !i.Parent.ConditionChainsAreEquivalent(destinationContainer))
|
||||||
|
.Where(i => i.ItemType == item.ItemType)
|
||||||
|
.Where(i => i.IntersectIncludes(item).Any());
|
||||||
|
}
|
||||||
|
|
||||||
private class MergeResult
|
private class MergeResult
|
||||||
{
|
{
|
||||||
public ProjectItemElement InputItem { get; set; }
|
public ProjectItemElement InputItem { get; set; }
|
||||||
|
|
|
@ -98,8 +98,8 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
// Get all project options and combine them
|
// Get all project options and combine them
|
||||||
var rootOptions = GetCompilerOptions();
|
var rootOptions = GetCompilerOptions();
|
||||||
var configurationOptions = configurationName != null ? GetCompilerOptions(configurationName) : null;
|
var configurationOptions = configurationName != null ? GetRawCompilerOptions(configurationName) : null;
|
||||||
var targetFrameworkOptions = targetFramework != null ? GetCompilerOptions(targetFramework) : null;
|
var targetFrameworkOptions = targetFramework != null ? GetRawCompilerOptions(targetFramework) : null;
|
||||||
|
|
||||||
// Combine all of the options
|
// Combine all of the options
|
||||||
var compilerOptions = CommonCompilerOptions.Combine(rootOptions, configurationOptions, targetFrameworkOptions);
|
var compilerOptions = CommonCompilerOptions.Combine(rootOptions, configurationOptions, targetFrameworkOptions);
|
||||||
|
@ -136,7 +136,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
return _defaultCompilerOptions;
|
return _defaultCompilerOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommonCompilerOptions GetCompilerOptions(string configurationName)
|
internal CommonCompilerOptions GetRawCompilerOptions(string configurationName)
|
||||||
{
|
{
|
||||||
CommonCompilerOptions options;
|
CommonCompilerOptions options;
|
||||||
if (_compilerOptionsByConfiguration.TryGetValue(configurationName, out options))
|
if (_compilerOptionsByConfiguration.TryGetValue(configurationName, out options))
|
||||||
|
@ -147,7 +147,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommonCompilerOptions GetCompilerOptions(NuGetFramework frameworkName)
|
internal CommonCompilerOptions GetRawCompilerOptions(NuGetFramework frameworkName)
|
||||||
{
|
{
|
||||||
return GetTargetFramework(frameworkName)?.CompilerOptions;
|
return GetTargetFramework(frameworkName)?.CompilerOptions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: Guid("303677d5-7312-4c3f-baee-beb1a9bd9fe6")]
|
[assembly: Guid("303677d5-7312-4c3f-baee-beb1a9bd9fe6")]
|
||||||
|
|
||||||
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]
|
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]
|
||||||
|
[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]
|
[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]
|
||||||
[assembly:
|
[assembly:
|
||||||
InternalsVisibleTo(
|
InternalsVisibleTo(
|
||||||
|
|
|
@ -51,8 +51,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
|
|
||||||
migrateAction.ShouldThrow<Exception>().Where(
|
migrateAction.ShouldThrow<Exception>().Where(
|
||||||
e => e.Message.Contains("MIGRATE1011::Deprecated Project:")
|
e => e.Message.Contains("MIGRATE1011::Deprecated Project:")
|
||||||
&& e.Message.Contains("The 'packInclude' option is deprecated. Use 'files' in 'packOptions' instead.")
|
&& e.Message.Contains("The 'packInclude' option is deprecated. Use 'files' in 'packOptions' instead. (line: 6, file:")
|
||||||
&& e.Message.Contains("The 'compilationOptions' option is deprecated. Use 'buildOptions' instead."));
|
&& e.Message.Contains("The 'compilationOptions' option is deprecated. Use 'buildOptions' instead. (line: 3, file:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -7,6 +7,154 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
{
|
{
|
||||||
public class GivenMSBuildExtensions
|
public class GivenMSBuildExtensions
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChain_is_empty_when_element_and_parents_have_no_condition()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
|
||||||
|
item1.ConditionChain().Should().HaveCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChain_has_parent_conditions_when_element_is_empty()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
itemGroup.Condition = "condition";
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
|
||||||
|
item1.ConditionChain().Should().HaveCount(1);
|
||||||
|
item1.ConditionChain().First().Should().Be("condition");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChain_has_element_and_parent_conditions_when_they_exist()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
itemGroup.Condition = "itemGroup";
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
item1.Condition = "item";
|
||||||
|
|
||||||
|
item1.ConditionChain().Should().HaveCount(2);
|
||||||
|
item1.ConditionChain().Should().BeEquivalentTo("itemGroup", "item");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_true_when_neither_element_or_parents_have_conditions()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup.AddItem("test", "include2");
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_true_when_elements_have_the_same_condition()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup.AddItem("test", "include2");
|
||||||
|
item1.Condition = "item";
|
||||||
|
item2.Condition = "item";
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_true_when_element_condition_matches_condition_of_other_element_parent()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup1 = project.AddItemGroup();
|
||||||
|
var itemGroup2 = project.AddItemGroup();
|
||||||
|
itemGroup1.Condition = "item";
|
||||||
|
|
||||||
|
var item1 = itemGroup1.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup2.AddItem("test", "include2");
|
||||||
|
item2.Condition = "item";
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_false_when_elements_have_different_conditions()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup = project.AddItemGroup();
|
||||||
|
|
||||||
|
var item1 = itemGroup.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup.AddItem("test", "include2");
|
||||||
|
item1.Condition = "item";
|
||||||
|
item2.Condition = "item2";
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_false_when_other_element_parent_has_a_condition()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup1 = project.AddItemGroup();
|
||||||
|
var itemGroup2 = project.AddItemGroup();
|
||||||
|
itemGroup1.Condition = "item";
|
||||||
|
|
||||||
|
var item1 = itemGroup1.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup2.AddItem("test", "include2");
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConditionChainsAreEquivalent_is_false_when_both_element_parent_conditions_dont_match()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var itemGroup1 = project.AddItemGroup();
|
||||||
|
var itemGroup2 = project.AddItemGroup();
|
||||||
|
itemGroup1.Condition = "item";
|
||||||
|
itemGroup2.Condition = "item2";
|
||||||
|
|
||||||
|
var item1 = itemGroup1.AddItem("test", "include1");
|
||||||
|
var item2 = itemGroup2.AddItem("test", "include2");
|
||||||
|
|
||||||
|
item1.ConditionChainsAreEquivalent(item2).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasConflictingMetadata_returns_true_when_items_have_metadata_with_same_name_but_different_value()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var item1 = project.AddItem("test", "include1");
|
||||||
|
item1.AddMetadata("name", "value");
|
||||||
|
|
||||||
|
var item2 = project.AddItem("test1", "include1");
|
||||||
|
item2.AddMetadata("name", "value2");
|
||||||
|
|
||||||
|
item1.HasConflictingMetadata(item2).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasConflictingMetadata_returns_false_when_items_have_metadata_with_same_nameand_value()
|
||||||
|
{
|
||||||
|
var project = ProjectRootElement.Create();
|
||||||
|
var item1 = project.AddItem("test", "include1");
|
||||||
|
item1.AddMetadata("name", "value");
|
||||||
|
|
||||||
|
var item2 = project.AddItem("test1", "include1");
|
||||||
|
item2.AddMetadata("name", "value");
|
||||||
|
|
||||||
|
item1.HasConflictingMetadata(item2).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Includes_returns_include_value_split_by_semicolon()
|
public void Includes_returns_include_value_split_by_semicolon()
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>1F2EF070-AC5F-4078-AFB0-65745AC691B9</ProjectGuid>
|
<ProjectGuid>1F2EF070-AC5F-4078-AFB0-65745AC691B9</ProjectGuid>
|
||||||
<RootNamespace>Microsoft.DotNet.ProjectJsonMigration.Tests</RootNamespace>
|
<RootNamespace>Microsoft.DotNet.ProjectJsonMigration.Tests</RootNamespace>
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' “>..\artifact\obj\$(RootNamespace)</BaseIntermediateOutputPath>
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifact\obj\$(RootNamespace)</BaseIntermediateOutputPath>
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' “>..\artifacts\bin\</OutputPath>
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
|
|
@ -48,18 +48,15 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Migrating_empty_buildOptions_populates_only_AssemblyName_and_OutputType()
|
public void Migrating_empty_buildOptions_populates_only_AssemblyName_Compile_and_EmbeddedResource()
|
||||||
{
|
{
|
||||||
var mockProj = RunBuildOptionsRuleOnPj(@"
|
var mockProj = RunBuildOptionsRuleOnPj(@"
|
||||||
{
|
{
|
||||||
""buildOptions"": { }
|
""buildOptions"": { }
|
||||||
}");
|
}");
|
||||||
|
|
||||||
mockProj.Properties.Count().Should().Be(2);
|
mockProj.Properties.Count().Should().Be(1);
|
||||||
mockProj.Properties.Any(
|
mockProj.Properties.Any(p => !p.Name.Equals("AssemblyName", StringComparison.Ordinal)).Should().BeFalse();
|
||||||
p =>
|
|
||||||
!(p.Name.Equals("AssemblyName", StringComparison.Ordinal) ||
|
|
||||||
p.Name.Equals("OutputType", StringComparison.Ordinal))).Should().BeFalse();
|
|
||||||
|
|
||||||
mockProj.Items.Count().Should().Be(2);
|
mockProj.Items.Count().Should().Be(2);
|
||||||
mockProj.Items.First(i => i.ItemType == "Compile").Include.Should().Be(@"**\*.cs");
|
mockProj.Items.First(i => i.ItemType == "Compile").Include.Should().Be(@"**\*.cs");
|
||||||
|
@ -107,7 +104,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
}");
|
}");
|
||||||
|
|
||||||
mockProj.Properties.Count(p => p.Name == "DefineConstants").Should().Be(1);
|
mockProj.Properties.Count(p => p.Name == "DefineConstants").Should().Be(1);
|
||||||
mockProj.Properties.First(p => p.Name == "DefineConstants").Value.Should().Be("DEBUG;TRACE");
|
mockProj.Properties.First(p => p.Name == "DefineConstants")
|
||||||
|
.Value.Should().Be("$(DefineConstants);DEBUG;TRACE");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -121,7 +119,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
}");
|
}");
|
||||||
|
|
||||||
mockProj.Properties.Count(p => p.Name == "NoWarn").Should().Be(1);
|
mockProj.Properties.Count(p => p.Name == "NoWarn").Should().Be(1);
|
||||||
mockProj.Properties.First(p => p.Name == "NoWarn").Value.Should().Be("CS0168;CS0219");
|
mockProj.Properties.First(p => p.Name == "NoWarn").Value.Should().Be("$(NoWarn);CS0168;CS0219");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -39,6 +39,29 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
.Contain("'$(Configuration)' == 'testconfig'");
|
.Contain("'$(Configuration)' == 'testconfig'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Frameworks_buildOptions_produce_expected_properties_in_a_group_with_a_condition()
|
||||||
|
{
|
||||||
|
var mockProj = RunConfigurationsRuleOnPj(@"
|
||||||
|
{
|
||||||
|
""frameworks"": {
|
||||||
|
""netcoreapp1.0"": {
|
||||||
|
""buildOptions"": {
|
||||||
|
""emitEntryPoint"": ""true"",
|
||||||
|
""debugType"": ""full""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
|
||||||
|
mockProj.Properties.Count(
|
||||||
|
prop => prop.Name == "OutputType" || prop.Name == "DebugType").Should().Be(2);
|
||||||
|
|
||||||
|
mockProj.Properties.First(p => p.Name == "OutputType")
|
||||||
|
.Parent.Condition.Should()
|
||||||
|
.Contain("'$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)' == '.NETCoreApp,Version=v1.0'");
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Configuration_buildOptions_properties_are_not_written_when_they_overlap_with_buildOptions()
|
public void Configuration_buildOptions_properties_are_not_written_when_they_overlap_with_buildOptions()
|
||||||
{
|
{
|
||||||
|
@ -67,11 +90,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
{
|
{
|
||||||
property.Parent.Condition.Should().Be(string.Empty);
|
property.Parent.Condition.Should().Be(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Configuration_buildOptions_includes_are_not_written_when_they_overlap_with_buildOptions()
|
public void Configuration_buildOptions_includes_and_Remove_are_written_when_they_differ_from_base_buildOptions()
|
||||||
{
|
{
|
||||||
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
{
|
{
|
||||||
|
@ -97,25 +119,31 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
}
|
}
|
||||||
}");
|
}");
|
||||||
|
|
||||||
mockProj.Items.Count(item => item.ItemType == "Content").Should().Be(3);
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
|
|
||||||
mockProj.Items.Where(item => item.ItemType == "Content")
|
contentItems.Count().Should().Be(4);
|
||||||
.Count(item => !string.IsNullOrEmpty(item.Parent.Condition))
|
|
||||||
.Should()
|
|
||||||
.Be(1);
|
|
||||||
|
|
||||||
var configContent = mockProj.Items
|
// 2 for Base Build options
|
||||||
.Where(item => item.ItemType == "Content").First(item => !string.IsNullOrEmpty(item.Parent.Condition));
|
contentItems.Where(i => i.ConditionChain().Count() == 0).Should().HaveCount(2);
|
||||||
|
|
||||||
|
// 2 for Configuration BuildOptions (1 Remove, 1 Include)
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 1).Should().HaveCount(2);
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0 && !string.IsNullOrEmpty(item.Include));
|
||||||
|
var configRemoveContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0 && !string.IsNullOrEmpty(item.Remove));
|
||||||
|
|
||||||
// Directories are not converted to globs in the result because we did not write the directory
|
// Directories are not converted to globs in the result because we did not write the directory
|
||||||
configContent.Include.Should().Be(@"root;rootfile.cs");
|
configRemoveContentItem.Remove.Should().Be(@"root;src;rootfile.cs");
|
||||||
configContent.Exclude.Should().Be(@"src;rootfile.cs;src\file2.cs");
|
configIncludeContentItem.Include.Should().Be(@"root;src;rootfile.cs");
|
||||||
|
configIncludeContentItem.Exclude.Should().Be(@"src;rootfile.cs;src\file2.cs");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Configuration_buildOptions_includes_which_have_different_excludes_than_buildOptions_throws()
|
public void Configuration_buildOptions_which_have_different_excludes_than_buildOptions_overwrites()
|
||||||
{
|
{
|
||||||
Action action = () => RunConfigurationsRuleOnPj(@"
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
{
|
{
|
||||||
""buildOptions"": {
|
""buildOptions"": {
|
||||||
""copyToOutput"": {
|
""copyToOutput"": {
|
||||||
|
@ -130,7 +158,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
""buildOptions"": {
|
""buildOptions"": {
|
||||||
""copyToOutput"": {
|
""copyToOutput"": {
|
||||||
""include"": [""root"", ""src"", ""rootfile.cs""],
|
""include"": [""root"", ""src"", ""rootfile.cs""],
|
||||||
""exclude"": [""src"", ""rootfile.cs""],
|
""exclude"": [""rootfile.cs"", ""someotherfile.cs""],
|
||||||
""includeFiles"": [""src/file1.cs"", ""src/file2.cs""],
|
""includeFiles"": [""src/file1.cs"", ""src/file2.cs""],
|
||||||
""excludeFiles"": [""src/file2.cs""]
|
""excludeFiles"": [""src/file2.cs""]
|
||||||
}
|
}
|
||||||
|
@ -139,10 +167,307 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
}
|
}
|
||||||
}");
|
}");
|
||||||
|
|
||||||
action.ShouldThrow<Exception>()
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
.WithMessage(
|
|
||||||
"MIGRATE20012::Configuration Exclude: Unable to migrate projects with excluded files in configurations.");
|
contentItems.Count().Should().Be(5);
|
||||||
|
|
||||||
|
// 2 for Base Build options
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 0).Should().HaveCount(2);
|
||||||
|
|
||||||
|
// 3 for Configuration BuildOptions (1 Remove, 2 Include)
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 1).Should().HaveCount(3);
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains("root"));
|
||||||
|
|
||||||
|
var configIncludeContentItem2 = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains(@"src\file1.cs"));
|
||||||
|
|
||||||
|
var configRemoveContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0 && !string.IsNullOrEmpty(item.Remove));
|
||||||
|
|
||||||
|
// Directories are not converted to globs in the result because we did not write the directory
|
||||||
|
configRemoveContentItem.Removes()
|
||||||
|
.Should().BeEquivalentTo("root", "src", "rootfile.cs", @"src\file1.cs", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem.Includes().Should().BeEquivalentTo("root", "src", "rootfile.cs");
|
||||||
|
configIncludeContentItem.Excludes()
|
||||||
|
.Should().BeEquivalentTo("rootfile.cs", "someotherfile.cs", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem2.Includes().Should().BeEquivalentTo(@"src\file1.cs", @"src\file2.cs");
|
||||||
|
configIncludeContentItem2.Excludes().Should().BeEquivalentTo(@"src\file2.cs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Configuration_buildOptions_which_have_mappings_to_directory_add_link_metadata_with_item_metadata()
|
||||||
|
{
|
||||||
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
|
{
|
||||||
|
""configurations"": {
|
||||||
|
""testconfig"": {
|
||||||
|
""buildOptions"": {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""mappings"": {
|
||||||
|
""/some/dir/"" : {
|
||||||
|
""include"": [""src"", ""root""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""],
|
||||||
|
""includeFiles"": [""src/file1.cs"", ""src/file2.cs""],
|
||||||
|
""excludeFiles"": [""src/file2.cs""]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
|
||||||
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
|
|
||||||
|
contentItems.Count().Should().Be(2);
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 1).Should().HaveCount(2);
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains("root"));
|
||||||
|
|
||||||
|
var configIncludeContentItem2 = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains(@"src\file1.cs"));
|
||||||
|
|
||||||
|
configIncludeContentItem.Includes().Should().BeEquivalentTo("root", "src");
|
||||||
|
configIncludeContentItem.Excludes()
|
||||||
|
.Should().BeEquivalentTo("rootfile.cs", "src", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Value.Should().Be("/some/dir/%(FileName)%(Extension)");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configIncludeContentItem2.Includes().Should().BeEquivalentTo(@"src\file1.cs", @"src\file2.cs");
|
||||||
|
configIncludeContentItem2.Excludes().Should().BeEquivalentTo(@"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("Link").Should().NotBeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("Link").Value.Should().Be("/some/dir/%(FileName)%(Extension)");
|
||||||
|
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Configuration_buildOptions_which_have_mappings_overlapping_with_includes_in_same_configuration_merged_items_have_Link_metadata()
|
||||||
|
{
|
||||||
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
|
{
|
||||||
|
""configurations"": {
|
||||||
|
""testconfig"": {
|
||||||
|
""buildOptions"": {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""include"": [""src"", ""root""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""],
|
||||||
|
""includeFiles"": [""src/file1.cs""],
|
||||||
|
""excludeFiles"": [""src/file2.cs""],
|
||||||
|
""mappings"": {
|
||||||
|
""/some/dir/"" : {
|
||||||
|
""include"": [""src""],
|
||||||
|
""exclude"": [""src"", ""src/rootfile.cs""]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
|
||||||
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
|
|
||||||
|
contentItems.Count().Should().Be(3);
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 1).Should().HaveCount(3);
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include == "root");
|
||||||
|
|
||||||
|
var configIncludeContentItem2 = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include == "src");
|
||||||
|
|
||||||
|
var configIncludeContentItem3 = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains(@"src\file1.cs"));
|
||||||
|
|
||||||
|
// Directories are not converted to globs in the result because we did not write the directory
|
||||||
|
|
||||||
|
configIncludeContentItem.Includes().Should().BeEquivalentTo("root");
|
||||||
|
configIncludeContentItem.Excludes()
|
||||||
|
.Should().BeEquivalentTo("rootfile.cs", "src", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Should().BeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configIncludeContentItem2.Include.Should().Be("src");
|
||||||
|
configIncludeContentItem2.Excludes().Should().BeEquivalentTo("src", "rootfile.cs", @"src\rootfile.cs", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("Link").Should().NotBeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("Link").Value.Should().Be("/some/dir/%(FileName)%(Extension)");
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configIncludeContentItem3.Includes().Should().BeEquivalentTo(@"src\file1.cs");
|
||||||
|
configIncludeContentItem3.Exclude.Should().Be(@"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem3.GetMetadataWithName("Link").Should().BeNull();
|
||||||
|
configIncludeContentItem3.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem3.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Configuration_buildOptions_which_have_mappings_overlapping_with_includes_in_root_buildoptions_has_remove()
|
||||||
|
{
|
||||||
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
|
{
|
||||||
|
""buildOptions"" : {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""include"": [""src"", ""root""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""],
|
||||||
|
""includeFiles"": [""src/file1.cs"", ""src/file2.cs""],
|
||||||
|
""excludeFiles"": [""src/file2.cs""]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""configurations"": {
|
||||||
|
""testconfig"": {
|
||||||
|
""buildOptions"": {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""mappings"": {
|
||||||
|
""/some/dir/"" : {
|
||||||
|
""include"": [""src""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
|
||||||
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
|
|
||||||
|
contentItems.Count().Should().Be(4);
|
||||||
|
|
||||||
|
var rootBuildOptionsContentItems = contentItems.Where(i => i.ConditionChain().Count() == 0).ToList();
|
||||||
|
rootBuildOptionsContentItems.Count().Should().Be(2);
|
||||||
|
foreach (var buildOptionContentItem in rootBuildOptionsContentItems)
|
||||||
|
{
|
||||||
|
buildOptionContentItem.GetMetadataWithName("Link").Should().BeNull();
|
||||||
|
buildOptionContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
}
|
||||||
|
|
||||||
|
var configItems = contentItems.Where(i => i.ConditionChain().Count() == 1);
|
||||||
|
configItems.Should().HaveCount(2);
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains("src"));
|
||||||
|
|
||||||
|
var configRemoveContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& !string.IsNullOrEmpty(item.Remove));
|
||||||
|
|
||||||
|
configIncludeContentItem.Include.Should().Be("src");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Value.Should().Be("/some/dir/%(FileName)%(Extension)");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configRemoveContentItem.Remove.Should().Be("src");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Configuration_buildOptions_which_have_mappings_overlapping_with_includes_in_same_configuration_and_root_buildOptions_have_removes_and_Link_metadata_and_encompassed_items_are_merged()
|
||||||
|
{
|
||||||
|
var mockProj = RunConfigurationsAndBuildOptionsRuleOnPj(@"
|
||||||
|
{
|
||||||
|
""buildOptions"" : {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""include"": [""src"", ""root""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""],
|
||||||
|
""includeFiles"": [""src/file1.cs""],
|
||||||
|
""excludeFiles"": [""src/file2.cs""]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""configurations"": {
|
||||||
|
""testconfig"": {
|
||||||
|
""buildOptions"": {
|
||||||
|
""copyToOutput"": {
|
||||||
|
""include"": [""src"", ""root""],
|
||||||
|
""exclude"": [""src"", ""rootfile.cs""],
|
||||||
|
""includeFiles"": [""src/file3.cs""],
|
||||||
|
""excludeFiles"": [""src/file2.cs""],
|
||||||
|
""mappings"": {
|
||||||
|
""/some/dir/"" : {
|
||||||
|
""include"": [""src""],
|
||||||
|
""exclude"": [""src"", ""src/rootfile.cs""]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
|
||||||
|
var contentItems = mockProj.Items.Where(item => item.ItemType == "Content");
|
||||||
|
|
||||||
|
contentItems.Count().Should().Be(5);
|
||||||
|
contentItems.Where(i => i.ConditionChain().Count() == 1).Should().HaveCount(3);
|
||||||
|
|
||||||
|
var rootBuildOptionsContentItems = contentItems.Where(i => i.ConditionChain().Count() == 0).ToList();
|
||||||
|
rootBuildOptionsContentItems.Count().Should().Be(2);
|
||||||
|
foreach (var buildOptionContentItem in rootBuildOptionsContentItems)
|
||||||
|
{
|
||||||
|
buildOptionContentItem.GetMetadataWithName("Link").Should().BeNull();
|
||||||
|
buildOptionContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
}
|
||||||
|
|
||||||
|
var configIncludeEncompassedItem = contentItems.FirstOrDefault(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include == "root");
|
||||||
|
configIncludeEncompassedItem.Should().BeNull();
|
||||||
|
|
||||||
|
var configIncludeContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include == "src");
|
||||||
|
|
||||||
|
var configIncludeContentItem2 = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& item.Include.Contains(@"src\file3.cs"));
|
||||||
|
|
||||||
|
var configRemoveContentItem = contentItems.First(
|
||||||
|
item => item.ConditionChain().Count() > 0
|
||||||
|
&& !string.IsNullOrEmpty(item.Remove));
|
||||||
|
|
||||||
|
configIncludeContentItem.Include.Should().Be("src");
|
||||||
|
configIncludeContentItem.Excludes().Should().BeEquivalentTo("src", "rootfile.cs", @"src\rootfile.cs", @"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("Link").Value.Should().Be("/some/dir/%(FileName)%(Extension)");
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configIncludeContentItem2.Includes().Should().BeEquivalentTo(@"src\file3.cs");
|
||||||
|
configIncludeContentItem2.Exclude.Should().Be(@"src\file2.cs");
|
||||||
|
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("Link").Should().BeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Should().NotBeNull();
|
||||||
|
configIncludeContentItem2.GetMetadataWithName("CopyToOutputDirectory").Value.Should().Be("PreserveNewest");
|
||||||
|
|
||||||
|
configRemoveContentItem.Removes().Should().BeEquivalentTo("src");
|
||||||
|
}
|
||||||
|
|
||||||
private ProjectRootElement RunConfigurationsRuleOnPj(string s, string testDirectory = null)
|
private ProjectRootElement RunConfigurationsRuleOnPj(string s, string testDirectory = null)
|
||||||
{
|
{
|
||||||
testDirectory = testDirectory ?? Temp.CreateDirectory().Path;
|
testDirectory = testDirectory ?? Temp.CreateDirectory().Path;
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Microsoft.DotNet.Migration.Tests
|
||||||
// TODO: Standalone apps [InlineData("TestAppSimple", false)]
|
// TODO: Standalone apps [InlineData("TestAppSimple", false)]
|
||||||
// https://github.com/dotnet/sdk/issues/73 [InlineData("TestAppWithLibrary/TestApp", false)]
|
// https://github.com/dotnet/sdk/issues/73 [InlineData("TestAppWithLibrary/TestApp", false)]
|
||||||
[InlineData("TestAppWithRuntimeOptions")]
|
[InlineData("TestAppWithRuntimeOptions")]
|
||||||
|
[InlineData("TestAppWithContents")]
|
||||||
public void It_migrates_apps(string projectName)
|
public void It_migrates_apps(string projectName)
|
||||||
{
|
{
|
||||||
var projectDirectory = TestAssetsManager.CreateTestInstance(projectName, callingMethod: "i").WithLockFiles().Path;
|
var projectDirectory = TestAssetsManager.CreateTestInstance(projectName, callingMethod: "i").WithLockFiles().Path;
|
||||||
|
@ -204,6 +205,8 @@ namespace Microsoft.DotNet.Migration.Tests
|
||||||
|
|
||||||
private string BuildMSBuild(string projectDirectory, string configuration="Debug")
|
private string BuildMSBuild(string projectDirectory, string configuration="Debug")
|
||||||
{
|
{
|
||||||
|
DeleteXproj(projectDirectory);
|
||||||
|
|
||||||
var result = new Build3Command()
|
var result = new Build3Command()
|
||||||
.WithWorkingDirectory(projectDirectory)
|
.WithWorkingDirectory(projectDirectory)
|
||||||
.ExecuteWithCapturedOutput($"/p:Configuration={configuration}");
|
.ExecuteWithCapturedOutput($"/p:Configuration={configuration}");
|
||||||
|
@ -215,6 +218,15 @@ namespace Microsoft.DotNet.Migration.Tests
|
||||||
return result.StdOut;
|
return result.StdOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DeleteXproj(string projectDirectory)
|
||||||
|
{
|
||||||
|
var xprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj");
|
||||||
|
foreach (var xprojFile in xprojFiles)
|
||||||
|
{
|
||||||
|
File.Delete(xprojFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OutputDiagnostics(MigratedBuildComparisonData comparisonData)
|
private void OutputDiagnostics(MigratedBuildComparisonData comparisonData)
|
||||||
{
|
{
|
||||||
OutputDiagnostics(comparisonData.MSBuildBuildOutputs, comparisonData.ProjectJsonBuildOutputs);
|
OutputDiagnostics(comparisonData.MSBuildBuildOutputs, comparisonData.ProjectJsonBuildOutputs);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue