public async Task <string> GenerateProject(GeneratorModel model) { var randomString = Guid.NewGuid().ToString() + DateTime.Now.Millisecond; var outFolder = Path.Combine(_outPath, randomString, model.ProjectName); var iParams = new Dictionary <string, string> { { "Name", model.ProjectName } }; foreach (var p in model.GetTemplateParameters()) { if (p.Contains('=')) { var paramkvp = p.Split('='); if (paramkvp.Length == 2) { iParams.Add(paramkvp[0], paramkvp[1]); } } else { iParams.Add(p, "true"); } } if (!string.IsNullOrEmpty(model.TargetFrameworkVersion)) { iParams.Add("Framework", model.TargetFrameworkVersion); } var templateShortName = string.IsNullOrEmpty(model.TemplateShortName) ? DEFAULT_TEMPLATE : model.TemplateShortName; TemplateInfo templateInfo = FindTemplateByShortName(templateShortName, model.TemplateVersion, EnvSettings); if (templateInfo == null) { throw new Exception($"Could not find template with shortName: {templateShortName} "); } TemplateCreator creator = new TemplateCreator(EnvSettings); var creationResult = await creator.InstantiateAsync( templateInfo : templateInfo, name : model.ProjectName, fallbackName : "SteeltoeProject", outputPath : outFolder, inputParameters : iParams, skipUpdateCheck : true, forceCreation : false, baselineName : "baseLine"); if (creationResult.Status != CreationResultStatus.Success) { throw new InvalidDataException(creationResult.Message + ": " + creationResult.Status + " " + templateShortName); } return(outFolder); }
private async Task <CreationResultStatus> CreateTemplateAsync(ITemplateInfo template) { string fallbackName = new DirectoryInfo(OutputPath ?? Directory.GetCurrentDirectory()).Name; TemplateCreationResult instantiateResult; try { instantiateResult = await _templateCreator.InstantiateAsync(template, Name, fallbackName, OutputPath, _app.AllTemplateParams, SkipUpdateCheck, IsForceFlagSpecified).ConfigureAwait(false); } catch (ContentGenerationException cx) { Reporter.Error.WriteLine(cx.Message.Bold().Red()); if (cx.InnerException != null) { Reporter.Error.WriteLine(cx.InnerException.Message.Bold().Red()); } return(CreationResultStatus.CreateFailed); } catch (TemplateAuthoringException tae) { Reporter.Error.WriteLine(tae.Message.Bold().Red()); return(CreationResultStatus.CreateFailed); } string resultTemplateName = string.IsNullOrEmpty(instantiateResult.TemplateFullName) ? TemplateName : instantiateResult.TemplateFullName; switch (instantiateResult.Status) { case CreationResultStatus.Success: Reporter.Output.WriteLine(string.Format(LocalizableStrings.CreateSuccessful, resultTemplateName)); HandlePostActions(instantiateResult); break; case CreationResultStatus.CreateFailed: Reporter.Error.WriteLine(string.Format(LocalizableStrings.CreateFailed, resultTemplateName, instantiateResult.Message).Bold().Red()); break; case CreationResultStatus.MissingMandatoryParam: Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingRequiredParameter, instantiateResult.Message, resultTemplateName).Bold().Red()); break; case CreationResultStatus.OperationNotSpecified: break; case CreationResultStatus.InvalidParamValues: case CreationResultStatus.NotFound: ShowTemplateHelp(); break; default: break; } return(instantiateResult.Status); }
public Task <TemplateCreationResult> Create( CustomSolutionTemplate template, NewProjectConfiguration config, IReadOnlyDictionary <string, string> parameters) { return(templateCreator.InstantiateAsync( template.Info, config.ProjectName, config.GetValidProjectName(), config.ProjectLocation, parameters, true, false, null )); }
public async Task <CreationResult> CreateTemplate(ITemplate template, string path, string name = "") { if (template is DotNetTemplateAdaptor templateImpl) { if (string.IsNullOrEmpty(name)) { _commandInput.ResetArgs(templateImpl.DotnetTemplate.Info.ShortName, "--output", path); } else { _commandInput.ResetArgs(templateImpl.DotnetTemplate.Info.ShortName, "--output", path, "--name", name); } string fallbackName = new DirectoryInfo(_commandInput.OutputPath ?? Directory.GetCurrentDirectory()).Name; var result = await _templateCreator.InstantiateAsync(templateImpl.DotnetTemplate.Info, _commandInput.Name, fallbackName, _commandInput.OutputPath, templateImpl.DotnetTemplate.GetValidTemplateParameters(), _commandInput.SkipUpdateCheck, _commandInput.IsForceFlagSpecified, _commandInput.BaselineName).ConfigureAwait(false); return((CreationResult)result.Status); } return(CreationResult.NotFound); }
// Attempts to invoke the template. // Warning: The _commandInput cannot be assumed to be in a state that is parsed for the template being invoked. // So be sure to only get template-agnostic information from it. Anything specific to the template must be gotten from the ITemplateMatchInfo // Or do a reparse if necessary (currently occurs in one error case). private async Task <CreationResultStatus> CreateTemplateAsync(ITemplateMatchInfo templateMatchDetails) { ITemplateInfo template = templateMatchDetails.Info; char[] invalidChars = Path.GetInvalidFileNameChars(); if (_commandInput?.Name != null && _commandInput.Name.IndexOfAny(invalidChars) > -1) { string printableChars = string.Join(", ", invalidChars.Where(x => !char.IsControl(x)).Select(x => $"'{x}'")); string nonPrintableChars = string.Join(", ", invalidChars.Where(char.IsControl).Select(x => $"char({(int)x})")); Reporter.Error.WriteLine(string.Format(LocalizableStrings.InvalidNameParameter, printableChars, nonPrintableChars).Bold().Red()); return(CreationResultStatus.CreateFailed); } string fallbackName = new DirectoryInfo( !string.IsNullOrWhiteSpace(_commandInput.OutputPath) ? _commandInput.OutputPath : Directory.GetCurrentDirectory()) .Name; if (string.IsNullOrEmpty(fallbackName) || string.Equals(fallbackName, "/", StringComparison.Ordinal)) { // DirectoryInfo("/").Name on *nix returns "/", as opposed to null or "". fallbackName = null; } // Name returns <disk letter>:\ for root disk folder on Windows - replace invalid chars else if (fallbackName.IndexOfAny(invalidChars) > -1) { Regex pattern = new Regex($"[{Regex.Escape(new string(invalidChars))}]"); fallbackName = pattern.Replace(fallbackName, ""); if (string.IsNullOrWhiteSpace(fallbackName)) { fallbackName = null; } } TemplateCreationResult instantiateResult; try { instantiateResult = await _templateCreator.InstantiateAsync(template, _commandInput.Name, fallbackName, _commandInput.OutputPath, templateMatchDetails.GetValidTemplateParameters(), _commandInput.SkipUpdateCheck, _commandInput.IsForceFlagSpecified, _commandInput.BaselineName, _commandInput.IsDryRun) .ConfigureAwait(false); } catch (ContentGenerationException cx) { Reporter.Error.WriteLine(cx.Message.Bold().Red()); if (cx.InnerException != null) { Reporter.Error.WriteLine(cx.InnerException.Message.Bold().Red()); } return(CreationResultStatus.CreateFailed); } catch (TemplateAuthoringException tae) { Reporter.Error.WriteLine(tae.Message.Bold().Red()); return(CreationResultStatus.CreateFailed); } string resultTemplateName = string.IsNullOrEmpty(instantiateResult.TemplateFullName) ? _commandInput.TemplateName : instantiateResult.TemplateFullName; switch (instantiateResult.Status) { case CreationResultStatus.Success: if (!_commandInput.IsDryRun) { Reporter.Output.WriteLine(string.Format(LocalizableStrings.CreateSuccessful, resultTemplateName)); } else { Reporter.Output.WriteLine(LocalizableStrings.FileActionsWouldHaveBeenTaken); foreach (IFileChange change in instantiateResult.CreationEffects.FileChanges) { Reporter.Output.WriteLine($" {change.ChangeKind}: {change.TargetRelativePath}"); } } if (!string.IsNullOrEmpty(template.ThirdPartyNotices)) { Reporter.Output.WriteLine(string.Format(LocalizableStrings.ThirdPartyNotices, template.ThirdPartyNotices)); } HandlePostActions(instantiateResult); break; case CreationResultStatus.CreateFailed: Reporter.Error.WriteLine(string.Format(LocalizableStrings.CreateFailed, resultTemplateName, instantiateResult.Message).Bold().Red()); break; case CreationResultStatus.MissingMandatoryParam: if (string.Equals(instantiateResult.Message, "--name", StringComparison.Ordinal)) { Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingRequiredParameter, instantiateResult.Message, resultTemplateName).Bold().Red()); } else { // TODO: rework to avoid having to reparse. // The canonical info could be in the ITemplateMatchInfo, but currently isn't. TemplateResolver.ParseTemplateArgs(template, _hostDataLoader, _commandInput); IReadOnlyList <string> missingParamNamesCanonical = instantiateResult.Message.Split(new[] { ',' }) .Select(x => _commandInput.VariantsForCanonical(x.Trim()) .DefaultIfEmpty(x.Trim()).First()) .ToList(); string fixedMessage = string.Join(", ", missingParamNamesCanonical); Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingRequiredParameter, fixedMessage, resultTemplateName).Bold().Red()); } break; case CreationResultStatus.OperationNotSpecified: break; case CreationResultStatus.NotFound: Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingTemplateContentDetected, _commandName).Bold().Red()); break; case CreationResultStatus.InvalidParamValues: TemplateUsageInformation?usageInformation = TemplateUsageHelp.GetTemplateUsageInformation(template, _environment, _commandInput, _hostDataLoader, _templateCreator); if (usageInformation != null) { string invalidParamsError = InvalidParameterInfo.InvalidParameterListToString(usageInformation.Value.InvalidParameters); Reporter.Error.WriteLine(invalidParamsError.Bold().Red()); Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunHelpForInformationAboutAcceptedParameters, $"{_commandName} {_commandInput.TemplateName}").Bold().Red()); } else { Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingTemplateContentDetected, _commandName).Bold().Red()); return(CreationResultStatus.NotFound); } break; default: break; } return(instantiateResult.Status); }
public async Task <ICreationResult> CreateAsync(ITemplateInfo info, string name, string outputPath, IReadOnlyDictionary <string, string> parameters, bool skipUpdateCheck, string baselineName) { TemplateCreationResult instantiateResult = await _templateCreator.InstantiateAsync(info, name, name, outputPath, parameters, skipUpdateCheck, forceCreation : false, baselineName : baselineName).ConfigureAwait(false); return(instantiateResult.ResultInfo); }
private static int Main(string[] args) { string profileDir = GetHomeDirectory(); string hivePath = Path.Combine(profileDir, ".templateengine", HostName, HostVersion); ITemplateEngineHost host = CreateHost(HostName, HostVersion); EnvironmentSettings = new EngineEnvironmentSettings(host, x => new SettingsLoader(x), hivePath); EnvironmentSettings.SettingsLoader.Components.OfType <IIdentifiedComponent>().ToList(); _paths = new Paths(EnvironmentSettings); //NOTE: With the base directory virtualized, packages cannot be installed from NuGet, // only local packages and folders EnvironmentSettings.Host.VirtualizeDirectory(_paths.User.Content); EnvironmentSettings.Host.VirtualizeDirectory(_paths.User.Packages); _settingsLoader = (SettingsLoader)EnvironmentSettings.SettingsLoader; _hostDataLoader = new HostSpecificDataLoader(EnvironmentSettings.SettingsLoader); CommandLineParser parser = new CommandLineParser(args) .AddOptionWithConstrainedValue("--operation", new[] { "list", "create" }) .AddOptionWithValue("--require") .AddOptionWithValue("--source"); if (!parser.TryGetValues("--require", out IReadOnlyList <string> requireDirectives) || !parser.TryGetSingleValue("--operation", out string operation)) { Console.SetOut(Console.Error); Console.WriteLine("ERROR: Expected \"--require\" and/or \"--operation\" parameter."); return(-1); } IInstaller installer = new Installer(EnvironmentSettings); if (!parser.TryGetValues("--source", out IReadOnlyList <string> sources)) { sources = null; } installer.InstallPackages(requireDirectives, sources?.ToList()); //All required templates/components/lang packs have now been configured //Desired operation information starts at args[commandArgsStart] _templateCreator = new TemplateCreator(EnvironmentSettings); IReadOnlyList <TemplateInfo> rawTemplates = _settingsLoader.UserTemplateCache.TemplateInfo; var templates = new JArray(); foreach (var rawTemplate in rawTemplates) { var template = JObject.FromObject(rawTemplate); template.Add("Parameters", JArray.FromObject(rawTemplate.Parameters)); templates.Add(template); } if (string.Equals(operation, "list")) { Console.WriteLine(templates); return(0); } parser = parser.AddOptionWithValue("--identity"); if (!parser.TryGetSingleValue("--identity", out string identity)) { Console.SetOut(Console.Error); Console.WriteLine("ERROR: Expected \"--identity\" parameter."); return(-1); } TemplateInfo info = rawTemplates.FirstOrDefault(x => string.Equals(x.Identity, identity, StringComparison.Ordinal)); if (info == null) { Console.SetOut(Console.Error); Console.WriteLine("ERROR: Failed to find template with identity \"{0}\".", identity); return(-1); } if (string.Equals(operation, "create")) { Dictionary <string, string> templateArgs = new Dictionary <string, string>(StringComparer.Ordinal); foreach (ITemplateParameter x in info.Parameters) { if (x.DataType != null && x.DataType.StartsWith("bool", StringComparison.OrdinalIgnoreCase)) { parser = parser.AddOptionWithBooleanValue($"--arg:{x.Name}", string.IsNullOrEmpty(x.DefaultValue) || string.Equals(x.DefaultValue, "true")); } else if (x.DataType != null && x.DataType.Equals("choice", StringComparison.OrdinalIgnoreCase)) { parser = parser.AddOptionWithConstrainedValue($"--arg:{x.Name}", x.Choices.Keys.ToList()); } else { parser = parser.AddOptionWithValue($"--arg:{x.Name}"); } if (parser.TryGetSingleValue($"--arg:{x.Name}", out string val)) { templateArgs[x.Name] = val; } } TemplateCreationResult result = _templateCreator.InstantiateAsync(info, null, null, null, templateArgs, true, false, null).Result; if (result.Status == CreationResultStatus.Success) { PostActionDispatcher postActionDispatcher = new PostActionDispatcher(EnvironmentSettings, result, AllowPostActionsSetting.Yes, false); postActionDispatcher.Process(null); } Console.WriteLine(JObject.FromObject(result)); return((int)result.Status); } return(0); }
// Attempts to invoke the template. // Warning: The _commandInput cannot be assumed to be in a state that is parsed for the template being invoked. // So be sure to only get template-agnostic information from it. Anything specific to the template must be gotten from the ITemplateMatchInfo // Or do a reparse if necessary (currently occurs in one error case). private async Task <CreationResultStatus> CreateTemplateAsync(ITemplateMatchInfo templateMatchDetails) { ITemplateInfo template = templateMatchDetails.Info; string fallbackName = new DirectoryInfo(_commandInput.OutputPath ?? Directory.GetCurrentDirectory()).Name; if (string.IsNullOrEmpty(fallbackName) || string.Equals(fallbackName, "/", StringComparison.Ordinal)) { // DirectoryInfo("/").Name on *nix returns "/", as opposed to null or "". fallbackName = null; } TemplateCreationResult instantiateResult; try { instantiateResult = await _templateCreator.InstantiateAsync(template, _commandInput.Name, fallbackName, _commandInput.OutputPath, templateMatchDetails.GetValidTemplateParameters(), _commandInput.SkipUpdateCheck, _commandInput.IsForceFlagSpecified, _commandInput.BaselineName).ConfigureAwait(false); } catch (ContentGenerationException cx) { Reporter.Error.WriteLine(cx.Message.Bold().Red()); if (cx.InnerException != null) { Reporter.Error.WriteLine(cx.InnerException.Message.Bold().Red()); } return(CreationResultStatus.CreateFailed); } catch (TemplateAuthoringException tae) { Reporter.Error.WriteLine(tae.Message.Bold().Red()); return(CreationResultStatus.CreateFailed); } string resultTemplateName = string.IsNullOrEmpty(instantiateResult.TemplateFullName) ? TemplateName : instantiateResult.TemplateFullName; switch (instantiateResult.Status) { case CreationResultStatus.Success: Reporter.Output.WriteLine(string.Format(LocalizableStrings.CreateSuccessful, resultTemplateName)); if (!string.IsNullOrEmpty(template.ThirdPartyNotices)) { Reporter.Output.WriteLine(string.Format(LocalizableStrings.ThirdPartyNotices, template.ThirdPartyNotices)); } HandlePostActions(instantiateResult); break; case CreationResultStatus.CreateFailed: Reporter.Error.WriteLine(string.Format(LocalizableStrings.CreateFailed, resultTemplateName, instantiateResult.Message).Bold().Red()); break; case CreationResultStatus.MissingMandatoryParam: if (string.Equals(instantiateResult.Message, "--name", StringComparison.Ordinal)) { Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingRequiredParameter, instantiateResult.Message, resultTemplateName).Bold().Red()); } else { // TODO: rework to avoid having to reparse. // The canonical info could be in the ITemplateMatchInfo, but currently isn't. TemplateListResolver.ParseTemplateArgs(template, _hostDataLoader, _commandInput); IReadOnlyList <string> missingParamNamesCanonical = instantiateResult.Message.Split(new[] { ',' }) .Select(x => _commandInput.VariantsForCanonical(x.Trim()) .DefaultIfEmpty(x.Trim()).First()) .ToList(); string fixedMessage = string.Join(", ", missingParamNamesCanonical); Reporter.Error.WriteLine(string.Format(LocalizableStrings.MissingRequiredParameter, fixedMessage, resultTemplateName).Bold().Red()); } break; case CreationResultStatus.OperationNotSpecified: break; case CreationResultStatus.InvalidParamValues: TemplateUsageInformation usageInformation = TemplateUsageHelp.GetTemplateUsageInformation(template, EnvironmentSettings, _commandInput, _hostDataLoader, _templateCreator); string invalidParamsError = InvalidParameterInfo.InvalidParameterListToString(usageInformation.InvalidParameters); Reporter.Error.WriteLine(invalidParamsError.Bold().Red()); Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunHelpForInformationAboutAcceptedParameters, $"{CommandName} {TemplateName}").Bold().Red()); break; default: break; } return(instantiateResult.Status); }
public async void InstantiateAsync_ParamsProperlyHonored(string?parameterValue, string expectedOutput, bool instantiateShouldFail) { // // Template content preparation // string sourceSnippet = @" //#if( ChoiceParam == FirstChoice ) FIRST //#elseif (ChoiceParam == SecondChoice ) SECOND //#elseif (ChoiceParam == ThirdChoice ) THIRD //#else UNKNOWN //#endif "; IDictionary <string, string?> templateSourceFiles = new Dictionary <string, string?>(); // template.json templateSourceFiles.Add(TestFileSystemHelper.DefaultConfigRelativePath, TemplateConfigQuotelessLiteralsEnabled); //content templateSourceFiles.Add("sourceFile", sourceSnippet); // // Dependencies preparation and mounting // IEngineEnvironmentSettings environment = _engineEnvironmentSettings; string sourceBasePath = FileSystemHelpers.GetNewVirtualizedPath(environment); TestFileSystemHelper.WriteTemplateSource(environment, sourceBasePath, templateSourceFiles); IMountPoint?sourceMountPoint = TestFileSystemHelper.CreateMountPoint(environment, sourceBasePath); RunnableProjectGenerator rpg = new RunnableProjectGenerator(); // cannot use SimpleConfigModel dirrectly - due to missing easy way of creating ParameterSymbols SimpleConfigModel configModel = SimpleConfigModel.FromJObject(JObject.Parse(TemplateConfigQuotelessLiteralsEnabled)); var runnableConfig = new RunnableProjectConfig(environment, rpg, configModel, sourceMountPoint.FileInfo(TestFileSystemHelper.DefaultConfigRelativePath)); TemplateCreator creator = new TemplateCreator(_engineEnvironmentSettings); string targetDir = FileSystemHelpers.GetNewVirtualizedPath(_engineEnvironmentSettings); IReadOnlyDictionary <string, string?> parameters = new Dictionary <string, string?>() { { "ChoiceParam", parameterValue } }; var res = await creator.InstantiateAsync( templateInfo : runnableConfig, name : "tst", fallbackName : "tst2", inputParameters : parameters, outputPath : targetDir); if (instantiateShouldFail) { Assert.NotNull(res.ErrorMessage); Assert.Null(res.OutputBaseDirectory); } else { Assert.Null(res.ErrorMessage); Assert.NotNull(res.OutputBaseDirectory); string resultContent = _engineEnvironmentSettings.Host.FileSystem .ReadAllText(Path.Combine(res.OutputBaseDirectory !, "sourceFile")).Trim(); Assert.Equal(expectedOutput, resultContent); } }