Merge branch 'release/10.5' into v10/dev
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
namespace Umbraco.Cms.Persistence.SqlServer;
|
||||
|
||||
/// <summary>
|
||||
/// Constants related to SQLite.
|
||||
/// Constants related to SQL Server.
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// SQLite provider name.
|
||||
/// SQL Server provider name.
|
||||
/// </summary>
|
||||
public const string ProviderName = "Microsoft.Data.SqlClient";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Extensions;
|
||||
@@ -50,6 +51,25 @@ public class SqlAzureDatabaseProviderMetadata : IDatabaseProviderMetadata
|
||||
/// <inheritdoc />
|
||||
public bool ForceCreateDatabase => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRecognizeConnectionString(string? connectionString)
|
||||
{
|
||||
if (connectionString is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var builder = new SqlConnectionStringBuilder(connectionString);
|
||||
|
||||
return string.IsNullOrEmpty(builder.AttachDBFilename) && builder.DataSource.Contains("database.windows.net");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public string GenerateConnectionString(DatabaseModel databaseModel)
|
||||
{
|
||||
|
||||
@@ -51,6 +51,27 @@ public class SqlLocalDbDatabaseProviderMetadata : IDatabaseProviderMetadata
|
||||
/// <inheritdoc />
|
||||
public bool ForceCreateDatabase => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRecognizeConnectionString(string? connectionString)
|
||||
{
|
||||
if (connectionString is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var builder = new SqlConnectionStringBuilder(connectionString);
|
||||
|
||||
return !string.IsNullOrEmpty(builder.AttachDBFilename);
|
||||
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GenerateConnectionString(DatabaseModel databaseModel)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Data.Common;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Persistence.SqlServer.Services;
|
||||
|
||||
@@ -49,6 +52,26 @@ public class SqlServerDatabaseProviderMetadata : IDatabaseProviderMetadata
|
||||
/// <inheritdoc />
|
||||
public bool ForceCreateDatabase => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRecognizeConnectionString(string? connectionString)
|
||||
{
|
||||
if (connectionString is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var builder = new SqlConnectionStringBuilder(connectionString);
|
||||
|
||||
return string.IsNullOrEmpty(builder.AttachDBFilename);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GenerateConnectionString(DatabaseModel databaseModel) =>
|
||||
databaseModel.IntegratedAuth
|
||||
|
||||
@@ -56,6 +56,26 @@ public class SqliteDatabaseProviderMetadata : IDatabaseProviderMetadata
|
||||
/// </remarks>
|
||||
public bool ForceCreateDatabase => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRecognizeConnectionString(string? connectionString)
|
||||
{
|
||||
if (connectionString is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder(connectionString);
|
||||
|
||||
return !string.IsNullOrEmpty(builder.DataSource);
|
||||
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public string GenerateConnectionString(DatabaseModel databaseModel)
|
||||
{
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Umbraco.Cms.Infrastructure.Install
|
||||
private bool IsBrandNewInstall =>
|
||||
_connectionStrings.CurrentValue.IsConnectionStringConfigured() == false ||
|
||||
_databaseBuilder.IsDatabaseConfigured == false ||
|
||||
(_databaseBuilder.CanConnectToDatabase == false && _databaseProviderMetadata.CanForceCreateDatabase(_umbracoDatabaseFactory.SqlContext.SqlSyntax.DbProvider)) ||
|
||||
(_databaseBuilder.CanConnectToDatabase == false && _databaseProviderMetadata.CanForceCreateDatabase(_umbracoDatabaseFactory)) ||
|
||||
_databaseBuilder.IsUmbracoInstalled() == false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
@@ -26,8 +27,32 @@ public static class DatabaseProviderMetadataExtensions
|
||||
/// <returns>
|
||||
/// <c>true</c> if a database can be created for the specified provider name; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
[Obsolete("Use CanForceCreateDatabase that takes an IUmbracoDatabaseFactory. Scheduled for removal in Umbraco 13.")]
|
||||
public static bool CanForceCreateDatabase(this IEnumerable<IDatabaseProviderMetadata> databaseProviderMetadata, string? providerName)
|
||||
=> databaseProviderMetadata.FirstOrDefault(x => string.Equals(x.ProviderName, providerName, StringComparison.InvariantCultureIgnoreCase))?.ForceCreateDatabase == true;
|
||||
{
|
||||
return databaseProviderMetadata
|
||||
.FirstOrDefault(x =>
|
||||
string.Equals(x.ProviderName, providerName, StringComparison.InvariantCultureIgnoreCase))
|
||||
?.ForceCreateDatabase == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a database can be created for the specified provider name while ignoring the value of <see cref="GlobalSettings.InstallMissingDatabase" />.
|
||||
/// </summary>
|
||||
/// <param name="databaseProviderMetadata">The database provider metadata.</param>
|
||||
/// <param name="umbracoDatabaseFactory">The database factory.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if a database can be created for the specified database; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool CanForceCreateDatabase(this IEnumerable<IDatabaseProviderMetadata> databaseProviderMetadata, IUmbracoDatabaseFactory umbracoDatabaseFactory)
|
||||
{
|
||||
// In case more metadata providers can recognize the connection string, we need to check if any can force create.
|
||||
// E.g. Both SqlServer and SqlAzure will recognize an azure connection string, but luckily none of those can force create.
|
||||
return databaseProviderMetadata
|
||||
.Where(x =>
|
||||
string.Equals(x.ProviderName, umbracoDatabaseFactory.SqlContext.SqlSyntax.ProviderName, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& x.CanRecognizeConnectionString(umbracoDatabaseFactory.ConnectionString) && x.IsAvailable).Any(x => x.ForceCreateDatabase == true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the connection string.
|
||||
|
||||
@@ -82,6 +82,12 @@ public interface IDatabaseProviderMetadata
|
||||
/// </summary>
|
||||
public bool ForceCreateDatabase { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this connections could have been build using <see cref="GenerateConnectionString"/>.
|
||||
/// </summary>
|
||||
public bool CanRecognizeConnectionString(string? connectionString) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a connection string for this provider.
|
||||
/// </summary>
|
||||
|
||||
@@ -29,6 +29,7 @@ public sealed class RichTextEditorPastedImages
|
||||
private readonly IPublishedUrlProvider _publishedUrlProvider;
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly string _tempFolderAbsolutePath;
|
||||
|
||||
public RichTextEditorPastedImages(
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
@@ -52,6 +53,9 @@ public sealed class RichTextEditorPastedImages
|
||||
_mediaUrlGenerators = mediaUrlGenerators;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_publishedUrlProvider = publishedUrlProvider;
|
||||
|
||||
_tempFolderAbsolutePath = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempImageUploads);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,12 +89,14 @@ public sealed class RichTextEditorPastedImages
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsValidPath(tmpImgPath) == false)
|
||||
|
||||
var absoluteTempImagePath = Path.GetFullPath(_hostingEnvironment.MapPathContentRoot(tmpImgPath));
|
||||
|
||||
if (IsValidPath(absoluteTempImagePath) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var absoluteTempImagePath = _hostingEnvironment.MapPathContentRoot(tmpImgPath);
|
||||
var fileName = Path.GetFileName(absoluteTempImagePath);
|
||||
var safeFileName = fileName.ToSafeFileName(_shortStringHelper);
|
||||
|
||||
@@ -191,5 +197,8 @@ public sealed class RichTextEditorPastedImages
|
||||
return htmlDoc.DocumentNode.OuterHtml;
|
||||
}
|
||||
|
||||
private bool IsValidPath(string imagePath) => imagePath.StartsWith(Constants.SystemDirectories.TempImageUploads);
|
||||
private bool IsValidPath(string imagePath)
|
||||
{
|
||||
return imagePath.StartsWith(_tempFolderAbsolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ public class RuntimeState : IRuntimeState
|
||||
// cannot connect to configured database, this is bad, fail
|
||||
_logger.LogDebug("Could not connect to database.");
|
||||
|
||||
if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory.ProviderName))
|
||||
if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory))
|
||||
{
|
||||
// ok to install on a configured but missing database
|
||||
Level = RuntimeLevel.Install;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Persistence.SqlServer.Services;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Persistence.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class SqlAzureDatabaseProviderMetadataTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase("myServer", "myDatabase", "myLogin", "myPassword", true /*ignored*/, ExpectedResult = "Server=tcp:myServer.database.windows.net,1433;Database=myDatabase;User ID=myLogin@myServer;Password=myPassword")]
|
||||
[TestCase("myServer", "myDatabase", "myLogin", "myPassword", false, ExpectedResult = "Server=tcp:myServer.database.windows.net,1433;Database=myDatabase;User ID=myLogin@myServer;Password=myPassword")]
|
||||
public string GenerateConnectionString(string server, string databaseName, string login, string password, bool integratedAuth)
|
||||
{
|
||||
var sut = new SqlAzureDatabaseProviderMetadata();
|
||||
return sut.GenerateConnectionString(new DatabaseModel()
|
||||
{
|
||||
DatabaseName = databaseName,
|
||||
Login = login,
|
||||
Password = password,
|
||||
Server = server,
|
||||
IntegratedAuth = integratedAuth
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("Server=myServer;Database=myDatabase;Integrated Security=true", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=myServer;Database=myDatabase;User Id=myLogin;Password=myPassword", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=tcp:cmstest27032000.database.windows.net,1433;Database=test_27032000;User ID=asdasdas@cmstest27032000;Password=123456879", ExpectedResult = true)] // Azure
|
||||
[TestCase("Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", ExpectedResult = false)] // Sqlite
|
||||
[TestCase("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=aspnet-MvcMovie;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\\umbraco.mdf", ExpectedResult = false)] // localDB
|
||||
public bool CanRecognizeConnectionString(string connectionString)
|
||||
{
|
||||
var sut = new SqlAzureDatabaseProviderMetadata();
|
||||
return sut.CanRecognizeConnectionString(connectionString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Persistence.SqlServer.Services;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Persistence.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class SqlLocalDbDatabaseProviderMetadataTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase("ignored", "myDatabase", "ignored", "ignored", true, ExpectedResult = "Data Source=(localdb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\myDatabase.mdf;Integrated Security=True")]
|
||||
[TestCase("ignored", "myDatabase2", "ignored", "ignored", false /*ignored*/, ExpectedResult = "Data Source=(localdb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\myDatabase2.mdf;Integrated Security=True")]
|
||||
public string GenerateConnectionString(string server, string databaseName, string login, string password, bool integratedAuth)
|
||||
{
|
||||
var sut = new SqlLocalDbDatabaseProviderMetadata();
|
||||
return sut.GenerateConnectionString(new DatabaseModel()
|
||||
{
|
||||
DatabaseName = databaseName,
|
||||
Login = login,
|
||||
Password = password,
|
||||
Server = server,
|
||||
IntegratedAuth = integratedAuth,
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("Server=myServer;Database=myDatabase;Integrated Security=true", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=myServer;Database=myDatabase;User Id=myLogin;Password=myPassword", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=tcp:cmstest27032000.database.windows.net,1433;Database=test_27032000;User ID=asdasdas@cmstest27032000;Password=123456879", ExpectedResult = false)] // Azure
|
||||
[TestCase("Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", ExpectedResult = false)] // Sqlite
|
||||
[TestCase("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=aspnet-MvcMovie;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\\umbraco.mdf", ExpectedResult = true)] // localDB
|
||||
public bool CanRecognizeConnectionString(string connectionString)
|
||||
{
|
||||
var sut = new SqlLocalDbDatabaseProviderMetadata();
|
||||
return sut.CanRecognizeConnectionString(connectionString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Persistence.SqlServer.Services;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Persistence.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class SqlServerDatabaseProviderMetadataTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase("myServer", "myDatabase", "myLogin", "myPassword", true, ExpectedResult = "Server=myServer;Database=myDatabase;Integrated Security=true")]
|
||||
[TestCase("myServer", "myDatabase", "myLogin", "myPassword", false, ExpectedResult = "Server=myServer;Database=myDatabase;User Id=myLogin;Password=myPassword")]
|
||||
public string GenerateConnectionString(string server, string databaseName, string login, string password, bool integratedAuth)
|
||||
{
|
||||
var sut = new SqlServerDatabaseProviderMetadata();
|
||||
return sut.GenerateConnectionString(new DatabaseModel()
|
||||
{
|
||||
DatabaseName = databaseName,
|
||||
Login = login,
|
||||
Password = password,
|
||||
Server = server,
|
||||
IntegratedAuth = integratedAuth
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("Server=myServer;Database=myDatabase;Integrated Security=true", ExpectedResult = true)] // SqlServer
|
||||
[TestCase("Server=myServer;Database=myDatabase;User Id=myLogin;Password=myPassword", ExpectedResult = true)] // SqlServer
|
||||
[TestCase("Server=tcp:cmstest27032000.database.windows.net,1433;Database=test_27032000;User ID=asdasdas@cmstest27032000;Password=123456879", ExpectedResult = true)] // Azure
|
||||
[TestCase("Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", ExpectedResult = false)] // Sqlite
|
||||
[TestCase("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=aspnet-MvcMovie;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\\umbraco.mdf", ExpectedResult = false)] // localDB
|
||||
public bool CanRecognizeConnectionString(string connectionString)
|
||||
{
|
||||
var sut = new SqlServerDatabaseProviderMetadata();
|
||||
return sut.CanRecognizeConnectionString(connectionString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Persistence.Sqlite.Services;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Persistence.Sqlite;
|
||||
|
||||
[TestFixture]
|
||||
public class SqliteDatabaseProviderMetadataTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase("ignored", "myDatabase", "ignored", "ignored", true /*ignored*/, ExpectedResult = "Data Source=|DataDirectory|/myDatabase.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True")]
|
||||
[TestCase("ignored", "myDatabase2", "ignored", "ignored", false /*ignored*/, ExpectedResult = "Data Source=|DataDirectory|/myDatabase2.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True")]
|
||||
public string GenerateConnectionString(string server, string databaseName, string login, string password, bool integratedAuth)
|
||||
{
|
||||
var sut = new SqliteDatabaseProviderMetadata();
|
||||
return sut.GenerateConnectionString(new DatabaseModel()
|
||||
{
|
||||
DatabaseName = databaseName,
|
||||
Login = login,
|
||||
Password = password,
|
||||
Server = server,
|
||||
IntegratedAuth = integratedAuth
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("Server=myServer;Database=myDatabase;Integrated Security=true", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=myServer;Database=myDatabase;User Id=myLogin;Password=myPassword", ExpectedResult = false)] // SqlServer
|
||||
[TestCase("Server=tcp:cmstest27032000.database.windows.net,1433;Database=test_27032000;User ID=asdasdas@cmstest27032000;Password=123456879", ExpectedResult = false)] // Azure
|
||||
[TestCase("Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", ExpectedResult = true)] // Sqlite
|
||||
[TestCase("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=aspnet-MvcMovie;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\\umbraco.mdf", ExpectedResult = false)] // localDB
|
||||
public bool CanRecognizeConnectionString(string connectionString)
|
||||
{
|
||||
var sut = new SqliteDatabaseProviderMetadata();
|
||||
return sut.CanRecognizeConnectionString(connectionString);
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,8 @@ public class DatabaseSettingsFactoryTests
|
||||
public Func<DatabaseModel, string> GenerateConnectionStringDelegate { get; set; } =
|
||||
_ => "ConnectionString";
|
||||
|
||||
public bool CanRecognizeConnectionString(string? connectionString) => false;
|
||||
|
||||
public string? GenerateConnectionString(DatabaseModel databaseModel) => GenerateConnectionStringDelegate(databaseModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Umbraco.Cms.Persistence.Sqlite\Umbraco.Cms.Persistence.Sqlite.csproj" />
|
||||
<ProjectReference Include="..\Umbraco.Tests.Common\Umbraco.Tests.Common.csproj" />
|
||||
<ProjectReference Include="..\..\src\Umbraco.Cms.ManagementApi\Umbraco.Cms.ManagementApi.csproj" />
|
||||
<ProjectReference Include="..\..\src\Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
|
||||
"version": "10.5.0-rc",
|
||||
"version": "10.5.0",
|
||||
"assemblyVersion": {
|
||||
"precision": "build"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user