Beispiel #1
0
        public async Task <ITemplateCreationResult> InstantiateAsync(
            ITemplateInfo templateInfo,
            string?name,
            string?fallbackName,
            string?outputPath,
            IReadOnlyDictionary <string, string?> inputParameters,
            bool forceCreation  = false,
            string?baselineName = null,
            bool dryRun         = false,
            CancellationToken cancellationToken = default)
        {
            _ = templateInfo ?? throw new ArgumentNullException(nameof(templateInfo));
            inputParameters = inputParameters ?? new Dictionary <string, string?>();
            cancellationToken.ThrowIfCancellationRequested();

            ITemplate?template = LoadTemplate(templateInfo, baselineName);

            if (template == null)
            {
                return(new TemplateCreationResult(CreationResultStatus.NotFound, templateInfo.Name, LocalizableStrings.TemplateCreator_TemplateCreationResult_Error_CouldNotLoadTemplate));
            }

            string?realName = name ?? fallbackName ?? template.DefaultName;

            if (string.IsNullOrWhiteSpace(realName))
            {
                return(new TemplateCreationResult(CreationResultStatus.MissingMandatoryParam, template.Name, "--name"));
            }
            if (template.IsNameAgreementWithFolderPreferred && string.IsNullOrEmpty(outputPath))
            {
                outputPath = name;
            }
            string targetDir             = !string.IsNullOrWhiteSpace(outputPath) ? outputPath ! : _environmentSettings.Host.FileSystem.GetCurrentDirectory();
            Timing contentGeneratorBlock = Timing.Over(_logger, "Template content generation");

            try
            {
                ICreationResult?creationResult = null;
                if (!dryRun)
                {
                    _environmentSettings.Host.FileSystem.CreateDirectory(targetDir);
                }
                IComponentManager componentManager = _environmentSettings.Components;

                // setup separate sets of parameters to be used for GetCreationEffects() and by CreateAsync().
                if (!TryCreateParameterSet(template, realName !, inputParameters, out IParameterSet? effectParams, out TemplateCreationResult? resultIfParameterCreationFailed))
                {
                    //resultIfParameterCreationFailed is not null when TryCreateParameterSet is false
                    return(resultIfParameterCreationFailed !);
                }
                if (effectParams is null)
                {
                    throw new InvalidOperationException($"{nameof(effectParams)} cannot be null when {nameof(TryCreateParameterSet)} returns 'true'");
                }

                ICreationEffects creationEffects = await template.Generator.GetCreationEffectsAsync(
                    _environmentSettings,
                    template,
                    effectParams,
                    targetDir,
                    cancellationToken).ConfigureAwait(false);

                IReadOnlyList <IFileChange> changes            = creationEffects.FileChanges;
                IReadOnlyList <IFileChange> destructiveChanges = changes.Where(x => x.ChangeKind != ChangeKind.Create).ToList();

                if (!forceCreation && destructiveChanges.Count > 0)
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    if (!_environmentSettings.Host.OnPotentiallyDestructiveChangesDetected(changes, destructiveChanges))
#pragma warning restore CS0618 // Type or member is obsolete
                    {
                        return(new TemplateCreationResult(
                                   CreationResultStatus.DestructiveChangesDetected,
                                   template.Name,
                                   LocalizableStrings.TemplateCreator_TemplateCreationResult_Error_DestructiveChanges,
                                   null,
                                   null,
                                   creationEffects));
                    }
                }

                if (!TryCreateParameterSet(template, realName !, inputParameters, out IParameterSet? creationParams, out resultIfParameterCreationFailed))
                {
                    return(resultIfParameterCreationFailed !);
                }

                if (creationParams is null)
                {
                    throw new InvalidOperationException($"{nameof(creationParams)} cannot be null when {nameof(TryCreateParameterSet)} returns 'true'");
                }

                if (!dryRun)
                {
                    creationResult = await template.Generator.CreateAsync(
                        _environmentSettings,
                        template,
                        creationParams,
                        targetDir,
                        cancellationToken).ConfigureAwait(false);
                }
                return(new TemplateCreationResult(
                           status: CreationResultStatus.Success,
                           templateName: template.Name,
                           creationOutputs: creationResult,
                           outputBaseDir: targetDir,
                           creationEffects: creationEffects));
            }
            catch (Exception cx)
            {
                string message = string.Join(Environment.NewLine, ExceptionMessages(cx));
                return(new TemplateCreationResult(
                           status: cx is TemplateAuthoringException ? CreationResultStatus.TemplateIssueDetected : CreationResultStatus.CreateFailed,
                           templateName: template.Name,
                           localizedErrorMessage: string.Format(LocalizableStrings.TemplateCreator_TemplateCreationResult_Error_CreationFailed, message),
                           outputBaseDir: targetDir));
            }
            finally
            {
#pragma warning disable CS0618 // Type or member is obsolete - temporary until the method becomes internal.
                ReleaseMountPoints(template);
#pragma warning restore CS0618 // Type or member is obsolete
                contentGeneratorBlock.Dispose();
            }
        }