Skip to content

Commit

Permalink
transform app.config on build
Browse files Browse the repository at this point in the history
  • Loading branch information
dansiegel committed Mar 14, 2020
1 parent c3afc9d commit e836bd5
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 195 deletions.
8 changes: 8 additions & 0 deletions src/Mobile.BuildTools/Configuration/MetaData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Mobile.BuildTools.Configuration
{
internal static class MetaData
{
public const string Link = nameof(Link);
public const string SourceFile = nameof(SourceFile);
}
}
20 changes: 7 additions & 13 deletions src/Mobile.BuildTools/ConfigurationManager.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,13 @@
IntermediateOutputPath="$(IntermediateOutputPath)"
TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
InputConfigFiles="@(MobileBuildToolsConfig)">
<Output ItemName="GeneratedFile"
TaskParameter="CopiedConfigs"/>
<Output ItemName="FilesWrite"
TaskParameter="CopiedConfigs"/>
<Output ItemName="GeneratedAppConfig"
TaskParameter="OutputConfigs"/>
<Output ItemName="BuildToolsTempConfigs"
TaskParameter="CopiedConfigs" />
</AppConfigCopyTask>
</Target>

<Target Name="ConfigurationManagerTransformAndCopy"
AfterTargets="_CollectAppConfigs"
Inputs="@(MobileBuildToolsConfig)"
Outputs="@(GeneratedAppConfig)">
AfterTargets="_CollectAppConfigs">
<PropertyGroup>
<AppConfigEnvironment Condition=" $(AppConfigEnvironment) == '' ">$(Configuration)</AppConfigEnvironment>
</PropertyGroup>
Expand All @@ -43,12 +35,14 @@
IntermediateOutputPath="$(IntermediateOutputPath)"
TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
AppConfigEnvironment="$(AppConfigEnvironment)"
InputConfigFiles="@(BuildToolsTempConfigs)"
ExpectedAppConfig="@(GeneratedAppConfig)">
InputConfigFiles="@(MobileBuildToolsConfig)"
GeneratedAppConfig="@(GeneratedAppConfig)">
<Output ItemName="GeneratedFile"
TaskParameter="GeneratedAppConfig"/>
TaskParameter="OutputConfigs"/>
<Output ItemName="FilesWrite"
TaskParameter="GeneratedAppConfig"/>
TaskParameter="OutputConfigs"/>
<Output ItemName="PlatformAppConfig"
TaskParameter="OutputConfigs"/>
</ConfigurationManagerHandlerTask>
</Target>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Xsl;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mobile.BuildTools.Build;
using Mobile.BuildTools.Configuration;
using Mobile.BuildTools.Generators;
using Mobile.BuildTools.Logging;

using Mobile.BuildTools.Models.Configuration;

namespace Mobile.BuildTools.Tasks.Generators.AppConfig
{
internal class ConfigurationManagerTransformationGenerator : GeneratorBase<IEnumerable<ITaskItem>>
internal class ConfigurationManagerTransformationGenerator : GeneratorBase
{
public ConfigurationManagerTransformationGenerator(IBuildConfiguration buildConfiguration)
: base(buildConfiguration)
Expand All @@ -29,53 +22,32 @@ public ConfigurationManagerTransformationGenerator(IBuildConfiguration buildConf
// C:/repos/MyProject/MyProject.iOS/app.config
public string TransformFilePath { get; set; }

public IEnumerable<ExpectedAppConfig> ExpectedConfigs { get; set; }

protected override void ExecuteInternal()
{
var parentDirectory = Directory.GetParent(BaseConfigPath);
var configFileName = Path.GetFileNameWithoutExtension(BaseConfigPath);

// Copy all output files...
foreach (var config in ExpectedConfigs)
{
Log.LogMessage($"Copying '{config.SourceFile}' to '{config.OutputPath}'.");
File.Copy(config.SourceFile, config.OutputPath);
}

if (!string.IsNullOrEmpty(TransformFilePath) && File.Exists(TransformFilePath))
{
var updatedConfig = TransformationHelper.Transform(File.ReadAllText(BaseConfigPath),
File.ReadAllText(TransformFilePath));
File.ReadAllText(TransformFilePath));
if (updatedConfig is null) return;

updatedConfig.Save(BaseConfigPath);
var appConfig = ExpectedConfigs.First(x => Path.GetFileName(x.OutputPath) == "app.config");
updatedConfig.Save(appConfig.OutputPath);

if (Build.Configuration.Debug)
{
Log.LogMessage("*************** Transformed app.config ******************************");
Log.LogMessage(updatedConfig.ToString());
}
}

switch(Build.Configuration.AppConfig.Strategy)
{
case Models.AppConfigStrategy.BundleAll:
Outputs = parentDirectory.EnumerateFiles()
.Select(x => new TaskItem(x.FullName));
Log.LogMessage($"All app.config's will be bundled. {string.Join(", ", parentDirectory.EnumerateFiles().Select(x => x.Name))}");
break;
case Models.AppConfigStrategy.BundleNonStandard:
var standardConfigs = new[]
{
"app.debug.config",
"app.release.config",
"app.store.config",
"app.adhoc.config"
};
Outputs = parentDirectory.EnumerateFiles()
.Where(x => !standardConfigs.Any(s => s.Equals(x.Name, StringComparison.InvariantCultureIgnoreCase)))
.Select(x => new TaskItem(x.FullName));
if(Outputs.Count() > 1)
{
Log.LogMessage($"The app.config will be bundled with the following configurations. {string.Join(", ", Outputs.Select(x => Path.GetFileName(x.ItemSpec)))}");
}
break;
default:
Outputs = new[] { new TaskItem(BaseConfigPath) };
break;
}
}
}
}
}
17 changes: 17 additions & 0 deletions src/Mobile.BuildTools/Models/Configuration/ExpectedAppConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Mobile.BuildTools.Models.Configuration
{
internal class ExpectedAppConfig
{
public string OutputPath { get; set; }
public string SourceFile { get; set; }

#if !(SCHEMAGENERATOR || CLI_TOOL)
public static ExpectedAppConfig FromTaskItem(Microsoft.Build.Framework.ITaskItem item) =>
new ExpectedAppConfig
{
OutputPath = item.ItemSpec,
SourceFile = item.GetMetadata(BuildTools.Configuration.MetaData.SourceFile)
};
#endif
}
}
2 changes: 1 addition & 1 deletion src/Mobile.BuildTools/MonoAndroid.targets
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
AfterTargets="_CollectAppConfigs;ConfigurationManagerTransformAndCopy"
BeforeTargets="_CreateDex;Compile">
<ItemGroup>
<AndroidAsset Include="@(GeneratedAppConfig)"
<AndroidAsset Include="@(PlatformAppConfig)"
Link="Assets\%(Filename)%(Extension)"/>
</ItemGroup>
</Target>
Expand Down
76 changes: 28 additions & 48 deletions src/Mobile.BuildTools/Tasks/AppConfigCopyTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,24 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mobile.BuildTools.Build;
using Mobile.BuildTools.Configuration;

namespace Mobile.BuildTools.Tasks
{
public class AppConfigCopyTask : BuildToolsTaskBase
{
private const string EmptyAppConfig = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<configuration>
<appSettings>
</appSettings>
<connectionStrings>
</connectionStrings>
</configuration>";

public ITaskItem[] InputConfigFiles { get; set; }

private List<ITaskItem> _outputs = new List<ITaskItem>();
[Output]
public ITaskItem[] OutputConfigs => _outputs.ToArray();

private List<ITaskItem> _copiedConfigs = new List<ITaskItem>();
[Output]
public ITaskItem[] CopiedConfigs => _copiedConfigs.ToArray();

internal override void ExecuteInternal(IBuildConfiguration config)
{
// if (!System.Diagnostics.Debugger.IsAttached)
// System.Diagnostics.Debugger.Launch();

// Validate Inputs
if (!InputConfigFiles.Any())
{
Log.LogMessage("No input config files were found");
Expand All @@ -48,47 +34,41 @@ internal override void ExecuteInternal(IBuildConfiguration config)
return;
}

var files = InputConfigFiles.Select(x => x.ItemSpec);
var configsOutputDir = Path.Combine(IntermediateOutputPath, "configs");

if (!Directory.Exists(configsOutputDir))
// Ensure there is an app.config available
if (!InputConfigFiles.Any(x => FileNameEquals("app.config", x.ItemSpec) ||
(!string.IsNullOrEmpty(x.GetMetadata("Link")) && FileNameEquals("app.config", x.GetMetadata("Link")))))
{
Directory.CreateDirectory(configsOutputDir);
Log.LogError("You must have at least one file included with the build action MobileBuildToolsConfig with the file name app.config");
return;
}

foreach (var file in files)
{
CopyFile(configsOutputDir, file, config);
}
var configsOutputDir = Path.Combine(IntermediateOutputPath, "configs");

if(!_outputs.Any(x => Path.GetFileName(x.ItemSpec).Equals("app.config", StringComparison.InvariantCultureIgnoreCase)))
// Determine which files need outputs
//var files = InputConfigFiles.Select(x => x.ItemSpec);
foreach (var item in InputConfigFiles)
{
var projectFile = Path.Combine(config.ProjectDirectory, "app.config");
File.WriteAllText(projectFile, EmptyAppConfig);
CopyFile(configsOutputDir, projectFile, config);
CollectValidOutput(configsOutputDir, item, config);
}
}

private void CopyFile(string configsOutputDir, string file, IBuildConfiguration config)
{
var outputFilePath = Path.Combine(configsOutputDir, Path.GetFileName(file));
var lockFilePath = $"{outputFilePath}.lock";
var inputFileInfo = new FileInfo(file);
private static bool FileNameEquals(string expected, string actualPath) =>
Path.GetFileName(actualPath).Equals(expected, StringComparison.InvariantCultureIgnoreCase);

if (!File.Exists(outputFilePath) || !File.Exists(lockFilePath) ||
DateTime.Parse(File.ReadAllText(lockFilePath)) < inputFileInfo.LastWriteTimeUtc)
{
config.Logger.LogMessage($"Copying {file} to {outputFilePath}");
inputFileInfo.CopyTo(outputFilePath);
File.WriteAllText(lockFilePath, $"{inputFileInfo.LastWriteTimeUtc.ToString()}");
}

_copiedConfigs.Add(new TaskItem(outputFilePath));
private void CollectValidOutput(string configsOutputDir, ITaskItem item, IBuildConfiguration config)
{
var filePath = item.ItemSpec;
var link = item.GetMetadata(MetaData.Link);
var fileName = !string.IsNullOrEmpty(link) ? Path.GetFileName(link) : Path.GetFileName(filePath);
var outputFilePath = Path.Combine(configsOutputDir, fileName);
var outputItem = new TaskItem(outputFilePath);
outputItem.SetMetadata(MetaData.Link, link);
outputItem.SetMetadata(MetaData.SourceFile, filePath);

switch (config.Configuration.AppConfig.Strategy)
{
case Models.AppConfigStrategy.BundleAll:
_outputs.Add(new TaskItem(outputFilePath));
_outputs.Add(outputItem);
break;
case Models.AppConfigStrategy.BundleNonStandard:
var standardConfigs = new[]
Expand All @@ -98,15 +78,15 @@ private void CopyFile(string configsOutputDir, string file, IBuildConfiguration
"app.store.config",
"app.adhoc.config"
};
if(!standardConfigs.Any(x => x.Equals(Path.GetFileName(file), StringComparison.InvariantCultureIgnoreCase)))
if(!standardConfigs.Any(x => x.Equals(fileName, StringComparison.InvariantCultureIgnoreCase)))
{
_outputs.Add(new TaskItem(outputFilePath));
_outputs.Add(outputItem);
}
break;
default:
if (Path.GetFileName(file).Equals("app.config", StringComparison.InvariantCultureIgnoreCase))
if (fileName.Equals("app.config", StringComparison.InvariantCultureIgnoreCase))
{
_outputs.Add(new TaskItem(outputFilePath));
_outputs.Add(outputItem);
}
break;
}
Expand Down
Loading

0 comments on commit e836bd5

Please sign in to comment.