diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs b/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs
index aaaa927343de..96ebca073460 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs
@@ -1394,6 +1394,15 @@ internal static string PossibleValuesHeader {
}
}
+ ///
+ /// Looks up a localized string similar to Post action argument '{0}' is not a valid boolean value..
+ ///
+ internal static string PostAction_ModifyJson_Error_ArgumentNotBoolean {
+ get {
+ return ResourceManager.GetString("PostAction_ModifyJson_Error_ArgumentNotBoolean", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Post action argument '{0}' is mandatory, but not configured..
///
@@ -1439,6 +1448,15 @@ internal static string PostAction_ModifyJson_Succeeded {
}
}
+ ///
+ /// Looks up a localized string similar to Attempting to find json file '{0}' in '{1}'.
+ ///
+ internal static string PostAction_ModifyJson_Verbose_AttemptingToFindJsonFile {
+ get {
+ return ResourceManager.GetString("PostAction_ModifyJson_Verbose_AttemptingToFindJsonFile", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Failed to run the command: argument 'executable' is missing in post action configuration..
///
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx b/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx
index dd607ed27b6c..05bab0edbd86 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx
@@ -307,7 +307,7 @@
Moderate
- represents nuget api severity of level 1.
+ represents nuget api severity of level 1.High
@@ -859,67 +859,64 @@ The header is followed by the list of parameters and their errors (might be seve
To list installed templates, run:
-
+
Package identifier
-
+
Specifies a concrete version for displaying details. If not specified the last is taken.
-
+
Authors
-
+
Details
-
+
Source Feed
-
+
Package version
-
+
Reserved
-
+
Languages
-
-
+
License Metadata
-
+
License Expression
-
+
License
-
+
License Url
-
+
Owners
-
+
Repository Url
-
+
Short Names
-
-
+
Tags
-
-
+
Templates
-
+
No NuGet sources are defined or enabled
-
+
Failed to load NuGet sources configured for the folder {0}
-
+
Could not parse NuGet source '{0}', so it was discarded
@@ -947,4 +944,10 @@ The header is followed by the list of parameters and their errors (might be seve
Trustedinformation about NuGet package origin; if a package has PrefixReserved indicator
-
+
+ Post action argument '{0}' is not a valid boolean value.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+
\ No newline at end of file
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/PostActionProcessors/AddJsonPropertyPostActionProcessor.cs b/src/Cli/Microsoft.TemplateEngine.Cli/PostActionProcessors/AddJsonPropertyPostActionProcessor.cs
index 619f062b6a53..68a0855d97ef 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/PostActionProcessors/AddJsonPropertyPostActionProcessor.cs
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/PostActionProcessors/AddJsonPropertyPostActionProcessor.cs
@@ -4,6 +4,7 @@
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
+
using Microsoft.DotNet.Cli.Utils;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.PhysicalFileSystem;
@@ -12,6 +13,8 @@ namespace Microsoft.TemplateEngine.Cli.PostActionProcessors
{
internal class AddJsonPropertyPostActionProcessor : PostActionProcessorBase
{
+ private const string AllowFileCreationArgument = "allowFileCreation";
+ private const string AllowPathCreationArgument = "allowPathCreation";
private const string JsonFileNameArgument = "jsonFileName";
private const string ParentPropertyPathArgument = "parentPropertyPath";
private const string NewJsonPropertyNameArgument = "newJsonPropertyName";
@@ -46,12 +49,25 @@ protected override bool ProcessInternal(
return false;
}
- IReadOnlyList jsonFiles = FindFilesInCurrentProjectOrSolutionFolder(environment.Host.FileSystem, outputBasePath, matchPattern: jsonFileName, maxAllowedAboveDirectories: 1);
+ IReadOnlyList jsonFiles = FindFilesInCurrentFolderOrParentFolder(environment.Host.FileSystem, outputBasePath, jsonFileName);
if (jsonFiles.Count == 0)
{
- Reporter.Error.WriteLine(LocalizableStrings.PostAction_ModifyJson_Error_NoJsonFile);
- return false;
+ if (!bool.TryParse(action.Args.GetValueOrDefault(AllowFileCreationArgument, "false"), out bool createFile))
+ {
+ Reporter.Error.WriteLine(string.Format(LocalizableStrings.PostAction_ModifyJson_Error_ArgumentNotBoolean, AllowFileCreationArgument));
+ return false;
+ }
+
+ if (!createFile)
+ {
+ Reporter.Error.WriteLine(LocalizableStrings.PostAction_ModifyJson_Error_NoJsonFile);
+ return false;
+ }
+
+ string newJsonFilePath = Path.Combine(outputBasePath, jsonFileName);
+ environment.Host.FileSystem.WriteAllText(newJsonFilePath, "{}");
+ jsonFiles = new List { newJsonFilePath };
}
if (jsonFiles.Count > 1)
@@ -73,7 +89,8 @@ protected override bool ProcessInternal(
newJsonElementProperties!.ParentProperty,
":",
newJsonElementProperties.NewJsonPropertyName,
- newJsonElementProperties.NewJsonPropertyValue);
+ newJsonElementProperties.NewJsonPropertyValue,
+ action);
if (newJsonContent == null)
{
@@ -87,7 +104,7 @@ protected override bool ProcessInternal(
return true;
}
- private static JsonNode? AddElementToJson(IPhysicalFileSystem fileSystem, string targetJsonFile, string? propertyPath, string propertyPathSeparator, string newJsonPropertyName, string newJsonPropertyValue)
+ private static JsonNode? AddElementToJson(IPhysicalFileSystem fileSystem, string targetJsonFile, string? propertyPath, string propertyPathSeparator, string newJsonPropertyName, string newJsonPropertyValue, IPostAction action)
{
JsonNode? jsonContent = JsonNode.Parse(fileSystem.ReadAllText(targetJsonFile), nodeOptions: null, documentOptions: DeserializerOptions);
@@ -96,7 +113,13 @@ protected override bool ProcessInternal(
return null;
}
- JsonNode? parentProperty = FindJsonNode(jsonContent, propertyPath, propertyPathSeparator);
+ if (!bool.TryParse(action.Args.GetValueOrDefault(AllowPathCreationArgument, "false"), out bool createPath))
+ {
+ Reporter.Error.WriteLine(string.Format(LocalizableStrings.PostAction_ModifyJson_Error_ArgumentNotBoolean, AllowPathCreationArgument));
+ return false;
+ }
+
+ JsonNode? parentProperty = FindJsonNode(jsonContent, propertyPath, propertyPathSeparator, createPath);
if (parentProperty == null)
{
@@ -116,7 +139,7 @@ protected override bool ProcessInternal(
return jsonContent;
}
- private static JsonNode? FindJsonNode(JsonNode content, string? nodePath, string pathSeparator)
+ private static JsonNode? FindJsonNode(JsonNode content, string? nodePath, string pathSeparator, bool createPath)
{
if (nodePath == null)
{
@@ -134,18 +157,22 @@ protected override bool ProcessInternal(
return null;
}
- node = node[property];
+ JsonNode? childNode = node[property];
+ if (childNode is null && createPath)
+ {
+ node[property] = childNode = new JsonObject();
+ }
+
+ node = childNode;
}
return node;
}
- private static IReadOnlyList FindFilesInCurrentProjectOrSolutionFolder(
+ private static string[] FindFilesInCurrentFolderOrParentFolder(
IPhysicalFileSystem fileSystem,
string startPath,
- string matchPattern,
- Func? secondaryFilter = null,
- int maxAllowedAboveDirectories = 250)
+ string matchPattern)
{
string? directory = fileSystem.DirectoryExists(startPath) ? startPath : Path.GetDirectoryName(startPath);
@@ -158,22 +185,20 @@ private static IReadOnlyList FindFilesInCurrentProjectOrSolutionFolder(
do
{
- List filesInDir = fileSystem.EnumerateFileSystemEntries(directory, matchPattern, SearchOption.AllDirectories).ToList();
- List matches = new();
-
- matches = secondaryFilter == null ? filesInDir : filesInDir.Where(x => secondaryFilter(x)).ToList();
+ Reporter.Verbose.WriteLine(string.Format(LocalizableStrings.PostAction_ModifyJson_Verbose_AttemptingToFindJsonFile, matchPattern, directory));
+ string[] filesInDir = fileSystem.EnumerateFileSystemEntries(directory, matchPattern, SearchOption.AllDirectories).ToArray();
- if (matches.Count > 0)
+ if (filesInDir.Length > 0)
{
- return matches;
+ return filesInDir;
}
directory = Path.GetPathRoot(directory) != directory ? Directory.GetParent(directory)?.FullName : null;
numberOfUpLevels++;
}
- while (directory != null && numberOfUpLevels <= maxAllowedAboveDirectories);
+ while (directory != null && numberOfUpLevels <= 1);
- return new List();
+ return Array.Empty();
}
private class JsonContentParameters
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf
index aeaadf8612f4..832d3c3d0367 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Chcete tuto akci spustit? [{0}(ano)|{1}(ne)]
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ Argument „{0}“ po akci je povinný, ale není nakonfigurovaný.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0} byl úspěšně změněn.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Příkaz se nepodařilo spustit. V konfiguraci akce publikování chybí argument executable.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
index dc1bb13aef69..9d09cc5425b2 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Möchten Sie diese Aktion ausführen [{0} (ja) |{1} (nein)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ Das Postaktionsargument "{0}" ist obligatorisch, aber nicht konfiguriert.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0} erfolgreich geändert.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Fehler beim Ausführen des Befehls: das Argument "Ausführbare Datei" fehlt in der Konfiguration der nachfolgenden Aktion.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
index d4b4b1f37611..dfceed7d9791 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
¿Quiere ejecutar esta acción [{0}(yes)|{1}(no)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ El argumento de acción posterior '{0}' es obligatorio, pero no está configurado.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0} modificado correctamente.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ No se pudo ejecutar el comando: falta el argumento "executable" en la configuración de la acción posterior.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
index b06daec2e1a0..dc4a7e3ecfc7 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Voulez-vous exécuter cette action [{0} (yes) |{1} (no)] ?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ L'argument de publication de l'action '{0}' est obligatoire, mais n'est pas configuré.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
Modifié avec succès {0}.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Échec de l’exécution de la commande : l’argument « Exécutable » est manquant dans la configuration de l’action de publication.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
index 4d17a1c6f8ec..c72a0079c4f2 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Eseguire questa azione [{0} (sì) |{1} (no)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ L'argomento post-azione '{0}' è obbligatorio, ma non configurato.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
Modifica di {0} completata.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Non è stato possibile eseguire il comando: argomento "eseguibile" mancante nella configurazione dell'azione post.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
index d0b01c5aa96f..e5d354ce85df 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
このアクションを実行しますか[{0} (はい) |{1} (いいえ)] ですか?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ 事後アクション引数 '{0}' は必須ですが、構成されていません。
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0} が正常に変更されました。
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ コマンドの実行は失敗しました: 引数 'executable' がPOST アクションの構成に存在しません。
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
index 61e93bbd5e25..4249b91d6cd7 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
이 작업을 실행하시겠어요 [{0} (예) |{1} (아니요)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ '{0}' 게시물 매크로 함수 인수가 필수이지만 구성되지 않았습니다.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0}을(를) 수정했습니다.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ 명령을 실행하지 못했습니다. 게시 작업 구성에 'executable' 인수가 없습니다.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
index 70154b9a40c1..23cc4f066fa5 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Chcesz uruchomić tę akcję [{0}(tak)|{1}(nie)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ Argument po wystąpieniu akcji „{0}” jest obowiązkowy, ale nie jest skonfigurowany.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
Pomyślnie zmodyfikowano {0}.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Nie można uruchomić polecenia: brak argumentu "executable" w konfiguracji akcji post.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
index 9f1efc54d0d7..6e26bb078114 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Deseja executar esta ação [{0}(yes)|{1}(no)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ O argumento pós-ação '{0}' é obrigatório, mas não configurado.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
Modificado com sucesso {0}.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Falha ao executar o comando: o argumento 'executável' está ausente na configuração pós-ação.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
index c60b3dde870e..64d24799e119 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Вы хотите выполнить это действие [{0}(да)|{1}(нет)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ Аргумент после действия "{0}" является обязательным, но не настроен.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
Успешное изменение {0}.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Не удалось выполнить команду: аргумент executable отсутствует в конфигурации действия публикации.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
index 25151df45489..d611f7f585f6 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
Bu eylemi çalıştırmak istiyor musunuz [{0}(evet)|{1}(hayır)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ '{0}' eylem sonrası bağımsız değişkeni zorunlu, ancak yapılandırılmamış.
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
{0} başarıyla değiştirildi.
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ Komut çalıştırılamadı: Gönderme eylemi yapılandırmasında 'executable' bağımsız değişkeni eksik.
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
index 4c8e5deccbfe..08bf8872676d 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
是否要运行此操作 [{0}(是)|{1}(否)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ 发布操作参数“{0}”是必需的,但未进行配置。
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
已成功修改 {0}。
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ 无法运行命令: 在发布操作配置中缺少参数“可执行”。
diff --git a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
index 0b1534e847f3..6023fda5c481 100644
--- a/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf
@@ -825,6 +825,11 @@ The header is followed by the list of parameters and their errors (might be seve
是否要執行此動作 [{0}(是)|{1}(否)]?
+
+
+ Post action argument '{0}' is not a valid boolean value.
+
+ 動作後引數 '{0}' 是強制的,但未設定。
@@ -850,6 +855,11 @@ The header is followed by the list of parameters and their errors (might be seve
已成功修改 {0}。
+
+
+ Attempting to find json file '{0}' in '{1}'
+
+ 無法執行命令: 後續動作設定中遺漏引數 'executable'。
diff --git a/test/Microsoft.TemplateEngine.Cli.UnitTests/PostActionTests/AddJsonPropertyPostActionTests.cs b/test/Microsoft.TemplateEngine.Cli.UnitTests/PostActionTests/AddJsonPropertyPostActionTests.cs
index 179a9de0eec1..6e43810e538e 100644
--- a/test/Microsoft.TemplateEngine.Cli.UnitTests/PostActionTests/AddJsonPropertyPostActionTests.cs
+++ b/test/Microsoft.TemplateEngine.Cli.UnitTests/PostActionTests/AddJsonPropertyPostActionTests.cs
@@ -2,11 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Text.Json.Nodes;
+
using Microsoft.DotNet.Cli.Utils;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Cli.PostActionProcessors;
using Microsoft.TemplateEngine.Mocks;
using Microsoft.TemplateEngine.TestHelper;
+
using Moq;
namespace Microsoft.TemplateEngine.Cli.UnitTests.PostActionTests
@@ -132,8 +134,8 @@ public void FailsWhenMandatoryArgumentsNotConfigured(ModifyJsonPostActionTestCas
}
[Theory]
- [MemberData(nameof(ModifyJsonPostActionTestCase.SuccessTestCases), MemberType = typeof(ModifyJsonPostActionTestCase))]
- public void CanSuccessfullyModifyJsonFile(ModifyJsonPostActionTestCase testCase)
+ [MemberData(nameof(ModifyJsonPostActionTestCase<(JsonNode, bool)>.SuccessTestCases), MemberType = typeof(ModifyJsonPostActionTestCase<(JsonNode, bool)>))]
+ public void CanSuccessfullyModifyJsonFile(ModifyJsonPostActionTestCase<(JsonNode, bool)> testCase)
{
string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
@@ -164,7 +166,183 @@ public void CanSuccessfullyModifyJsonFile(ModifyJsonPostActionTestCase
Assert.NotNull(modifiedJsonContent);
- testCase.AssertionCallback(modifiedJsonContent);
+ testCase.AssertionCallback((modifiedJsonContent, false));
+ }
+
+ [Theory]
+ [MemberData(nameof(ModifyJsonPostActionTestCase<(JsonNode, bool)>.SuccessTestCases), MemberType = typeof(ModifyJsonPostActionTestCase<(JsonNode, bool)>))]
+ public void CanSuccessfullyCreateAndModifyJsonFileWhenAllowFileCreationAndPathCreationAreSet(ModifyJsonPostActionTestCase<(JsonNode, bool)> testCase)
+ {
+ string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
+
+ string jsonFileName = Guid.NewGuid().ToString("N") + ".json";
+ testCase.PostActionArgs["jsonFileName"] = jsonFileName;
+ testCase.PostActionArgs["allowFileCreation"] = "true";
+ testCase.PostActionArgs["allowPathCreation"] = "true";
+ IPostAction postAction = new MockPostAction(default, default, default, default, default!)
+ {
+ ActionId = AddJsonPropertyPostActionProcessor.ActionProcessorId,
+ Args = testCase.PostActionArgs
+ };
+
+ AddJsonPropertyPostActionProcessor processor = new();
+
+ bool result = processor.Process(
+ _engineEnvironmentSettings,
+ postAction,
+ new MockCreationEffects(),
+ new MockCreationResult(),
+ targetBasePath);
+
+ Assert.True(result);
+
+ string jsonFilePath = Path.Combine(targetBasePath, jsonFileName);
+ JsonNode? modifiedJsonContent = JsonNode.Parse(_engineEnvironmentSettings.Host.FileSystem.ReadAllText(jsonFilePath));
+
+ Assert.NotNull(modifiedJsonContent);
+
+ testCase.AssertionCallback((modifiedJsonContent, true));
+ }
+
+ [Theory]
+ [MemberData(nameof(ModifyJsonPostActionTestCase<(JsonNode, bool)>.SuccessTestCases), MemberType = typeof(ModifyJsonPostActionTestCase<(JsonNode, bool)>))]
+ public void CanSuccessfullyModifyJsonFileWhenPathDoesNotExistAndAllowPathCreationIsSet(ModifyJsonPostActionTestCase<(JsonNode, bool)> testCase)
+ {
+ string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
+
+ string jsonFileName = Guid.NewGuid().ToString("N") + ".json";
+ testCase.PostActionArgs["jsonFileName"] = jsonFileName;
+ testCase.PostActionArgs["allowPathCreation"] = "true";
+
+ string jsonFilePath = CreateJsonFile(targetBasePath, jsonFileName, "{}");
+
+ IPostAction postAction = new MockPostAction(default, default, default, default, default!)
+ {
+ ActionId = AddJsonPropertyPostActionProcessor.ActionProcessorId,
+ Args = testCase.PostActionArgs
+ };
+
+ AddJsonPropertyPostActionProcessor processor = new();
+
+ bool result = processor.Process(
+ _engineEnvironmentSettings,
+ postAction,
+ new MockCreationEffects(),
+ new MockCreationResult(),
+ targetBasePath);
+
+ Assert.True(result);
+
+ JsonNode? modifiedJsonContent = JsonNode.Parse(_engineEnvironmentSettings.Host.FileSystem.ReadAllText(jsonFilePath));
+
+ Assert.NotNull(modifiedJsonContent);
+
+ testCase.AssertionCallback((modifiedJsonContent, true));
+ }
+
+ [Fact]
+ public void FailsWhenFileExistsButPathDoesNotExistAndAllowPathCreationIsNotSet()
+ {
+ string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
+
+ string jsonFileName = Guid.NewGuid().ToString("N") + ".json";
+ string originalJsonContent = "{}";
+ string jsonFilePath = CreateJsonFile(targetBasePath, jsonFileName, originalJsonContent);
+
+ IPostAction postAction = new MockPostAction(default, default, default, default, default!)
+ {
+ ActionId = AddJsonPropertyPostActionProcessor.ActionProcessorId,
+ Args = new Dictionary
+ {
+ ["jsonFileName"] = jsonFileName,
+ ["allowPathCreation"] = "false",
+ ["parentPropertyPath"] = "",
+ ["newJsonPropertyName"] = "lastName",
+ ["newJsonPropertyValue"] = "Watson"
+ }
+ };
+
+ AddJsonPropertyPostActionProcessor processor = new();
+
+ bool result = processor.Process(
+ _engineEnvironmentSettings,
+ postAction,
+ new MockCreationEffects(),
+ new MockCreationResult(),
+ targetBasePath);
+
+ Assert.False(result);
+
+ Assert.Equal(originalJsonContent, _engineEnvironmentSettings.Host.FileSystem.ReadAllText(jsonFilePath));
+ }
+
+ [Fact]
+ public void FailsWhenFileDoesNotExistAndAllowFileCreationIsNotSet()
+ {
+ string jsonFileName = Guid.NewGuid().ToString("N") + ".json";
+
+ IPostAction postAction = new MockPostAction(default, default, default, default, default!)
+ {
+ ActionId = AddJsonPropertyPostActionProcessor.ActionProcessorId,
+ Args = new Dictionary
+ {
+ ["jsonFileName"] = jsonFileName,
+ ["allowFileCreation"] = "false",
+ ["parentPropertyPath"] = "",
+ ["newJsonPropertyName"] = "lastName",
+ ["newJsonPropertyValue"] = "Watson"
+ }
+ };
+
+ AddJsonPropertyPostActionProcessor processor = new();
+
+ string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
+ bool result = processor.Process(
+ _engineEnvironmentSettings,
+ postAction,
+ new MockCreationEffects(),
+ new MockCreationResult(),
+ targetBasePath);
+
+ Assert.False(result);
+
+ string jsonFilePath = Path.Combine(targetBasePath, jsonFileName);
+ Assert.False(_engineEnvironmentSettings.Host.FileSystem.FileExists(jsonFilePath));
+ }
+
+ [Fact]
+ public void FailsWhenFileDoesNotExistAndAllowFileCreationIsSetButAllowPathCreationIsNotSet()
+ {
+ string jsonFileName = Guid.NewGuid().ToString("N") + ".json";
+
+ IPostAction postAction = new MockPostAction(default, default, default, default, default!)
+ {
+ ActionId = AddJsonPropertyPostActionProcessor.ActionProcessorId,
+ Args = new Dictionary
+ {
+ ["jsonFileName"] = jsonFileName,
+ ["allowFileCreation"] = "true",
+ ["allowPathCreation"] = "false",
+ ["parentPropertyPath"] = "",
+ ["newJsonPropertyName"] = "lastName",
+ ["newJsonPropertyValue"] = "Watson"
+ }
+ };
+
+ AddJsonPropertyPostActionProcessor processor = new();
+
+ string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath();
+ bool result = processor.Process(
+ _engineEnvironmentSettings,
+ postAction,
+ new MockCreationEffects(),
+ new MockCreationResult(),
+ targetBasePath);
+
+ Assert.False(result);
+
+ string jsonFilePath = Path.Combine(targetBasePath, jsonFileName);
+ Assert.Equal("{}", _engineEnvironmentSettings.Host.FileSystem.ReadAllText(jsonFilePath));
}
private string CreateJsonFile(string targetBasePath, string fileName, string jsonContent)
@@ -182,7 +360,7 @@ public record ModifyJsonPostActionTestCase(
Dictionary PostActionArgs,
Action AssertionCallback)
{
- private static readonly ModifyJsonPostActionTestCase[] _successTestCases =
+ private static readonly ModifyJsonPostActionTestCase<(JsonNode ResultingJson, bool IsNewJson)>[] _successTestCases =
{
new(
"Can add simple property",
@@ -194,10 +372,9 @@ public record ModifyJsonPostActionTestCase(
["newJsonPropertyName"] = "lastName",
["newJsonPropertyValue"] = "Watson"
},
- (JsonNode modifiedJsonContent) =>
+ tuple =>
{
- Assert.NotNull(modifiedJsonContent["person"]!["lastName"]);
- Assert.Equal("Watson", modifiedJsonContent["person"]!["lastName"]!.ToString());
+ Assert.Equal("Watson", tuple.ResultingJson["person"]!["lastName"]!.ToString());
}),
new(
@@ -210,10 +387,9 @@ public record ModifyJsonPostActionTestCase(
["newJsonPropertyName"] = "address",
["newJsonPropertyValue"] = @"{""street"": ""street name"", ""zip"": ""zipcode""}"
},
- (JsonNode modifiedJsonContent) =>
+ tuple =>
{
- Assert.NotNull(modifiedJsonContent["person"]!["address"]);
- Assert.Equal("street name", modifiedJsonContent["person"]!["address"]!["street"]!.ToString());
+ Assert.Equal("street name", tuple.ResultingJson["person"]!["address"]!["street"]!.ToString());
}),
new(
@@ -226,10 +402,16 @@ public record ModifyJsonPostActionTestCase(
["newJsonPropertyName"] = "secondProperty",
["newJsonPropertyValue"] = "bar"
},
- (JsonNode modifiedJsonContent) =>
+ tuple =>
{
- Assert.NotNull(modifiedJsonContent["secondProperty"]);
- Assert.Equal(@"{""firstProperty"":""foo"",""secondProperty"":""bar""}", modifiedJsonContent.ToJsonString());
+ if (tuple.IsNewJson)
+ {
+ Assert.Equal(@"{""secondProperty"":""bar""}", tuple.ResultingJson.ToJsonString());
+ }
+ else
+ {
+ Assert.Equal(@"{""firstProperty"":""foo"",""secondProperty"":""bar""}", tuple.ResultingJson.ToJsonString());
+ }
}),
new(
@@ -242,9 +424,16 @@ public record ModifyJsonPostActionTestCase(
["newJsonPropertyName"] = "foo",
["newJsonPropertyValue"] = "bar"
},
- (JsonNode modifiedJsonContent) =>
+ tuple =>
{
- Assert.Equal(@"{""rootProperty"":{""subProperty1"":{""subProperty2"":{""subProperty3"":{""name"":""test"",""foo"":""bar""}}}}}", modifiedJsonContent.ToJsonString());
+ if (tuple.IsNewJson)
+ {
+ Assert.Equal(@"{""rootProperty"":{""subProperty1"":{""subProperty2"":{""subProperty3"":{""foo"":""bar""}}}}}", tuple.ResultingJson.ToJsonString());
+ }
+ else
+ {
+ Assert.Equal(@"{""rootProperty"":{""subProperty1"":{""subProperty2"":{""subProperty3"":{""name"":""test"",""foo"":""bar""}}}}}", tuple.ResultingJson.ToJsonString());
+ }
})
};
@@ -297,7 +486,7 @@ public record ModifyJsonPostActionTestCase(
public static IEnumerable