Skip to content

Commit 1f34adf

Browse files
authoredAug 13, 2022
Merge pull request chocolatey#2507 from TheCakeIsNaOH/template-params
(chocolatey#2500) List parameters in templates
2 parents 974a3bc + 565c083 commit 1f34adf

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed
 

‎src/chocolatey.tests/infrastructure.app/services/TemplateServiceSpecs.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace chocolatey.tests.infrastructure.app.services
2626
using chocolatey.infrastructure.app.services;
2727
using chocolatey.infrastructure.app.templates;
2828
using chocolatey.infrastructure.filesystem;
29+
using chocolatey.infrastructure.services;
2930
using Moq;
3031
using NUnit.Framework;
3132
using Should;
@@ -36,12 +37,14 @@ public abstract class TemplateServiceSpecsBase : TinySpec
3637
{
3738
protected TemplateService service;
3839
protected Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
40+
protected Mock<IXmlService> xmlService = new Mock<IXmlService>();
3941

4042
public override void Context()
4143
{
4244
fileSystem.ResetCalls();
45+
xmlService.ResetCalls();
4346

44-
service = new TemplateService(fileSystem.Object);
47+
service = new TemplateService(fileSystem.Object, xmlService.Object);
4548
}
4649
}
4750

‎src/chocolatey/infrastructure.app/services/TemplateService.cs

+61-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace chocolatey.infrastructure.app.services
2323
using System.Reflection;
2424
using System.Text;
2525
using configuration;
26+
using infrastructure.services;
2627
using logging;
2728
using templates;
2829
using tokens;
@@ -35,6 +36,7 @@ public class TemplateService : ITemplateService
3536
private readonly UTF8Encoding utf8WithoutBOM = new UTF8Encoding(false);
3637
private readonly IFileSystem _fileSystem;
3738
private readonly ILogger _nugetLogger;
39+
private readonly IXmlService _xmlService;
3840

3941
private readonly IList<string> _templateBinaryExtensions = new List<string> {
4042
".exe", ".msi", ".msu", ".msp", ".mst",
@@ -45,10 +47,12 @@ public class TemplateService : ITemplateService
4547

4648
private readonly string _builtInTemplateOverrideName = "default";
4749
private readonly string _builtInTemplateName = "built-in";
50+
private readonly string _templateParameterCacheFilename = ".parameters";
4851

49-
public TemplateService(IFileSystem fileSystem)
52+
public TemplateService(IFileSystem fileSystem, IXmlService xmlService)
5053
{
5154
_fileSystem = fileSystem;
55+
_xmlService = xmlService;
5256
}
5357

5458
public void generate_noop(ChocolateyConfiguration configuration)
@@ -148,6 +152,7 @@ public void generate(ChocolateyConfiguration configuration)
148152
configuration.NewCommand.TemplateName = string.IsNullOrWhiteSpace(configuration.NewCommand.TemplateName) ? "default" : configuration.NewCommand.TemplateName;
149153

150154
var templatePath = _fileSystem.combine_paths(ApplicationParameters.TemplatesLocation, configuration.NewCommand.TemplateName);
155+
var templateParameterCachePath = _fileSystem.combine_paths(templatePath, _templateParameterCacheFilename);
151156
if (!_fileSystem.directory_exists(templatePath)) throw new ApplicationException("Unable to find path to requested template '{0}'. Path should be '{1}'".format_with(configuration.NewCommand.TemplateName, templatePath));
152157

153158
this.Log().Info(configuration.QuietOutput ? logger : ChocolateyLoggers.Important, "Generating package from custom template at '{0}'.".format_with(templatePath));
@@ -174,6 +179,10 @@ public void generate(ChocolateyConfiguration configuration)
174179
this.Log().Debug(" Treating template file ('{0}') as binary instead of replacing templated values.".format_with(_fileSystem.get_file_name(file)));
175180
_fileSystem.copy_file(file, packageFileLocation, overwriteExisting:true);
176181
}
182+
else if (templateParameterCachePath.is_equal_to(file))
183+
{
184+
this.Log().Debug("{0} is the parameter cache file, ignoring".format_with(file));
185+
}
177186
else
178187
{
179188
generate_file_from_template(configuration, tokens, _fileSystem.read_file(file), packageFileLocation, Encoding.UTF8);
@@ -280,6 +289,7 @@ protected void list_custom_template_info(ChocolateyConfiguration configuration,
280289
.combine_paths(ApplicationParameters.TemplatesLocation, configuration.TemplateCommand.Name), "*", SearchOption.AllDirectories)));
281290
var isOverridingBuiltIn = configuration.TemplateCommand.Name == _builtInTemplateOverrideName;
282291
var isDefault = string.IsNullOrWhiteSpace(configuration.DefaultTemplateName) ? isOverridingBuiltIn : (configuration.DefaultTemplateName == configuration.TemplateCommand.Name);
292+
var templateParams = " {0}".format_with(string.Join("{0} ".format_with(Environment.NewLine), get_template_parameters(configuration, templateInstalledViaPackage)));
283293

284294
if (configuration.RegularOutput)
285295
{
@@ -292,14 +302,17 @@ protected void list_custom_template_info(ChocolateyConfiguration configuration,
292302
{5}{6}
293303
List of files:
294304
{7}
305+
List of Parameters:
306+
{8}
295307
".format_with(configuration.TemplateCommand.Name,
296308
pkgVersion,
297309
isDefault,
298310
isOverridingBuiltIn ? "This template is overriding the built in template{0}".format_with(Environment.NewLine) : string.Empty,
299311
pkgTitle,
300312
string.IsNullOrEmpty(pkgSummary) ? "Template not installed as a package" : "Summary: {0}".format_with(pkgSummary),
301313
string.IsNullOrEmpty(pkgDescription) ? string.Empty : "{0}Description:{0} {1}".format_with(Environment.NewLine, pkgDescription),
302-
pkgFiles));
314+
pkgFiles,
315+
templateParams));
303316
}
304317
else
305318
{
@@ -345,5 +358,51 @@ protected void list_built_in_template_info(ChocolateyConfiguration configuration
345358
}
346359
}
347360
}
361+
362+
protected IEnumerable<string> get_template_parameters(ChocolateyConfiguration configuration, bool templateInstalledViaPackage)
363+
{
364+
// If the template was installed via package, the cache file gets removed on upgrade, so the cache file would be up to date if it exists
365+
if (templateInstalledViaPackage)
366+
{
367+
var templateDirectory = _fileSystem.combine_paths(ApplicationParameters.TemplatesLocation, configuration.TemplateCommand.Name);
368+
var cacheFilePath = _fileSystem.combine_paths(templateDirectory, _templateParameterCacheFilename);
369+
370+
if (!_fileSystem.file_exists(cacheFilePath))
371+
{
372+
_xmlService.serialize(get_template_parameters_from_files(configuration).ToList(), cacheFilePath);
373+
}
374+
375+
return _xmlService.deserialize<List<string>>(cacheFilePath);
376+
}
377+
// If the template is not installed via a package, always read the parameters directly as the template may have been updated manually
378+
379+
return get_template_parameters_from_files(configuration).ToList();
380+
}
381+
382+
protected HashSet<string> get_template_parameters_from_files(ChocolateyConfiguration configuration)
383+
{
384+
var filesList = _fileSystem.get_files(_fileSystem.combine_paths(ApplicationParameters.TemplatesLocation, configuration.TemplateCommand.Name), "*", SearchOption.AllDirectories);
385+
var parametersList = new HashSet<string>();
386+
387+
foreach (var filePath in filesList)
388+
{
389+
if (_templateBinaryExtensions.Contains(_fileSystem.get_file_extension(filePath)))
390+
{
391+
this.Log().Debug("{0} is a binary file, not reading parameters".format_with(filePath));
392+
continue;
393+
}
394+
395+
if (_fileSystem.get_file_name(filePath) == _templateParameterCacheFilename)
396+
{
397+
this.Log().Debug("{0} is the parameter cache file, not reading parameters".format_with(filePath));
398+
continue;
399+
}
400+
401+
var fileContents = _fileSystem.read_file(filePath);
402+
parametersList.UnionWith(TokenReplacer.get_tokens(fileContents, "[[", "]]"));
403+
}
404+
405+
return parametersList;
406+
}
348407
}
349408
}

‎src/chocolatey/infrastructure/tokens/TokenReplacer.cs

+11
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,16 @@ private static IDictionary<string, string> create_dictionary_from_configuration<
6161

6262
return propertyDictionary;
6363
}
64+
65+
public static IEnumerable<string> get_tokens(string textWithTokens, string tokenPrefix = "[[", string tokenSuffix = "]]")
66+
{
67+
var regexMatches = Regex.Matches(textWithTokens, "{0}(?<key>\\w+){1}"
68+
.format_with(Regex.Escape(tokenPrefix), Regex.Escape(tokenSuffix))
69+
);
70+
foreach (Match regexMatch in regexMatches)
71+
{
72+
yield return regexMatch.Groups["key"].to_string();
73+
}
74+
}
6475
}
6576
}

0 commit comments

Comments
 (0)
Please sign in to comment.