-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAggregateConfig.cs
More file actions
161 lines (136 loc) · 6.28 KB
/
AggregateConfig.cs
File metadata and controls
161 lines (136 loc) · 6.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using AggregateConfigBuildTask.FileHandlers;
using Microsoft.Build.Framework;
using Task = Microsoft.Build.Utilities.Task;
[assembly: InternalsVisibleTo("AggregateConfig.Tests.UnitTests")]
namespace AggregateConfigBuildTask
{
/// <summary>
/// Represents a task that aggregates configuration files from a directory and outputs a merged file with optional modifications.
/// </summary>
public class AggregateConfig : Task
{
private readonly IFileSystem fileSystem;
private ITaskLogger logger;
/// <summary>
/// The directory path where input files are located. This property is required.
/// </summary>
[Required]
public string InputDirectory { get; set; }
/// <summary>
/// The type of input file type to be processed from <see cref="FileType"/>. If not specified, the default type <see cref="FileType.Yml"/> is used.
/// </summary>
public string InputType { get; set; }
/// <summary>
/// The output file path where the merged result will be saved. This property is required.
/// </summary>
[Required]
public string OutputFile { get; set; }
/// <summary>
/// The type of the output file type to be created from <see cref="FileType"/>. This property is required.
/// </summary>
[Required]
public string OutputType { get; set; }
/// <summary>
/// Specifies whether the source property (i.e., the file name) should be added to each merged object.
/// </summary>
public bool AddSourceProperty { get; set; }
/// <summary>
/// An array of additional properties that can be included in the output. These are user-specified key-value pairs.
/// </summary>
public ITaskItem[] AdditionalProperties { get; set; }
/// <summary>
/// Gets or sets whether quiet mode is enabled. When enabled, the logger will suppress non-critical messages.
/// </summary>
public bool IsQuietMode
{
get
{
return logger is QuietTaskLogger;
}
set
{
logger = value && !(logger is QuietTaskLogger) ? new QuietTaskLogger(Log) : logger;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="AggregateConfig"/> class with default file system and logger.
/// </summary>
public AggregateConfig()
{
this.fileSystem = new FileSystem();
this.logger = new TaskLogger(Log);
}
internal AggregateConfig(IFileSystem fileSystem, ITaskLogger logger)
{
this.fileSystem = fileSystem;
this.logger = logger;
}
/// <summary>
/// The entry point for the task.
/// </summary>
/// <returns>A boolean that is true if processing was successful.</returns>
public override bool Execute()
{
try
{
EmitHeader();
InputDirectory = Path.GetFullPath(InputDirectory);
OutputFile = Path.GetFullPath(OutputFile);
if (!Enum.TryParse(OutputType, true, out FileType outputType) ||
!Enum.IsDefined(typeof(FileType), outputType))
{
logger.LogError("Invalid FileType: {0}. Available options: {1}", OutputType, string.Join(", ", Enum.GetNames(typeof(FileType))));
return false;
}
FileType inputType = FileType.Yaml;
if (!string.IsNullOrEmpty(InputType) &&
(!Enum.TryParse(InputType, true, out inputType) || !Enum.IsDefined(typeof(FileType), inputType)))
{
logger.LogError("Invalid FileType: {0}. Available options: {1}", InputType, string.Join(", ", Enum.GetNames(typeof(FileType))));
return false;
}
return Process(inputType, outputType).GetAwaiter().GetResult();
}
catch (Exception ex)
{
logger.LogError("An unknown exception occurred: {0}", ex.Message);
logger.LogErrorFromException(ex, true, true, null);
return false;
}
}
private async Task<bool> Process(FileType inputType, FileType outputType)
{
logger.LogMessage(MessageImportance.High, "Aggregating {0} to {1} in folder {2}", inputType, outputType, InputDirectory);
string directoryPath = Path.GetDirectoryName(OutputFile);
if (!fileSystem.DirectoryExists(directoryPath))
{
fileSystem.CreateDirectory(directoryPath);
}
var finalResult = await ObjectManager.MergeFileObjects(InputDirectory, inputType, AddSourceProperty, fileSystem, logger).ConfigureAwait(false);
if (finalResult == null)
{
logger.LogError("No input was found! Check the input directory.");
return false;
}
var additionalPropertiesDictionary = JsonHelper.ParseAdditionalProperties(AdditionalProperties);
finalResult = await ObjectManager.InjectAdditionalProperties(finalResult, additionalPropertiesDictionary, logger).ConfigureAwait(false);
var writer = FileHandlerFactory.GetFileHandlerForType(fileSystem, outputType);
await writer.WriteOutput(finalResult, OutputFile).ConfigureAwait(false);
logger.LogMessage(MessageImportance.High, "Wrote aggregated configuration file to {0}", OutputFile);
return true;
}
private void EmitHeader()
{
var assembly = Assembly.GetExecutingAssembly();
var informationalVersion = assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion;
logger.LogMessage(MessageImportance.Normal, $"AggregateConfig Version: {informationalVersion}");
}
}
}