From 45042ed7e76d7821b45dee809f9d531d0ad14d44 Mon Sep 17 00:00:00 2001
From: VasiliyF <5789590+vfofanov@users.noreply.github.com>
Date: Sat, 3 Oct 2026 21:14:14 +0200
Subject: [PATCH 1/3] Build with DragoAnt.MSBuildKit 0.1.0 instead of
MSBuild.Routine
- Remove the .msbuild submodule and its empty secrets templates.
- Install the kit release 0.1.0 under .toolkit/ (with PackageAsProj)
and import its init.props / init.targets.
- Drop settings the kit now defaults (licence, repository URL, release
notes, TFM strategy) and the test-package swaps it already does.
- Drop the package versions the kit provides from
Directory.Packages.props (xunit.v3*, AwesomeAssertions, NSubstitute*,
Microsoft.Testing.Extensions.CodeCoverage).
- Keep the 2025 copyright year and declare VersionPrefix 2.0.0.
---
.github/dependabot.yml | 5 -
.gitmodules | 4 -
.msbuild | 1 -
.../Directory.Secrets.props | 2 -
.../DragoAnt.src/Directory.Secrets.props | 2 -
.toolkit/kit.json | 6 +
.toolkit/kit.parts | 20 ++
.../audit/audit.autodetect-mutex.targets | 15 ++
.../audit/audit.roslyn-satellites.targets | 33 +++
.../core.common.props | 32 +++
.../core.locals.props | 8 +
.../core.locals.targets | 8 +
.../DragoAnt.MSBuildKit.Core/git.root.props | 29 +++
.../git.routine.props | 12 +
.../DragoAnt.MSBuildKit.Core/init.props | 10 +
.../DragoAnt.MSBuildKit.Core/init.targets | 5 +
.../project-types.autodetect.props | 46 ++++
.../tfm.routine.props | 42 ++++
.../init.props | 3 +
.../init.targets | 3 +
.../local.compile.props | 7 +
.../local.compile.targets | 40 ++++
.../init.props | 9 +
.../init.targets | 10 +
.../local.directory.secrets.cleanup.targets | 19 ++
.../local.directory.secrets.props | 31 +++
.../local.directory.secrets.targets | 73 ++++++
.../init.props | 7 +
.../init.targets | 14 ++
.../local.secrets.cleanup.targets | 10 +
.../local.secrets.props | 10 +
.../local.secrets.targets | 61 +++++
.../init.last.targets | 8 +
.../packageAsProj.targets | 42 ++++
.../audit/audit.package.targets | 128 ++++++++++
.../DragoAnt.MSBuildKit.Packaging/init.props | 18 ++
.../init.targets | 5 +
.../package.inspect.targets | 110 +++++++++
.../package.targets | 81 +++++++
.../init.last.targets | 5 +
.../private.assets.references.targets | 14 ++
.../audit.tests.project.xunit.v3.targets | 15 ++
.../implicit.package.targets | 26 ++
.../init.last.targets | 6 +
.../init.props | 12 +
.../init.targets | 7 +
.../tests.lib.project.xunit.v3.common.props | 5 +
.../tests.project.xunit.v3.common.props | 8 +
.../tests.project.xunit.v3.routine.props | 8 +
.../tests.project.xunit.v3.routine.targets | 57 +++++
.../audit/audit.internalsVisibleTo.targets | 20 ++
.../audit/audit.tests.lib.project.targets | 37 +++
.../audit/audit.tests.project.targets | 82 +++++++
.../implicit.package.targets | 42 ++++
.../init.last.targets | 6 +
.../DragoAnt.MSBuildKit.Testing/init.props | 15 ++
.../DragoAnt.MSBuildKit.Testing/init.targets | 9 +
.../test.project.internalsVisibleTo.targets | 31 +++
.../tests.lib.project.common.props | 21 ++
.../tests.project.common.props | 22 ++
.../tests.project.lib.global.usings.targets | 28 +++
.../tests.project.mtp.routine.targets | 25 ++
.../tests.project.props | 44 ++++
.../tests.project.targets | 35 +++
.../init.props | 5 +
.../tfm.constants.props | 44 ++++
.../ci.github.props | 27 +++
.../DragoAnt.MSBuildKit.Vcs.GitHub/init.props | 5 +
...audit.implicit.packages.duplicates.targets | 34 +++
.../audit/audit.prerelease.packages.targets | 29 +++
.../audit/audit.restrict.packages.targets | 32 +++
.../audit/audit.restrict.reference.targets | 35 +++
.../audit/audit.shared.properties.targets | 98 ++++++++
.../audit/audit.version.targets | 93 ++++++++
.../DragoAnt.MSBuildKit/init.last.props | 11 +
.../DragoAnt.MSBuildKit/init.last.targets | 7 +
.../msbuild/DragoAnt.MSBuildKit/init.props | 17 ++
.../msbuild/DragoAnt.MSBuildKit/init.targets | 16 ++
.../msbuild/DragoAnt.MSBuildKit/product.props | 13 +
.../project.global.metadata.targets | 31 +++
.../project.global.usings.targets | 12 +
.../twae.shared.init.props | 8 +
.../msbuild/DragoAnt.MSBuildKit/version.props | 145 ++++++++++++
.../DragoAnt.MSBuildKit/version.targets | 38 +++
.toolkit/msbuild/init.company.props | 35 +++
.toolkit/msbuild/init.company.targets | 5 +
.toolkit/msbuild/init.props | 26 ++
.toolkit/msbuild/init.targets | 28 +++
.toolkit/res/package.icon.png | Bin 0 -> 10282 bytes
.toolkit/update.ps1 | 214 +++++++++++++++++
.toolkit/update.sh | 222 ++++++++++++++++++
CONTRIBUTING.md | 14 +-
Directory.Build.props | 12 +-
Directory.Build.targets | 17 +-
Directory.Packages.props | 9 -
Directory.Version.props | 5 +
DragoAnt.System.Text.Json.slnx | 5 +-
97 files changed, 2785 insertions(+), 56 deletions(-)
delete mode 100644 .gitmodules
delete mode 160000 .msbuild
delete mode 100644 .msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props
delete mode 100644 .msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props
create mode 100644 .toolkit/kit.json
create mode 100644 .toolkit/kit.parts
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/init.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/product.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/version.props
create mode 100644 .toolkit/msbuild/DragoAnt.MSBuildKit/version.targets
create mode 100644 .toolkit/msbuild/init.company.props
create mode 100644 .toolkit/msbuild/init.company.targets
create mode 100644 .toolkit/msbuild/init.props
create mode 100644 .toolkit/msbuild/init.targets
create mode 100644 .toolkit/res/package.icon.png
create mode 100644 .toolkit/update.ps1
create mode 100644 .toolkit/update.sh
create mode 100644 Directory.Version.props
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 1f1aea1..0f211da 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -47,8 +47,3 @@ updates:
- dependency-name: Microsoft.Extensions.*
update-types:
- version-update:semver-major
-
- - package-ecosystem: gitsubmodule
- directory: /
- schedule:
- interval: weekly
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index b27f125..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,4 +0,0 @@
-[submodule ".msbuild"]
- path = .msbuild
- url = https://github.com/DragoAnt/MSBuild.Routine.git
- branch = main
diff --git a/.msbuild b/.msbuild
deleted file mode 160000
index f62e88f..0000000
--- a/.msbuild
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit f62e88f837ba7df06262ce9686b92dcd87469461
diff --git a/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props b/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props
deleted file mode 100644
index 8c119d5..0000000
--- a/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props b/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props
deleted file mode 100644
index 8c119d5..0000000
--- a/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/.toolkit/kit.json b/.toolkit/kit.json
new file mode 100644
index 0000000..dcb1eef
--- /dev/null
+++ b/.toolkit/kit.json
@@ -0,0 +1,6 @@
+{
+ "repository": "DragoAnt/MSBuildKit",
+ "version": "0.1.0",
+ "sha256": "55c2f40a21fed8bcb5f727a56cf4830e476277574463437dd41560980dbec887",
+ "parts": ["PackageAsProj"]
+}
diff --git a/.toolkit/kit.parts b/.toolkit/kit.parts
new file mode 100644
index 0000000..180cd2b
--- /dev/null
+++ b/.toolkit/kit.parts
@@ -0,0 +1,20 @@
+# DragoAnt.MSBuildKit parts: [required parts...]
+# The folder of a part is msbuild/DragoAnt.MSBuildKit. ("Trunk" is msbuild/DragoAnt.MSBuildKit).
+Core default
+Trunk default
+Vcs.GitHub default
+TfmConstants default
+Packaging default
+Testing default
+Testing.XUnit.v3 default Testing
+Locals.Compile default
+Locals.DirectorySecrets default
+Locals.Secrets default
+PrivateAssets default
+Project.RoslynComponent optional
+Project.CodeAnalyzer optional Project.RoslynComponent
+Project.CodeFixer optional Project.RoslynComponent Project.CodeAnalyzer
+Project.SourceGenerator optional Project.RoslynComponent
+PackageAsProj optional
+ProjMetadata optional
+EF optional
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets
new file mode 100644
index 0000000..74fc36e
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets
@@ -0,0 +1,15 @@
+
+
+
+
+
+ <_MSKit_AutoDetectedTypes>@(MSKit_AutoDetectedProjectType, ', ')
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets
new file mode 100644
index 0000000..d5b0b61
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props
new file mode 100644
index 0000000..cac50d6
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props
@@ -0,0 +1,32 @@
+
+
+
+ false
+
+ True
+
+
+ $(Version)
+
+ True
+
+ $(MSBuildThisFileDirectory)../../.local/
+
+ $([System.IO.Path]::GetDirectoryName('$(SlnxFilePath)').Replace('\', '/').TrimEnd('/'))/
+ $(MSBuildThisFileDirectory)../../../
+ $([System.IO.Path]::GetFullPath('$(MSKit_SlnFileDirectory)').Replace('\', '/').TrimEnd('/'))/
+
+ $([System.IO.Path]::GetFileNameWithoutExtension('$(SlnxFilePath)'))
+
+ $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../').Replace('\', '/').TrimEnd('/'))/
+ $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../').Replace('\', '/').TrimEnd('/'))/
+
+ <_ProjectObjDir>$(BaseIntermediateOutputPath)
+ <_ProjectObjDir Condition="'$(_ProjectObjDir)'==''">obj
+ $(_ProjectObjDir)
+ $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/$(_ProjectObjDir)'))
+ $([System.IO.Path]::GetFullPath('$(MSKit_ProjectObjDir)').TrimEnd('/').Replace('\', '/'))
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props
new file mode 100644
index 0000000..162da03
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props
@@ -0,0 +1,8 @@
+
+
+
+ $([System.Environment]::GetFolderPath(SpecialFolder.ApplicationData))\Microsoft\UserSecrets\
+ $([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.microsoft/usersecrets/
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets
new file mode 100644
index 0000000..fcae3d7
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets
@@ -0,0 +1,8 @@
+
+
+
+
+ $(MSKit_LocalSecretsBaseDirectory)$(UserSecretsId)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props
new file mode 100644
index 0000000..74b018a
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props
@@ -0,0 +1,29 @@
+
+
+
+
+ $(GITHUB_HEAD_REF)
+
+
+ $(GITHUB_REF_NAME)
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildProjectDirectory)', '.git'))
+ $([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildProjectDirectory)', '.git/HEAD'))
+
+
+
+ <_MSKit_GitHeadFile Condition="Exists('$(MSKit_GitRoot)/.git/HEAD')">$(MSKit_GitRoot)/.git/HEAD
+
+ <_MSKit_GitDirPointer Condition="'$(_MSKit_GitHeadFile)'=='' AND Exists('$(MSKit_GitRoot)/.git')">$([System.IO.File]::ReadAllText('$(MSKit_GitRoot)/.git').Trim().Replace('gitdir: ', ''))
+ <_MSKit_GitDirPointer Condition="'$(_MSKit_GitDirPointer)'!='' AND !$([System.IO.Path]::IsPathRooted('$(_MSKit_GitDirPointer)'))">$(MSKit_GitRoot)/$(_MSKit_GitDirPointer)
+ <_MSKit_GitHeadFile Condition="'$(_MSKit_GitDirPointer)'!='' AND Exists('$(_MSKit_GitDirPointer)/HEAD')">$(_MSKit_GitDirPointer)/HEAD
+
+
+
+ $([System.IO.File]::ReadAllText('$(_MSKit_GitHeadFile)').Trim().Replace('ref: refs/heads/', ''))
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props
new file mode 100644
index 0000000..2993abe
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props
@@ -0,0 +1,12 @@
+
+
+
+ $(GITHUB_REF_NAME)
+ unknown-branch
+
+ ^(main|master|release/.+)$
+ false
+ true
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props
new file mode 100644
index 0000000..edfb4ee
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets
new file mode 100644
index 0000000..2869ae6
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props
new file mode 100644
index 0000000..b6ae321
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props
@@ -0,0 +1,46 @@
+
+
+
+
+ (?<!^DragoAnt\.MSBuildKit\.Project)\.Analyzers$
+ (?<!^DragoAnt\.MSBuildKit\.Project)\.CodeFixes$
+ (?<!^DragoAnt\.MSBuildKit\.Project)\.SourceGenerator$
+
+
+
+ $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_CodeAnalyzerProjectNameRegex)))
+ True
+
+ $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_CodeFixerProjectNameRegex)))
+ True
+
+ $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_SourceGeneratorProjectNameRegex)))
+ true
+
+
+
+
+ <_MSKit_CodeAnalyzerProjectNameRegex_Shared>$(MSKit_CodeAnalyzerProjectNameRegex)
+ <_MSKit_CodeFixerProjectNameRegex_Shared>$(MSKit_CodeFixerProjectNameRegex)
+ <_MSKit_SourceGeneratorProjectNameRegex_Shared>$(MSKit_SourceGeneratorProjectNameRegex)
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props
new file mode 100644
index 0000000..0239a0f
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props
@@ -0,0 +1,42 @@
+
+
+
+
+ <_MSKit_DbpFilePath>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props'))
+ <_MSKit_DbpText Condition="'$(_MSKit_DbpFilePath)' != '' AND Exists('$(_MSKit_DbpFilePath)')">$([System.IO.File]::ReadAllText('$(_MSKit_DbpFilePath)'))
+
+ <_MSKit_DbpHasTargetFramework Condition="'$(_MSKit_DbpText)' != '' AND ($(_MSKit_DbpText.Contains('<TargetFramework>')) OR $(_MSKit_DbpText.Contains('<TargetFramework ')))">True
+ <_MSKit_DbpHasTargetFrameworks Condition="'$(_MSKit_DbpText)' != '' AND ($(_MSKit_DbpText.Contains('<TargetFrameworks>')) OR $(_MSKit_DbpText.Contains('<TargetFrameworks ')))">True
+
+ $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_DbpText), '<TargetFramework[^>/]*>([^<]*)</TargetFramework>').Groups[1].Value)
+ $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_DbpText), '<TargetFrameworks[^>/]*>([^<]*)</TargetFrameworks>').Groups[1].Value)
+
+
+
+
+ <_MSKit_GuardXmlPeekRoutine Condition="'$(MSKit_GuardXmlPeekRoutine)'!='False'">True
+ <_MSKit_CsprojText Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND '$(_MSKit_CsprojText)'==''">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)'))
+ <_MSKit_RoutineHasTargetFramework Condition="'$(_MSKit_GuardXmlPeekRoutine)'!='True'">True
+ <_MSKit_RoutineHasTargetFramework Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND ($(_MSKit_CsprojText.Contains('<TargetFramework>')) OR $(_MSKit_CsprojText.Contains('<TargetFramework ')))">True
+ <_MSKit_RoutineHasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeekRoutine)'!='True'">True
+ <_MSKit_RoutineHasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND ($(_MSKit_CsprojText.Contains('<TargetFrameworks>')) OR $(_MSKit_CsprojText.Contains('<TargetFrameworks ')))">True
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_CsprojText), '<TargetFramework[^>/]*>([^<]*)</TargetFramework>').Groups[1].Value)
+ $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_CsprojText), '<TargetFrameworks[^>/]*>([^<]*)</TargetFrameworks>').Groups[1].Value)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props
new file mode 100644
index 0000000..47e2180
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props
@@ -0,0 +1,3 @@
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets
new file mode 100644
index 0000000..3c6b4c8
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props
new file mode 100644
index 0000000..b068b85
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props
@@ -0,0 +1,7 @@
+
+
+
+ $(MSKit_Templates)LocalCompile/
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets
new file mode 100644
index 0000000..77eb087
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets
@@ -0,0 +1,40 @@
+
+
+
+ <_LocalCompileNamespace>$(RootNamespace)
+ <_LocalCompileNamespace Condition="'$(_LocalCompileNamespace)'==''">$(MSBuildProjectName)
+
+
+
+
+
+
+
+
+
+
+
+
+ %(Filename)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props
new file mode 100644
index 0000000..effb46d
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props
@@ -0,0 +1,9 @@
+
+
+
+ True
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets
new file mode 100644
index 0000000..d2456b2
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets
new file mode 100644
index 0000000..eb8172a
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props
new file mode 100644
index 0000000..8dec6d3
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props
@@ -0,0 +1,31 @@
+
+
+
+ $(MSKit_SlnFileName)
+
+ False
+
+
+
+
+ $(MSKit_LocalSecretsBaseDirectory)$(MSKit_SlnSecretsId)
+ $(LocalSlnSecretsDir)/Directory.Secrets.props
+
+ $(MSKit_Templates)
+ $(LocalSlnSecretsTemplateDir)/Directory.Secrets.props
+
+
+
+
+
+
+ False
+
+
+
+ $(LocalSlnSecretsDir)/Directory.Secrets.targets
+
+ $(LocalSlnSecretsTemplateDir)/Directory.Secrets.targets
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets
new file mode 100644
index 0000000..71e24f6
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+ Directory.Secrets.props
+ true
+
+
+ Directory.Secrets.targets
+ true
+
+
+
+
+ <Project>
+</Project>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props
new file mode 100644
index 0000000..b796e6c
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props
@@ -0,0 +1,7 @@
+
+
+
+ True
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets
new file mode 100644
index 0000000..ce7b418
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets
new file mode 100644
index 0000000..ed00d8e
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props
new file mode 100644
index 0000000..0de50b5
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props
@@ -0,0 +1,10 @@
+
+
+
+ $(LocalSecretsDir)/secrets.json
+
+ $(MSKit_Templates)
+ $(LocalSecretsTemplateDir)/$(UserSecretsId).secrets.json
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets
new file mode 100644
index 0000000..dcce4ad
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets
@@ -0,0 +1,61 @@
+
+
+
+ appsettings
+
+ false
+
+ {
+}
+
+
+
+
+
+
+ $(UserSecretsLinkNamePrefix).UserSecrets.json
+
+ Always
+
+ Always
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets
new file mode 100644
index 0000000..876d52b
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets
new file mode 100644
index 0000000..03588d0
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets
new file mode 100644
index 0000000..06657dc
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets
@@ -0,0 +1,128 @@
+
+
+
+
+
+ True
+ 30
+ ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$
+ 128
+
+ api.codacy.com;api.codeclimate.com;api.dependabot.com;api.reuse.software;api.travis-ci.com;app.codacy.com;app.deepsource.com;avatars.githubusercontent.com;badgen.net;badges.gitter.im;camo.githubusercontent.com;caniuse.bitsofco.de;cdn.jsdelivr.net;cdn.syncfusion.com;ci.appveyor.com;circleci.com;cloudback.it;codecov.io;codefactor.io;coveralls.io;dev.azure.com;devpod.sh;flat.badgen.net;gitlab.com;i.imgur.com;img.shields.io;infragistics.com;isitmaintained.com;media.githubusercontent.com;opencollective.com;raw.github.com;raw.githubusercontent.com;snyk.io;sonarcloud.io;travis-ci.com;travis-ci.org;user-images.githubusercontent.com
+ <_MSKit_PkgRules>https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices
+ <_MSKit_PkgReadmeRules>https://learn.microsoft.com/nuget/nuget-org/package-readme-on-nuget-org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_Description>$(PackageDescription)
+ <_MSKit_Description Condition="'$(_MSKit_Description)'==''">$(Description)
+ <_MSKit_Description>$(_MSKit_Description.Trim())
+ <_MSKit_DescriptionIsPlaceholder Condition="'$(_MSKit_Description)'=='' OR '$(_MSKit_Description)'=='Package Description' OR '$(_MSKit_Description)'=='$(PackageId)' OR '$(_MSKit_Description)'=='$(MSBuildProjectName)'">True
+ <_MSKit_PkgVersion>$(PackageVersion)
+ <_MSKit_PkgVersion Condition="'$(_MSKit_PkgVersion)'==''">$(Version)
+ <_MSKit_RepoUrlFinal>$(RepositoryUrl)
+ <_MSKit_RepoUrlFinal Condition="'$(_MSKit_RepoUrlFinal)'==''">$(PrivateRepositoryUrl)
+ <_MSKit_LicenseIsOpen Condition="'$(PackageLicenseExpression)'!=''">True
+
+
+
+ <_MSKit_PkgFinding Include="MSKIT_PKG001" Condition="'$(_MSKit_DescriptionIsPlaceholder)'=='True'"
+ Text="Package '$(PackageId)' has no real Description ('$(_MSKit_Description)'). nuget.org search shows it first: say what the package does and what sets it apart, in one or two sentences."
+ Rule="$(_MSKit_PkgRules)#description" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG002" Condition="'$(_MSKit_DescriptionIsPlaceholder)'!='True' AND $(_MSKit_Description.Length) < $(MSKit_PackageDescriptionMinLength)"
+ Text="Package '$(PackageId)' Description is $(_MSKit_Description.Length) characters ('$(_MSKit_Description)'); write at least $(MSKit_PackageDescriptionMinLength): what it does and for whom (MSKit_PackageDescriptionMinLength sets the bar)."
+ Rule="$(_MSKit_PkgRules)#description" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG003" Condition="'$(PackageReadmeFile)'==''"
+ Text="Package '$(PackageId)' ships no README. Add package.readme.md next to the csproj: what it is, how to start, a short example, where to give feedback."
+ Rule="$(_MSKit_PkgRules)#readme" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG004" Condition="'$(PackageTags)'==''"
+ Text="Package '$(PackageId)' has no PackageTags. Add a few search terms that are not already in the package id."
+ Rule="$(_MSKit_PkgRules)#tags" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG005" Condition="'$(PackageIcon)'==''"
+ Text="Package '$(PackageId)' has no icon. Set PackageIconPath to a 128x128 PNG (the company layer of the kit sets one for every package)."
+ Rule="$(_MSKit_PkgRules)#icon" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG006" Condition="'$(PackageLicenseExpression)'=='' AND '$(PackageLicenseFile)'==''"
+ Text="Package '$(PackageId)' has no licence. Without one nobody may use it. Set PackageLicenseExpression to an SPDX id (for example MIT)."
+ Rule="$(_MSKit_PkgRules)#licensing" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG007" Condition="'$(PackageLicenseUrl)'!=''"
+ Text="Package '$(PackageId)' uses the deprecated PackageLicenseUrl. Replace it with PackageLicenseExpression (an SPDX id) or PackageLicenseFile."
+ Rule="$(_MSKit_PkgRules)#licensing" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG008" Condition="'$(PackageIconUrl)'!=''"
+ Text="Package '$(PackageId)' uses the deprecated PackageIconUrl. Pack the image and point PackageIcon (or the kit's PackageIconPath) at it."
+ Rule="$(_MSKit_PkgRules)#icon" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG009" Condition="'$(_MSKit_RelativeImages)'!=''"
+ Text="The package README of '$(PackageId)' has relative images, which nuget.org does not render: $(_MSKit_RelativeImages). Use absolute https URLs from an allowed host."
+ Rule="$(_MSKit_PkgReadmeRules)#allowed-domains-for-images-and-badges" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG010" Condition="'$(_MSKit_HtmlTags)'!=''"
+ Text="The package README of '$(PackageId)' contains HTML, which nuget.org does not render: $(_MSKit_HtmlTags). Use Markdown instead."
+ Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG011" Condition="'$(_MSKit_Alerts)'!=''"
+ Text="The package README of '$(PackageId)' uses GitHub alert blocks, which nuget.org shows as plain quotes: $(_MSKit_Alerts). Use a bold lead-in such as **Note:** instead."
+ Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG012" Condition="'$(_MSKit_DisallowedImages)'!=''"
+ Text="The package README of '$(PackageId)' loads images from hosts nuget.org blocks: $(_MSKit_DisallowedImages). Host them on an allowed domain (img.shields.io, raw.githubusercontent.com, ...)."
+ Rule="$(_MSKit_PkgReadmeRules)#allowed-domains-for-images-and-badges" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG013" Condition="'$(_MSKit_PkgVersion)'!='' AND !$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_PkgVersion)', '$(MSKit_SemVerRegex)'))"
+ Text="Package '$(PackageId)' version '$(_MSKit_PkgVersion)' is not SemVer 2.0 (MAJOR.MINOR.PATCH[-prerelease][+metadata])."
+ Rule="$(_MSKit_PkgRules)#package-version" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG014" Condition="'$(_MSKit_RepoUrlFinal)'=='' OR '$(PackageProjectUrl)'==''"
+ Text="Package '$(PackageId)' has no repository or project URL. Set RepositoryUrl, or build from a git clone whose origin remote Source Link can read."
+ Rule="$(_MSKit_PkgRules)#repository-type-and-url" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG015" Condition="'$(MSKit_PackageIconSourcePath)'!='' AND Exists('$(MSKit_PackageIconSourcePath)') AND ('$(_MSKit_IconIsPng)'!='True' OR '$(_MSKit_IconWidth)'!='$(MSKit_PackageIconSize)' OR '$(_MSKit_IconHeight)'!='$(MSKit_PackageIconSize)')"
+ Text="Package '$(PackageId)' icon is not a $(MSKit_PackageIconSize)x$(MSKit_PackageIconSize) PNG (PNG: $(_MSKit_IconIsPng), size: $(_MSKit_IconWidth)x$(_MSKit_IconHeight))."
+ Rule="$(_MSKit_PkgRules)#icon" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG016" Condition="'$(PackageReleaseNotes)'==''"
+ Text="Package '$(PackageId)' has no PackageReleaseNotes. Set them, or a link to the changelog (on GitHub the kit links the releases page by default)."
+ Rule="$(_MSKit_PkgRules)#release-notes" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG017" Condition="'$(_MSKit_RelativeLinks)'!=''"
+ Text="The package README of '$(PackageId)' has relative links, which break on nuget.org: $(_MSKit_RelativeLinks). Use absolute URLs."
+ Rule="$(_MSKit_PkgReadmeRules)" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG018" Condition="'$(_MSKit_LicenseIsOpen)'=='True' AND $(Copyright.ToLowerInvariant().Contains('all rights reserved'))"
+ Text="Package '$(PackageId)' is licensed '$(PackageLicenseExpression)' but its Copyright says 'all rights reserved' ('$(Copyright)'). Use 'Copyright (c) YEAR OWNER'."
+ Rule="$(_MSKit_PkgRules)#copyright" />
+ <_MSKit_PkgFinding Include="MSKIT_PKG019" Condition="'$(_MSKit_HasMermaid)'=='True'"
+ Text="The package README of '$(PackageId)' contains a Mermaid diagram, which nuget.org shows as code. Link to the diagram on GitHub instead."
+ Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" />
+
+
+
+ <_MSKit_PkgSkip Include="$(MSKit_SkipPackageChecks)" />
+ <_MSKit_PkgSkip Include="$(NoWarn)" />
+ <_MSKit_PkgFinding Remove="@(_MSKit_PkgSkip)" />
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
new file mode 100644
index 0000000..e739d5c
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
@@ -0,0 +1,18 @@
+
+
+
+
+
+ true
+ true
+ true
+
+ true
+
+ true
+ all
+ low
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets
new file mode 100644
index 0000000..1d52011
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets
new file mode 100644
index 0000000..4133174
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ();
+var disallowedImages = new List();
+var relativeLinks = new List();
+var htmlTags = new List();
+var alerts = new List();
+
+if (!string.IsNullOrEmpty(ReadmePath) && File.Exists(ReadmePath))
+{
+ var text = File.ReadAllText(ReadmePath);
+ HasMermaid = Regex.IsMatch(text, @"^\s*(```|~~~)\s*mermaid\b", RegexOptions.Multiline | RegexOptions.IgnoreCase);
+
+ var prose = Regex.Replace(text, @"^\s*(```|~~~)[\s\S]*?^\s*\1\s*$", "", RegexOptions.Multiline);
+ prose = Regex.Replace(prose, @"`[^`\r\n]*`", "");
+
+ var hosts = (AllowedImageHosts ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(h => h.Trim().ToLowerInvariant()).Where(h => h.Length > 0).ToList();
+
+ var images = new List();
+ foreach (Match m in Regex.Matches(prose, @"!\[[^\]]*\]\(\s*([^)\s>]+)"))
+ images.Add(m.Groups[1].Value);
+ foreach (Match m in Regex.Matches(prose, @"
]*\bsrc\s*=\s*[""']([^""']+)[""']", RegexOptions.IgnoreCase))
+ images.Add(m.Groups[1].Value);
+
+ foreach (var url in images.Distinct())
+ {
+ Uri uri;
+ if (!Uri.TryCreate(url, UriKind.Absolute, out uri) || (uri.Scheme != "https" && uri.Scheme != "http"))
+ {
+ relativeImages.Add(url);
+ continue;
+ }
+ var host = uri.Host.ToLowerInvariant();
+ var allowed = hosts.Contains(host)
+ || (host == "github.com" && Regex.IsMatch(uri.AbsolutePath, @"^/[^/]+/[^/]+/(actions/)?workflows/[^/]+/badge\.svg$", RegexOptions.IgnoreCase));
+ if (!allowed)
+ disallowedImages.Add(url);
+ }
+
+ foreach (Match m in Regex.Matches(prose, @"(?]+)"))
+ {
+ var target = m.Groups[1].Value;
+ if (target.StartsWith("#") || Regex.IsMatch(target, @"^[A-Za-z][A-Za-z0-9+.-]*:"))
+ continue;
+ relativeLinks.Add(target);
+ }
+
+ foreach (Match m in Regex.Matches(prose, @"?([A-Za-z][A-Za-z0-9-]*)(\s[^<>]*)?/?>"))
+ {
+ if (m.Value.Contains("://") || m.Value.Contains("@"))
+ continue;
+ htmlTags.Add("<" + m.Groups[1].Value.ToLowerInvariant() + ">");
+ }
+
+ foreach (Match m in Regex.Matches(prose, @"^\s*>\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]", RegexOptions.Multiline | RegexOptions.IgnoreCase))
+ alerts.Add("[!" + m.Groups[1].Value.ToUpperInvariant() + "]");
+}
+
+if (!string.IsNullOrEmpty(IconPath) && File.Exists(IconPath))
+{
+ var header = new byte[24];
+ using (var stream = File.OpenRead(IconPath))
+ {
+ var read = stream.Read(header, 0, header.Length);
+ IconIsPng = read == 24 && header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47;
+ }
+ if (IconIsPng)
+ {
+ IconWidth = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19];
+ IconHeight = (header[20] << 24) | (header[21] << 16) | (header[22] << 8) | header[23];
+ }
+}
+
+RelativeImages = string.Join(", ", relativeImages.Distinct());
+DisallowedImages = string.Join(", ", disallowedImages.Distinct());
+RelativeLinks = string.Join(", ", relativeLinks.Distinct());
+HtmlTags = string.Join(", ", htmlTags.Distinct());
+Alerts = string.Join(", ", alerts.Distinct());
+]]>
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
new file mode 100644
index 0000000..89204e3
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
@@ -0,0 +1,81 @@
+
+
+
+
+
+ $(MSBuildProjectName)
+ True
+ false
+ git
+ $(RepositoryUrl)
+
+
+ true
+ false
+ snupkg
+
+
+ true
+ $(MSKit_PackageValidationBaselineVersion)
+
+
+
+
+ $(MSBuildProjectDirectory)/package.readme.md
+ $(MSBuildProjectDirectory)/README.md
+ readme.md
+ <_MSKit_PacksReadme Condition="'$(PackageReadmeFile)'!=''">True
+
+
+ $(MSBuildProjectDirectory)/$(PackageReadmeFile)
+
+
+
+
+ icon.png
+ <_MSKit_PacksIcon>True
+
+
+ $(PackageIconPath)
+ $(MSBuildProjectDirectory)/$(PackageIcon)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_ResolvePackageUrlsDependsOn Condition="'$(SourceControlInformationFeatureSupported)'=='true'">InitializeSourceControlInformation
+
+
+
+ <_MSKit_RepoUrl>$(RepositoryUrl)
+ <_MSKit_RepoUrl Condition="'$(_MSKit_RepoUrl)'==''">$(PrivateRepositoryUrl)
+ <_MSKit_RepoUrl Condition="$(_MSKit_RepoUrl.EndsWith('.git'))">$(_MSKit_RepoUrl.Substring(0, $([MSBuild]::Subtract($(_MSKit_RepoUrl.Length), 4))))
+ $(_MSKit_RepoUrl)
+
+ <_MSKit_IsGitHubUrl Condition="$(PackageProjectUrl.StartsWith('https://github.com/'))">True
+ $(PackageProjectUrl)/releases/tag/$(MSKit_ReleaseTagRaw)
+ $(PackageProjectUrl)/releases
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets
new file mode 100644
index 0000000..2d938a6
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets
new file mode 100644
index 0000000..9226ef2
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets
new file mode 100644
index 0000000..febe8d5
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets
new file mode 100644
index 0000000..29bd17d
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets
@@ -0,0 +1,26 @@
+
+
+
+ 4.0.1
+ $(MSKit_PackageVersion_XunitV3)
+ $(MSKit_PackageVersion_XunitV3)
+ 4.0.0
+
+
+
+
+
+
+
+
+
+
+
+ $(MSKit_PackageVersion_XunitV3)
+ $(MSKit_PackageVersion_XunitV3)
+ $(MSKit_PackageVersion_XunitV3Assert)
+ $(MSKit_PackageVersion_XunitV3ExtensibilityCore)
+ $(MSKit_PackageVersion_XunitRunnerVisualStudio)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets
new file mode 100644
index 0000000..ea85fe1
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props
new file mode 100644
index 0000000..86ddd60
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props
@@ -0,0 +1,12 @@
+
+
+
+ true
+ <_MSKit_TestingFramework_xunit_v3_CommonPropsPath>$(MSBuildThisFileDirectory)tests.project.xunit.v3.common.props
+ <_MSKit_TestingFramework_xunit_v3_LibCommonPropsPath>$(MSBuildThisFileDirectory)tests.lib.project.xunit.v3.common.props
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets
new file mode 100644
index 0000000..d12608e
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props
new file mode 100644
index 0000000..962eec1
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props
new file mode 100644
index 0000000..7fa68e2
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props
@@ -0,0 +1,8 @@
+
+
+
+
+ true
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props
new file mode 100644
index 0000000..08b3e1f
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props
@@ -0,0 +1,8 @@
+
+
+
+
+ true
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets
new file mode 100644
index 0000000..095e1fc
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Exe
+ xunit.runner.json
+
+
+
+
+
+
+
+
+
+
+{
+ "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json"
+}
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets
new file mode 100644
index 0000000..8de8fe0
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets
new file mode 100644
index 0000000..11cb07e
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets
new file mode 100644
index 0000000..8075de2
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_CsprojText013>$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)'))
+ <_MSKit_CsprojText013>$([System.Text.RegularExpressions.Regex]::Replace($(_MSKit_CsprojText013), '<!--[\s\S]*?-->', ''))
+ <_MSKit_HasDirectIsTestsProject>$([System.Text.RegularExpressions.Regex]::IsMatch($(_MSKit_CsprojText013), '<IsTestsProject\s*>'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets
new file mode 100644
index 0000000..68fa036
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets
@@ -0,0 +1,42 @@
+
+
+
+
+ [7.2.2]
+ 4.3.0
+ 9.6.0
+ 6.2.0
+ 1.0.17
+ 18.10.1
+ 2.4.1
+ 18.11.2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSKit_PackageVersion_FluentAssertions)
+ $(MSKit_PackageVersion_Shouldly)
+ $(MSKit_PackageVersion_AwesomeAssertions)
+ $(MSKit_PackageVersion_NSubstitute)
+ $(MSKit_PackageVersion_NSubstituteAnalyzersCSharp)
+ $(MSKit_PackageVersion_MicrosoftNetTestSdk)
+ $(MSKit_PackageVersion_MicrosoftTestingExtensionsTrxReport)
+ $(MSKit_PackageVersion_MicrosoftTestingExtensionsCodeCoverage)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets
new file mode 100644
index 0000000..ea85fe1
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props
new file mode 100644
index 0000000..73ea576
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props
@@ -0,0 +1,15 @@
+
+
+
+
+ $(MSBuildThisFileDirectory)tests.project.common.props
+ $(MSBuildThisFileDirectory)tests.lib.project.common.props
+ AwesomeAssertions
+ NSubstitute
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets
new file mode 100644
index 0000000..958c8f9
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets
new file mode 100644
index 0000000..d651dd7
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets
@@ -0,0 +1,31 @@
+
+
+
+
+ $(MSKit_SlnFileDirectory)
+ $(MSKit_GitRoot)/
+
+
+ $(MSKit_TestsDir)/
+
+
+
+ <_AllCsprojsUnderTestsDir Include="$(MSKit_TestsDir)**/*.csproj" Exclude="$(MSKit_TestsDir)**/bin/**;$(MSKit_TestsDir)**/obj/**;$(MSKit_TestsDir)**/node_modules/**" />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props
new file mode 100644
index 0000000..9685d6b
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props
@@ -0,0 +1,21 @@
+
+
+
+
+ <_MSKit_TestingFrameworkAtLibCommonPropsImport>$(MSKit_TestingFramework)
+ <_MSKit_TestsLibProjectCommonPropsImported>True
+ True
+
+
+
+
+
+ $(_MSKit_TestingFramework_xunit_v3_LibCommonPropsPath)
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props
new file mode 100644
index 0000000..72b358c
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props
@@ -0,0 +1,22 @@
+
+
+
+
+ <_MSKit_TestingFrameworkAtCommonPropsImport>$(MSKit_TestingFramework)
+ <_MSKit_TestsProjectCommonPropsImported>True
+ True
+ True
+
+
+
+
+
+ $(_MSKit_TestingFramework_xunit_v3_CommonPropsPath)
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets
new file mode 100644
index 0000000..3c3053d
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets
new file mode 100644
index 0000000..253fb90
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets
@@ -0,0 +1,25 @@
+
+
+
+ testconfig.json
+
+
+
+
+
+
+
+
+
+
+{
+ "diagnosticMessages": false
+}
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props
new file mode 100644
index 0000000..fce3b86
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props
@@ -0,0 +1,44 @@
+
+
+
+
+
+ \.(Tests(\.Integration|\.Unit)?|IntegrationTests|UnitTests)$
+ $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_TestsProjectNameRegex)))
+ True
+
+
+ \.(TestsSuite|TestsFixtures|Fixtures)$
+ $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_TestsLibProjectNameRegex)))
+ True
+
+ <_MSKit_TestsProjectNameRegex_Shared>$(MSKit_TestsProjectNameRegex)
+ <_MSKit_TestsLibProjectNameRegex_Shared>$(MSKit_TestsLibProjectNameRegex)
+
+
+
+
+
+
+
+
+
+ Exe
+ True
+
+ --ignore-exit-code 8
+
+
+
+ <_MSKit_TestsProjectPropsImported>True
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets
new file mode 100644
index 0000000..1bd4bba
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets
@@ -0,0 +1,35 @@
+
+
+
+
+ False
+ Library
+
+
+
+ False
+ False
+
+
+
+ True
+
+ True
+
+
+
+ True
+
+
+
+ True
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props
new file mode 100644
index 0000000..0f2d9a1
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props
new file mode 100644
index 0000000..fca8585
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props
@@ -0,0 +1,44 @@
+
+
+
+ true
+
+ True
+
+ True
+ True
+ True
+
+ True
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+
+
+
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props
new file mode 100644
index 0000000..30decc3
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props
@@ -0,0 +1,27 @@
+
+
+
+
+ True
+ False
+
+ $(GITHUB_RUN_ID)
+
+ $(GITHUB_RUN_NUMBER)
+ $(GITHUB_SHA)
+
+ True
+ $(GITHUB_REF_NAME)
+ $([System.Text.RegularExpressions.Regex]::Replace('$(MSKit_ReleaseTagRaw)', '^[vV]', ''))
+
+ $([System.Text.RegularExpressions.Regex]::Match('$(GITHUB_REF)', 'refs/pull/(\d+)/').Groups[1].Value)
+ $([System.Text.RegularExpressions.Regex]::Match('$(GITHUB_REF_NAME)', '^\d+').Value)
+
+ $(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)
+ https://github.com/$(GITHUB_REPOSITORY)
+
+ GitHub
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props
new file mode 100644
index 0000000..48bdbb4
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets
new file mode 100644
index 0000000..b03a750
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets
@@ -0,0 +1,34 @@
+
+
+
+
+
+ False
+
+
+
+
+ <_MSKit_ConsumerIdentities Include="%(PackageVersion.Identity)"
+ Condition="'%(PackageVersion.ControlledBy)'==''" />
+
+
+ <_MSKit_ConsumerIdsStr>;@(_MSKit_ConsumerIdentities, ';');
+
+
+ <_MSKit_DuplicateReport Include="@(PackageVersion)"
+ Condition="'%(PackageVersion.ControlledBy)'!=''
+ AND $(_MSKit_ConsumerIdsStr.Contains(';%(PackageVersion.Identity);'))" />
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets
new file mode 100644
index 0000000..534e94f
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets
@@ -0,0 +1,29 @@
+
+
+
+
+
+ true
+
+
+
+
+ <_MSKit_PackagesWithVersion Include="@(PackageReference)" Condition="'%(PackageReference.Version)' != ''" />
+ <_MSKit_PackagesWithVersion Include="@(PackageVersion)" Condition="'%(PackageVersion.Version)' != ''" />
+ <_MSKit_PrereleaseReferences Include="@(_MSKit_PackagesWithVersion)"
+ Condition="$([System.String]::Copy('%(_MSKit_PackagesWithVersion.Identity)').StartsWith('$(MSKit_PrereleasePackagePrefix)')) AND $([System.String]::Copy('%(_MSKit_PackagesWithVersion.Version)').Contains('-'))" />
+
+
+ <_MSKit_PrereleaseText>Prerelease $(MSKit_PrereleasePackagePrefix)* packages referenced on stable branch '$(MSKit_Branch)':%0A@(_MSKit_PrereleaseReferences->' %(Identity) %(Version)', '%0A')%0AFix: replace them with stable versions in Directory.Packages.props or the csproj.
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets
new file mode 100644
index 0000000..4fba85c
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets
new file mode 100644
index 0000000..6e84fa3
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets
@@ -0,0 +1,35 @@
+
+
+
+
+
+ False
+ $(MSKit_RestrictReferences)
+ $(MSKit_RestrictReferences)
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_PackageReferenceNotAllowListed Include="@(PackageReference)"
+ Condition=" '%(PackageReference.Allowed)'!='True' AND '@(PackageReference)'!='' AND '%(Identity)'!=''" />
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets
new file mode 100644
index 0000000..eeda662
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+ <_MSKit_GuardXmlPeek Condition="'$(MSKit_GuardXmlPeekAudit)'!='False'">True
+ <_MSKit_SPC_CsprojText Condition="'$(_MSKit_GuardXmlPeek)'=='True'">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)'))
+ <_MSKit_HasTargetFramework Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True
+ <_MSKit_HasTargetFramework Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_SPC_CsprojText.Contains('<TargetFramework>')) OR $(_MSKit_SPC_CsprojText.Contains('<TargetFramework ')))">True
+ <_MSKit_HasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True
+ <_MSKit_HasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_SPC_CsprojText.Contains('<TargetFrameworks>')) OR $(_MSKit_SPC_CsprojText.Contains('<TargetFrameworks ')))">True
+
+
+
+
+
+
+
+
+
+ <_MSKit_TF_ProjNodeCount>@(_MSKit_TF_NodeCheckXmlResult->Count())
+ <_MSKit_TFs_ProjNodeCount>@(_MSKit_TFs_NodeCheckXmlResult->Count())
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets
new file mode 100644
index 0000000..aaea8ee
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+ <_MSKit_GuardXmlPeek Condition="'$(MSKit_GuardXmlPeekAudit)'!='False'">True
+ <_MSKit_RMV_CsprojText Condition="'$(_MSKit_GuardXmlPeek)'=='True'">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)'))
+ <_MSKit_HasVersion Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True
+ <_MSKit_HasVersion Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_RMV_CsprojText.Contains('<Version>')) OR $(_MSKit_RMV_CsprojText.Contains('<Version ')))">True
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_ValidPlaceholders>prefix;buildNumber;pipelineId;branchSlug;branchTicket;branchAspectSuffix;buildDateUtcDash;buildDateUtcDot;versionTag;releaseTag;prNumber;commitShaShort
+ <_MSKit_PlaceholderHelp>
+Valid placeholders:
+ {prefix} - $(VersionPrefix), declared in Directory.Version.props
+ {buildNumber} - CI run number (GITHUB_RUN_NUMBER); DateBased caps it at 65535
+ {pipelineId} - CI run id (GITHUB_RUN_ID)
+ {releaseTag} - the release tag with a leading v removed (tag builds only)
+ {prNumber} - the pull request number (pull request builds only)
+ {branchSlug} - the branch name with every character outside [0-9A-Za-z-] replaced by '-'
+ {branchTicket} - the first [A-Za-z]+-[0-9]+ match in {branchSlug}, else {branchSlug}
+ {branchAspectSuffix} - the part of {branchSlug} from its first '--' to the end, else empty
+ {buildDateUtcDash} - UTC build time as yyyyMMdd-HHmmss
+ {buildDateUtcDot} - UTC build time as yyyy.M.d
+ {versionTag} - $(VersionTag)
+ {commitShaShort} - the first 8 characters of the commit SHA
+
+ <_MSKit_AllTemplates>$(MSKit_VersionTemplate)|$(MSKit_StableVersionTemplate)|$(MSKit_ReleaseVersionTemplate)|$(MSKit_PullRequestVersionTemplate)
+ <_MSKit_TplHasTokens>false
+ <_MSKit_TplHasTokens Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_AllTemplates)', '\{[A-Za-z][A-Za-z0-9]*\}'))">true
+ <_MSKit_TplNames Condition="'$(_MSKit_TplHasTokens)'=='true'">$([System.Text.RegularExpressions.Regex]::Replace('$(_MSKit_AllTemplates)', '[^{}]*\{([A-Za-z][A-Za-z0-9]*)\}[^{}]*', '$1;').TrimEnd(';'))
+
+
+
+ <_MSKit_ValidPlaceholder Include="$(_MSKit_ValidPlaceholders.Split(';'))" />
+ <_MSKit_TplNameItem Include="$(_MSKit_TplNames.Split(';'))" Condition="'$(_MSKit_TplNames)'!=''" />
+ <_MSKit_UnknownPlaceholder Include="@(_MSKit_TplNameItem)" Exclude="@(_MSKit_ValidPlaceholder)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_ReleaseTagCore>$([System.Text.RegularExpressions.Regex]::Match('$(MSKit_ReleaseTag)', '^\d+\.\d+\.\d+').Value)
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props
new file mode 100644
index 0000000..5787c55
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets
new file mode 100644
index 0000000..d4f4b5e
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props
new file mode 100644
index 0000000..ef44584
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props
@@ -0,0 +1,17 @@
+
+
+
+ enable
+ enable
+ latest
+ True
+ False
+ True
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets
new file mode 100644
index 0000000..8f6c1b4
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props
new file mode 100644
index 0000000..85cd674
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props
@@ -0,0 +1,13 @@
+
+
+
+ $(MSBuildProjectName)
+ $([System.DateTime]::UtcNow.Year)
+ $(ManufacturerName)
+ $(FullManufacturerName)
+
+ Copyright (c) $(Year) $(FullManufacturerName)
+ $(ManufacturerName)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets
new file mode 100644
index 0000000..9b34627
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets
@@ -0,0 +1,31 @@
+
+
+
+
+
+ all
+ all
+
+
+ all
+ all
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets
new file mode 100644
index 0000000..8e42751
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props
new file mode 100644
index 0000000..ffddb18
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props
@@ -0,0 +1,8 @@
+
+
+
+
+ $(TreatWarningsAsErrors)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props
new file mode 100644
index 0000000..6e356cf
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props
@@ -0,0 +1,145 @@
+
+
+
+
+
+ $(VersionPrefix)
+
+ SemVer
+ DevEnv
+
+ 0
+ 0
+
+ ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$
+ false
+ true
+
+
+
+
+ $([System.Environment]::GetEnvironmentVariable('MSKit_BuildDateTimeUtc'))
+
+
+ <_MSKit_Ph_buildDateUtcDash>$([System.DateTime]::Parse('$(MSKit_BuildDateTimeUtc)').ToUniversalTime().ToString(yyyyMMdd-HHmmss))
+ <_MSKit_Ph_buildDateUtcDot>$([System.DateTime]::Parse('$(MSKit_BuildDateTimeUtc)').ToUniversalTime().ToString(yyyy.M.d))
+
+
+ <_MSKit_Ph_buildDateUtcDash>$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmmss))
+ <_MSKit_Ph_buildDateUtcDot>$([System.DateTime]::UtcNow.ToString(yyyy.M.d))
+
+
+
+
+
+ 0.0.0
+ {releaseTag}
+ {prefix}-pr.{prNumber}.{buildNumber}
+ {prefix}-ci.{buildNumber}
+ {prefix}-ci.{buildNumber}
+
+
+
+
+ 1.0.0
+ {prefix}-{buildDateUtcDash}-{branchTicket}{branchAspectSuffix}
+ {prefix}
+
+
+
+
+ 1.0.0
+ {prefix}.{buildNumber}-{buildDateUtcDash}-{branchTicket}{branchAspectSuffix}
+ {prefix}.{buildNumber}
+
+
+
+
+ $(_MSKit_Ph_buildDateUtcDot)
+ $([MSBuild]::Modulo($(MSKit_CIPipelineId), 65535))
+ 1
+ {buildDateUtcDot}.{buildNumber}-{branchTicket}{branchAspectSuffix}
+ {buildDateUtcDot}.{buildNumber}
+
+
+
+
+ {versionTag}
+ {versionTag}
+
+
+
+
+ 9999.0.0
+
+
+ 9999.0.0
+ 9999.0.0
+
+
+
+
+
+
+
+
+
+
+
+ <_MSKit_Ph_prefix>$(VersionPrefix)
+ <_MSKit_Ph_versionTag>$(VersionTag)
+ <_MSKit_Ph_releaseTag Condition="'$(MSKit_IsReleaseTagValid)'=='true'">$(MSKit_ReleaseTag)
+
+ <_MSKit_Ph_releaseTag Condition="'$(MSKit_IsReleaseTagValid)'!='true'">0.0.0-invalid-release-tag
+ <_MSKit_Ph_prNumber>$(MSKit_PullRequestNumber)
+ <_MSKit_Ph_buildNumber>$(MSKit_BuildNumber)
+ <_MSKit_Ph_pipelineId>$(MSKit_CIPipelineId)
+ <_MSKit_Ph_branchSlug>$([System.Text.RegularExpressions.Regex]::Replace('$(MSKit_Branch)', '[^0-9A-Za-z-]', '-'))
+
+ <_MSKit_BranchTicketMatch>$([System.Text.RegularExpressions.Regex]::Match($(_MSKit_Ph_branchSlug), '[A-Za-z]+-\d+').Value)
+ <_MSKit_Ph_branchTicket Condition="'$(_MSKit_BranchTicketMatch)'!=''">$(_MSKit_BranchTicketMatch)
+ <_MSKit_Ph_branchTicket Condition="'$(_MSKit_BranchTicketMatch)'==''">$(_MSKit_Ph_branchSlug)
+
+ <_MSKit_BranchAspectIdx>$(_MSKit_Ph_branchSlug.IndexOf('--'))
+ <_MSKit_Ph_branchAspectSuffix Condition="'$(_MSKit_BranchAspectIdx)'!='-1'">$(_MSKit_Ph_branchSlug.Substring($(_MSKit_BranchAspectIdx)))
+
+ <_MSKit_Ph_commitShaShort Condition="$(MSKit_CommitSha.Length) >= 8">$(MSKit_CommitSha.Substring(0, 8))
+
+
+
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'=='true'">$(MSKit_StableVersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'!='true'">$(MSKit_VersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_PullRequestNumber)'!='' AND '$(MSKit_PullRequestVersionTemplate)'!=''">$(MSKit_PullRequestVersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsReleaseTag)'=='True' AND '$(MSKit_ReleaseVersionTemplate)'!=''">$(MSKit_ReleaseVersionTemplate)
+
+ <_MSKit_Rendered>$(_MSKit_EffectiveTemplate)
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prefix}', '$(_MSKit_Ph_prefix)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildNumber}', '$(_MSKit_Ph_buildNumber)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{pipelineId}', '$(_MSKit_Ph_pipelineId)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchSlug}', '$(_MSKit_Ph_branchSlug)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchTicket}', '$(_MSKit_Ph_branchTicket)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchAspectSuffix}', '$(_MSKit_Ph_branchAspectSuffix)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDash}', '$(_MSKit_Ph_buildDateUtcDash)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDot}', '$(_MSKit_Ph_buildDateUtcDot)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{versionTag}', '$(_MSKit_Ph_versionTag)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{releaseTag}', '$(_MSKit_Ph_releaseTag)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prNumber}', '$(_MSKit_Ph_prNumber)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{commitShaShort}', '$(_MSKit_Ph_commitShaShort)'))
+
+ <_MSKit_RenderHasUnknown>false
+ <_MSKit_RenderHasUnknown Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_Rendered)', '\{[A-Za-z][A-Za-z0-9]*\}'))">true
+
+ $(_MSKit_Rendered)
+
+ unknown placeholder: $(_MSKit_Rendered)
+
+
+
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets
new file mode 100644
index 0000000..8b72fe8
--- /dev/null
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ <_MSKit_Ph_prefix>$(VersionPrefix)
+
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'=='true'">$(MSKit_StableVersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'!='true'">$(MSKit_VersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_PullRequestNumber)'!='' AND '$(MSKit_PullRequestVersionTemplate)'!=''">$(MSKit_PullRequestVersionTemplate)
+ <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsReleaseTag)'=='True' AND '$(MSKit_ReleaseVersionTemplate)'!=''">$(MSKit_ReleaseVersionTemplate)
+
+ <_MSKit_Rendered>$(_MSKit_EffectiveTemplate)
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prefix}', '$(_MSKit_Ph_prefix)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildNumber}', '$(_MSKit_Ph_buildNumber)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{pipelineId}', '$(_MSKit_Ph_pipelineId)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchSlug}', '$(_MSKit_Ph_branchSlug)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchTicket}', '$(_MSKit_Ph_branchTicket)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchAspectSuffix}', '$(_MSKit_Ph_branchAspectSuffix)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDash}', '$(_MSKit_Ph_buildDateUtcDash)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDot}', '$(_MSKit_Ph_buildDateUtcDot)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{versionTag}', '$(_MSKit_Ph_versionTag)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{releaseTag}', '$(_MSKit_Ph_releaseTag)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prNumber}', '$(_MSKit_Ph_prNumber)'))
+ <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{commitShaShort}', '$(_MSKit_Ph_commitShaShort)'))
+
+ $(_MSKit_Rendered)
+ $(_MSKit_Rendered)
+
+
+
+
+
diff --git a/.toolkit/msbuild/init.company.props b/.toolkit/msbuild/init.company.props
new file mode 100644
index 0000000..587098c
--- /dev/null
+++ b/.toolkit/msbuild/init.company.props
@@ -0,0 +1,35 @@
+
+
+
+
+ DragoAnt
+ DragoAnt
+
+ MIT
+ $(MSBuildThisFileDirectory)../res/package.icon.png
+ DragoAnt.
+
+ ^(main|release/.+)$
+ ReleaseTag
+
+
+ True
+
+ True
+
+ CS1591;xUnit1051;$(NoWarn)
+
+ $(WarningsNotAsErrors);NU1901;NU1902;NU1903;NU1904
+
+ xunit.v3
+ AwesomeAssertions
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/init.company.targets b/.toolkit/msbuild/init.company.targets
new file mode 100644
index 0000000..45bff74
--- /dev/null
+++ b/.toolkit/msbuild/init.company.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.toolkit/msbuild/init.props b/.toolkit/msbuild/init.props
new file mode 100644
index 0000000..580345c
--- /dev/null
+++ b/.toolkit/msbuild/init.props
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/msbuild/init.targets b/.toolkit/msbuild/init.targets
new file mode 100644
index 0000000..0385214
--- /dev/null
+++ b/.toolkit/msbuild/init.targets
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.toolkit/res/package.icon.png b/.toolkit/res/package.icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..e890a2973d5ebd15b6604fcb3f48cba42a2d0c15
GIT binary patch
literal 10282
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
literal 0
HcmV?d00001
diff --git a/.toolkit/update.ps1 b/.toolkit/update.ps1
new file mode 100644
index 0000000..d5fdfea
--- /dev/null
+++ b/.toolkit/update.ps1
@@ -0,0 +1,214 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+Installs or updates DragoAnt.MSBuildKit in a repository's .toolkit/ folder.
+
+.DESCRIPTION
+Downloads a release zip of the kit from GitHub, checks its SHA-256 against the published
+checksum (and against .toolkit/kit.json when the version is unchanged), and rewrites
+.toolkit/msbuild/ with the default parts plus the optional parts you selected.
+
+.EXAMPLE
+pwsh .toolkit/update.ps1 # update to the version in kit.json, else the latest
+pwsh .toolkit/update.ps1 -Version 0.2.0 -DryRun # show what 0.2.0 would change
+pwsh .toolkit/update.ps1 -Add PackageAsProj # install an optional part
+#>
+[CmdletBinding()]
+param(
+ # Kit version to install; default: the version in .toolkit/kit.json, else the latest release.
+ [string] $Version,
+ # Optional parts to install, e.g. PackageAsProj, EF, Project.SourceGenerator.
+ [string[]] $Add = @(),
+ # Optional parts to uninstall.
+ [string[]] $Remove = @(),
+ # Show what would change and change nothing.
+ [switch] $DryRun,
+ # Install from a local kit build (a folder containing .toolkit/ or a release zip).
+ [string] $Source,
+ # Expected SHA-256 of the release zip (or of a -Source zip).
+ [string] $Sha256,
+ # GitHub repository to download releases from.
+ [string] $Repo = 'DragoAnt/MSBuildKit',
+ # Repository root; default: the current folder.
+ [string] $Root
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+
+function Say([string] $text) { Write-Host "update: $text" }
+function Fail([string] $text) { throw "update: error: $text" }
+
+if (-not $Root) { $Root = (Get-Location).Path }
+$Root = (Resolve-Path $Root).Path
+$toolkit = Join-Path $Root '.toolkit'
+$kitJsonPath = Join-Path $toolkit 'kit.json'
+$kitJson = if (Test-Path $kitJsonPath) { Get-Content -Raw $kitJsonPath | ConvertFrom-Json } else { $null }
+function KitJsonValue([string] $name) {
+ if ($null -ne $kitJson -and $kitJson.PSObject.Properties.Name -contains $name) { return $kitJson.$name }
+ return $null
+}
+
+if ($Version) { $Version = $Version -replace '^[vV]', '' }
+if ($Sha256) { $Sha256 = $Sha256.ToLowerInvariant() }
+$recordedRepo = KitJsonValue 'repository'
+if ($recordedRepo -and $Repo -eq 'DragoAnt/MSBuildKit') { $Repo = $recordedRepo }
+
+$work = Join-Path ([System.IO.Path]::GetTempPath()) ("msbuildkit-" + [guid]::NewGuid().ToString('N'))
+New-Item -ItemType Directory -Path $work | Out-Null
+try {
+ $actualSha = ''
+ $kitDir = $null
+ if ($Source) {
+ if (Test-Path $Source -PathType Container) {
+ if (-not (Test-Path (Join-Path $Source '.toolkit/msbuild/init.props'))) { Fail "'$Source' is not a kit build: no .toolkit/msbuild/init.props" }
+ $kitDir = (Resolve-Path $Source).Path
+ }
+ elseif (Test-Path $Source -PathType Leaf) {
+ $actualSha = (Get-FileHash -Algorithm SHA256 $Source).Hash.ToLowerInvariant()
+ if ($Sha256 -and $actualSha -ne $Sha256) { Fail "SHA-256 mismatch for '$Source': expected $Sha256, got $actualSha" }
+ $kitDir = Join-Path $work 'kit'
+ Expand-Archive -Path $Source -DestinationPath $kitDir
+ }
+ else { Fail "-Source '$Source' does not exist" }
+ if (-not $Version) {
+ $versionFile = Join-Path $kitDir '.toolkit/kit.version'
+ $Version = if (Test-Path $versionFile) { (Get-Content $versionFile -TotalCount 1).Trim() } else { '0.0.0-local' }
+ }
+ }
+ else {
+ if (-not $Version) { $Version = KitJsonValue 'version' }
+ if (-not $Version) {
+ $latest = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -Headers @{ 'User-Agent' = 'msbuildkit-update' }
+ $Version = ($latest.tag_name -replace '^[vV]', '')
+ if (-not $Version) { Fail "no release found in $Repo" }
+ }
+ $zipName = "msbuildkit-$Version.zip"
+ $base = "https://github.com/$Repo/releases/download/v$Version"
+ $zipPath = Join-Path $work $zipName
+ Say "downloading $base/$zipName"
+ Invoke-WebRequest -Uri "$base/$zipName" -OutFile $zipPath
+ Invoke-WebRequest -Uri "$base/$zipName.sha256" -OutFile "$zipPath.sha256"
+ $published = ((Get-Content "$zipPath.sha256" -TotalCount 1) -split '\s+')[0].ToLowerInvariant()
+ $actualSha = (Get-FileHash -Algorithm SHA256 $zipPath).Hash.ToLowerInvariant()
+ if ($actualSha -ne $published) { Fail "SHA-256 mismatch for ${zipName}: published $published, downloaded $actualSha" }
+ $pinned = KitJsonValue 'sha256'
+ if (-not $Sha256 -and (KitJsonValue 'version') -eq $Version -and $pinned) { $Sha256 = $pinned.ToLowerInvariant() }
+ if ($Sha256 -and $actualSha -ne $Sha256) { Fail "SHA-256 mismatch for ${zipName}: expected $Sha256 (kit.json or -Sha256), got $actualSha" }
+ $kitDir = Join-Path $work 'kit'
+ Expand-Archive -Path $zipPath -DestinationPath $kitDir
+ }
+
+ $newToolkit = Join-Path $kitDir '.toolkit'
+ if (-not (Test-Path (Join-Path $newToolkit 'msbuild/init.props'))) { Fail 'the kit build has no .toolkit/msbuild/init.props' }
+ $partsPath = Join-Path $newToolkit 'kit.parts'
+ if (-not (Test-Path $partsPath)) { Fail 'the kit build has no .toolkit/kit.parts' }
+ if ((Test-Path $toolkit) -and (Resolve-Path $newToolkit).Path -eq (Resolve-Path $toolkit).Path) {
+ Fail 'the target .toolkit is the kit source itself; run from the repository you want to update, or pass -Root'
+ }
+ $parts = [ordered]@{}
+ foreach ($line in Get-Content $partsPath) {
+ $line = $line.Trim()
+ if (-not $line -or $line.StartsWith('#')) { continue }
+ $fields = $line -split '\s+'
+ $parts[$fields[0]] = [pscustomobject]@{ Kind = $fields[1]; Requires = @($fields | Select-Object -Skip 2) }
+ }
+ function PartDir([string] $name) { if ($name -eq 'Trunk') { 'DragoAnt.MSBuildKit' } else { "DragoAnt.MSBuildKit.$name" } }
+
+ $optional = [System.Collections.Generic.List[string]]::new()
+ $recordedParts = @(KitJsonValue 'parts' | Where-Object { $_ })
+ foreach ($p in @($recordedParts) + @($Add)) {
+ if (-not $parts.Contains($p)) { Fail "unknown part '$p'; known parts: $($parts.Keys -join ' ')" }
+ if ($parts[$p].Kind -eq 'optional' -and -not $optional.Contains($p)) { $optional.Add($p) }
+ }
+ foreach ($p in $Remove) {
+ if (-not $parts.Contains($p)) { Fail "unknown part '$p'" }
+ if ($parts[$p].Kind -ne 'optional') { Fail "'$p' is a default part and cannot be removed" }
+ [void]$optional.Remove($p)
+ }
+
+ $selected = [System.Collections.Generic.List[string]]::new()
+ foreach ($name in $parts.Keys) { if ($parts[$name].Kind -eq 'default') { $selected.Add($name) } }
+ $pending = [System.Collections.Generic.Queue[string]]::new([string[]]$optional)
+ while ($pending.Count -gt 0) {
+ $p = $pending.Dequeue()
+ if ($selected.Contains($p)) { continue }
+ $selected.Add($p)
+ foreach ($d in $parts[$p].Requires) { $pending.Enqueue($d) }
+ }
+ $recorded = @($parts.Keys | Where-Object { $selected.Contains($_) -and $parts[$_].Kind -eq 'optional' })
+
+ $stage = Join-Path $work 'stage/msbuild'
+ New-Item -ItemType Directory -Path $stage -Force | Out-Null
+ Get-ChildItem -File (Join-Path $newToolkit 'msbuild') | Copy-Item -Destination $stage
+ foreach ($p in $selected) {
+ $d = PartDir $p
+ $from = Join-Path $newToolkit "msbuild/$d"
+ if (-not (Test-Path $from)) { Fail "the kit build has no part folder msbuild/$d" }
+ Copy-Item -Recurse $from (Join-Path $stage $d)
+ }
+
+ $oldVersion = KitJsonValue 'version'
+ Say "kit $Repo $(if ($oldVersion) { $oldVersion } else { 'none' }) -> $Version$(if ($actualSha) { " (sha256 $actualSha)" })"
+ Say "parts: $($selected -join ' ')"
+
+ $currentMsbuild = Join-Path $toolkit 'msbuild'
+ function RelativeFiles([string] $dir) {
+ if (-not (Test-Path $dir)) { return @() }
+ $full = (Resolve-Path $dir).Path
+ @(Get-ChildItem -Recurse -File $full | ForEach-Object { $_.FullName.Substring($full.Length + 1).Replace('\', '/') } | Sort-Object)
+ }
+ $old = RelativeFiles $currentMsbuild
+ $new = RelativeFiles $stage
+ $changes = 0
+ foreach ($f in $new) {
+ if ($old -notcontains $f) { Say " add .toolkit/msbuild/$f"; $changes++ }
+ elseif ((Get-FileHash (Join-Path $currentMsbuild $f)).Hash -ne (Get-FileHash (Join-Path $stage $f)).Hash) { Say " change .toolkit/msbuild/$f"; $changes++ }
+ }
+ foreach ($f in $old) { if ($new -notcontains $f) { Say " remove .toolkit/msbuild/$f"; $changes++ } }
+
+ $dbp = Join-Path $Root 'Directory.Build.props'
+ $dbt = Join-Path $Root 'Directory.Build.targets'
+ if ($DryRun) {
+ Say "$changes file(s) under .toolkit/msbuild would change"
+ if (-not (Test-Path $dbp)) { Say ' would create Directory.Build.props' }
+ if (-not (Test-Path $dbt)) { Say ' would create Directory.Build.targets' }
+ Say 'dry run: nothing changed'
+ return
+ }
+
+ New-Item -ItemType Directory -Path $toolkit -Force | Out-Null
+ if (Test-Path $currentMsbuild) { Remove-Item -Recurse -Force $currentMsbuild }
+ Copy-Item -Recurse $stage $currentMsbuild
+ $res = Join-Path $newToolkit 'res'
+ if (Test-Path $res) { New-Item -ItemType Directory -Path (Join-Path $toolkit 'res') -Force | Out-Null; Copy-Item -Recurse -Force (Join-Path $res '*') (Join-Path $toolkit 'res') }
+ foreach ($f in 'update.sh', 'update.ps1', 'kit.parts') {
+ $from = Join-Path $newToolkit $f
+ if (Test-Path $from) { Copy-Item -Force $from (Join-Path $toolkit $f) }
+ }
+ Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $toolkit 'kit.version')
+
+ $partsJson = ($recorded | ForEach-Object { "`"$_`"" }) -join ', '
+ $json = "{`n `"repository`": `"$Repo`",`n `"version`": `"$Version`",`n `"sha256`": `"$actualSha`",`n `"parts`": [$partsJson]`n}`n"
+ [System.IO.File]::WriteAllText($kitJsonPath, $json)
+ Say "$changes file(s) under .toolkit/msbuild changed"
+
+ if (-not (Test-Path $dbp)) {
+ [System.IO.File]::WriteAllText($dbp, "`n`n `n`n`n")
+ Say 'created Directory.Build.props'
+ }
+ elseif ((Get-Content -Raw $dbp) -notmatch '\.toolkit[/\\]msbuild[/\\]init\.props') {
+ Say 'add to Directory.Build.props: '
+ }
+ if (-not (Test-Path $dbt)) {
+ [System.IO.File]::WriteAllText($dbt, "`n`n `n`n`n")
+ Say 'created Directory.Build.targets'
+ }
+ elseif ((Get-Content -Raw $dbt) -notmatch '\.toolkit[/\\]msbuild[/\\]init\.targets') {
+ Say 'add to Directory.Build.targets: '
+ }
+ Say "done: DragoAnt.MSBuildKit $Version installed in $toolkit"
+}
+finally {
+ Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $work
+}
diff --git a/.toolkit/update.sh b/.toolkit/update.sh
new file mode 100644
index 0000000..9cec564
--- /dev/null
+++ b/.toolkit/update.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+# Installs or updates DragoAnt.MSBuildKit in a repository's .toolkit/ folder.
+# Usage: sh .toolkit/update.sh [--version X.Y.Z] [--add PART] [--remove PART] [--dry-run]
+# [--source DIR|ZIP] [--sha256 HEX] [--repo OWNER/NAME] [--root DIR]
+set -eu
+
+repo="DragoAnt/MSBuildKit"
+version=""
+source=""
+expected_sha=""
+root=""
+dry_run=0
+add_parts=""
+remove_parts=""
+
+usage() {
+ sed -n '2,4p' "$0" | sed 's/^# \{0,1\}//'
+ cat <<'EOF'
+
+ --version X.Y.Z kit version to install (default: the version in .toolkit/kit.json, else the latest release)
+ --add PART install an optional part (repeatable), e.g. --add PackageAsProj
+ --remove PART uninstall an optional part (repeatable)
+ --dry-run show what would change and change nothing
+ --source DIR|ZIP install from a local kit build instead of a GitHub release
+ --sha256 HEX expected SHA-256 of the release zip (or of a --source zip)
+ --repo OWNER/NAME GitHub repository to download releases from (default: DragoAnt/MSBuildKit)
+ --root DIR repository root (default: the current folder)
+EOF
+}
+
+fail() { echo "update: error: $*" >&2; exit 1; }
+say() { echo "update: $*"; }
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --version) [ $# -ge 2 ] || fail "--version needs a value"; version="${2#v}"; shift 2 ;;
+ --source) [ $# -ge 2 ] || fail "--source needs a value"; source="$2"; shift 2 ;;
+ --sha256) [ $# -ge 2 ] || fail "--sha256 needs a value"; expected_sha=$(printf '%s' "$2" | tr 'A-F' 'a-f'); shift 2 ;;
+ --repo) [ $# -ge 2 ] || fail "--repo needs a value"; repo="$2"; shift 2 ;;
+ --root) [ $# -ge 2 ] || fail "--root needs a value"; root="$2"; shift 2 ;;
+ --add) [ $# -ge 2 ] || fail "--add needs a value"; add_parts="$add_parts $2"; shift 2 ;;
+ --remove) [ $# -ge 2 ] || fail "--remove needs a value"; remove_parts="$remove_parts $2"; shift 2 ;;
+ --dry-run) dry_run=1; shift ;;
+ -h|--help) usage; exit 0 ;;
+ *) fail "unknown argument '$1' (see --help)" ;;
+ esac
+done
+
+[ -n "$root" ] || root=$(pwd)
+[ -d "$root" ] || fail "root '$root' is not a directory"
+toolkit="$root/.toolkit"
+kit_json="$toolkit/kit.json"
+
+json_value() { [ -f "$kit_json" ] && sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$kit_json" | head -n 1 || true; }
+json_parts() { [ -f "$kit_json" ] && sed -n 's/.*"parts"[[:space:]]*:[[:space:]]*\[\(.*\)\].*/\1/p' "$kit_json" | tr -d '" ' | tr ',' ' ' || true; }
+
+sha256_of() {
+ if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1
+ elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d' ' -f1
+ else fail "neither sha256sum nor shasum is available"; fi
+}
+
+download() {
+ if command -v curl >/dev/null 2>&1; then curl -fsSL --retry 3 -o "$2" "$1"
+ elif command -v wget >/dev/null 2>&1; then wget -q -O "$2" "$1"
+ else fail "neither curl nor wget is available"; fi
+}
+
+extract_zip() {
+ if command -v unzip >/dev/null 2>&1; then unzip -q -o "$1" -d "$2"
+ else tar -xf "$1" -C "$2" || fail "cannot extract '$1': install unzip"; fi
+}
+
+work=$(mktemp -d)
+trap 'rm -rf "$work"' EXIT INT TERM
+kit_dir=""
+actual_sha=""
+
+[ -n "$repo" ] || fail "--repo is empty"
+recorded_repo=$(json_value repository)
+if [ -n "$recorded_repo" ] && [ "$repo" = "DragoAnt/MSBuildKit" ]; then repo="$recorded_repo"; fi
+
+if [ -n "$source" ]; then
+ if [ -d "$source" ]; then
+ [ -f "$source/.toolkit/msbuild/init.props" ] || fail "'$source' is not a kit build: no .toolkit/msbuild/init.props"
+ kit_dir="$source"
+ elif [ -f "$source" ]; then
+ actual_sha=$(sha256_of "$source")
+ if [ -n "$expected_sha" ] && [ "$actual_sha" != "$expected_sha" ]; then
+ fail "SHA-256 mismatch for '$source': expected $expected_sha, got $actual_sha"
+ fi
+ mkdir -p "$work/kit"; extract_zip "$source" "$work/kit"; kit_dir="$work/kit"
+ else
+ fail "--source '$source' does not exist"
+ fi
+ [ -n "$version" ] || version=$(sed -n '1p' "$kit_dir/.toolkit/kit.version" 2>/dev/null || true)
+ [ -n "$version" ] || version="0.0.0-local"
+else
+ [ -n "$version" ] || version=$(json_value version)
+ if [ -z "$version" ]; then
+ download "https://api.github.com/repos/$repo/releases/latest" "$work/latest.json" || fail "cannot query the latest release of $repo"
+ tag=$(sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$work/latest.json" | head -n 1)
+ [ -n "$tag" ] || fail "no release found in $repo"
+ version="${tag#v}"
+ fi
+ zip_name="msbuildkit-$version.zip"
+ base="https://github.com/$repo/releases/download/v$version"
+ say "downloading $base/$zip_name"
+ download "$base/$zip_name" "$work/$zip_name" || fail "cannot download $base/$zip_name"
+ download "$base/$zip_name.sha256" "$work/$zip_name.sha256" || fail "cannot download $base/$zip_name.sha256"
+ published_sha=$(cut -d' ' -f1 "$work/$zip_name.sha256" | tr 'A-F' 'a-f')
+ actual_sha=$(sha256_of "$work/$zip_name")
+ [ "$actual_sha" = "$published_sha" ] || fail "SHA-256 mismatch for $zip_name: published $published_sha, downloaded $actual_sha"
+ pinned_sha=$(json_value sha256)
+ if [ -z "$expected_sha" ] && [ "$(json_value version)" = "$version" ] && [ -n "$pinned_sha" ]; then expected_sha="$pinned_sha"; fi
+ if [ -n "$expected_sha" ] && [ "$actual_sha" != "$expected_sha" ]; then
+ fail "SHA-256 mismatch for $zip_name: expected $expected_sha (kit.json or --sha256), got $actual_sha"
+ fi
+ mkdir -p "$work/kit"; extract_zip "$work/$zip_name" "$work/kit"; kit_dir="$work/kit"
+fi
+
+new_toolkit="$kit_dir/.toolkit"
+[ -f "$new_toolkit/msbuild/init.props" ] || fail "the kit build has no .toolkit/msbuild/init.props"
+[ -f "$new_toolkit/kit.parts" ] || fail "the kit build has no .toolkit/kit.parts"
+if [ -d "$toolkit" ] && [ "$(cd "$new_toolkit" && pwd -P)" = "$(cd "$toolkit" && pwd -P)" ]; then fail "the target .toolkit is the kit source itself; run from the repository you want to update, or pass --root"; fi
+parts_file="$work/kit.parts"
+tr -d '\r' < "$new_toolkit/kit.parts" | grep -v '^[[:space:]]*#' | grep -v '^[[:space:]]*$' > "$parts_file"
+
+part_kind() { awk -v p="$1" '$1==p {print $2}' "$parts_file"; }
+part_deps() { awk -v p="$1" '$1==p {for (i=3;i<=NF;i++) print $i}' "$parts_file"; }
+part_dir() { if [ "$1" = "Trunk" ]; then echo "DragoAnt.MSBuildKit"; else echo "DragoAnt.MSBuildKit.$1"; fi; }
+
+optional=""
+for p in $(json_parts) $add_parts; do
+ kind=$(part_kind "$p")
+ [ -n "$kind" ] || fail "unknown part '$p'; known parts: $(awk '{print $1}' "$parts_file" | tr '\n' ' ')"
+ case " $optional " in *" $p "*) ;; *) if [ "$kind" = optional ]; then optional="$optional $p"; fi ;; esac
+done
+for p in $remove_parts; do
+ kind=$(part_kind "$p")
+ [ -n "$kind" ] || fail "unknown part '$p'"
+ [ "$kind" = optional ] || fail "'$p' is a default part and cannot be removed"
+ optional=$(echo " $optional " | sed "s/ $p / /g")
+done
+
+selected=$(awk '$2=="default" {print $1}' "$parts_file")
+pending="$optional"
+while [ -n "$(echo $pending)" ]; do
+ next=""
+ for p in $pending; do
+ case " $(echo $selected) " in *" $p "*) continue ;; esac
+ selected="$selected $p"
+ for d in $(part_deps "$p"); do next="$next $d"; done
+ done
+ pending="$next"
+done
+recorded=""
+for p in $selected; do if [ "$(part_kind "$p")" = optional ]; then recorded="$recorded $p"; fi; done
+recorded=$(echo $recorded)
+
+stage="$work/stage"
+mkdir -p "$stage/msbuild"
+for f in "$new_toolkit"/msbuild/*; do [ -f "$f" ] && cp "$f" "$stage/msbuild/"; done
+for p in $selected; do
+ d=$(part_dir "$p")
+ [ -d "$new_toolkit/msbuild/$d" ] || fail "the kit build has no part folder msbuild/$d"
+ cp -R "$new_toolkit/msbuild/$d" "$stage/msbuild/$d"
+done
+
+old_version=$(json_value version)
+say "kit $repo ${old_version:-none} -> $version${actual_sha:+ (sha256 $actual_sha)}"
+say "parts: $(echo $selected)"
+changes=0
+if [ -d "$toolkit/msbuild" ]; then
+ (cd "$toolkit/msbuild" && find . -type f | sort) > "$work/old.lst"
+else
+ : > "$work/old.lst"
+fi
+(cd "$stage/msbuild" && find . -type f | sort) > "$work/new.lst"
+for f in $(comm -13 "$work/old.lst" "$work/new.lst"); do say " add .toolkit/msbuild/${f#./}"; changes=$((changes+1)); done
+for f in $(comm -23 "$work/old.lst" "$work/new.lst"); do say " remove .toolkit/msbuild/${f#./}"; changes=$((changes+1)); done
+for f in $(comm -12 "$work/old.lst" "$work/new.lst"); do
+ cmp -s "$toolkit/msbuild/$f" "$stage/msbuild/$f" || { say " change .toolkit/msbuild/${f#./}"; changes=$((changes+1)); }
+done
+
+dbp="$root/Directory.Build.props"
+dbt="$root/Directory.Build.targets"
+
+if [ "$dry_run" -eq 1 ]; then
+ say "$changes file(s) under .toolkit/msbuild would change"
+ [ -f "$dbp" ] || say " would create Directory.Build.props"
+ [ -f "$dbt" ] || say " would create Directory.Build.targets"
+ say "dry run: nothing changed"
+ exit 0
+fi
+
+mkdir -p "$toolkit"
+rm -rf "$toolkit/msbuild"
+cp -R "$stage/msbuild" "$toolkit/msbuild"
+if [ -d "$new_toolkit/res" ]; then mkdir -p "$toolkit/res"; cp -R "$new_toolkit/res/." "$toolkit/res/"; fi
+for f in update.sh update.ps1 kit.parts; do [ -f "$new_toolkit/$f" ] && cp "$new_toolkit/$f" "$toolkit/$f"; done
+rm -f "$toolkit/kit.version"
+say "$changes file(s) under .toolkit/msbuild changed"
+
+parts_json=""
+for p in $recorded; do parts_json="$parts_json${parts_json:+, }\"$p\""; done
+printf '{\n "repository": "%s",\n "version": "%s",\n "sha256": "%s",\n "parts": [%s]\n}\n' \
+ "$repo" "$version" "$actual_sha" "$parts_json" > "$kit_json"
+
+if [ ! -f "$dbp" ]; then
+ printf '\n\n \n\n\n' > "$dbp"
+ say "created Directory.Build.props"
+elif ! grep -q '\.toolkit[/\\]msbuild[/\\]init\.props' "$dbp"; then
+ say "add to Directory.Build.props: "
+fi
+if [ ! -f "$dbt" ]; then
+ printf '\n\n \n\n\n' > "$dbt"
+ say "created Directory.Build.targets"
+elif ! grep -q '\.toolkit[/\\]msbuild[/\\]init\.targets' "$dbt"; then
+ say "add to Directory.Build.targets: "
+fi
+say "done: DragoAnt.MSBuildKit $version installed in $toolkit"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 715cde9..af13157 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,10 +4,10 @@ Issues and pull requests are welcome. For anything larger than a small fix, open
## Build and test
-The build imports shared MSBuild files from the `.msbuild` git submodule, so clone with submodules:
+The shared MSBuild settings come from [DragoAnt.MSBuildKit](https://github.com/DragoAnt/MSBuildKit), committed under `.toolkit/`, so a plain clone builds:
```sh
-git clone --recurse-submodules https://github.com/DragoAnt/Extensions.System.Text.Json.git
+git clone https://github.com/DragoAnt/Extensions.System.Text.Json.git
cd Extensions.System.Text.Json
```
@@ -46,6 +46,16 @@ Benchmarks live in `DragoAnt.System.Text.Json.Observer.Benchmarks` (BenchmarkDot
dotnet run -c Release --project DragoAnt.System.Text.Json.Observer.Benchmarks
```
+### Build kit
+
+`.toolkit/` is installed by DragoAnt.MSBuildKit; don't edit it by hand. Move to another kit release with its update script and commit the result:
+
+```sh
+sh .toolkit/update.sh --version 0.2.0 # or: pwsh .toolkit/update.ps1 -Version 0.2.0
+```
+
+Repository settings live in `Directory.Build.props` (target frameworks, copyright), `Directory.Version.props` (the next release's `VersionPrefix`) and `Directory.Packages.props` (package versions the kit does not provide).
+
## Pull requests
- Branch from `main` and target `main`.
diff --git a/Directory.Build.props b/Directory.Build.props
index a7ad065..5e33a71 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,18 +1,8 @@
-
- TargetFrameworks
net8.0;net9.0;net10.0
-
-
-
-
-
-
Copyright (c) 2025 DragoAnt
- MIT
- https://github.com/DragoAnt/Extensions.System.Text.Json
- https://github.com/DragoAnt/Extensions.System.Text.Json/releases
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
index a6c8512..80622f2 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,27 +1,12 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
$([System.String]::Copy('$(NoWarn)').Replace('CS1591',''))
diff --git a/Directory.Packages.props b/Directory.Packages.props
index af073ca..3ab3882 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,7 +1,5 @@
-
-
true
false
@@ -39,17 +37,10 @@
-
-
-
-
-
-
-
diff --git a/Directory.Version.props b/Directory.Version.props
new file mode 100644
index 0000000..16af6b2
--- /dev/null
+++ b/Directory.Version.props
@@ -0,0 +1,5 @@
+
+
+ 2.0.0
+
+
diff --git a/DragoAnt.System.Text.Json.slnx b/DragoAnt.System.Text.Json.slnx
index 8ef29b4..17f14c0 100644
--- a/DragoAnt.System.Text.Json.slnx
+++ b/DragoAnt.System.Text.Json.slnx
@@ -1,8 +1,4 @@
-
-
-
-
@@ -10,6 +6,7 @@
+
From 42f74248960be524eea538accf83e4b5fdbd711e Mon Sep 17 00:00:00 2001
From: VasiliyF <5789590+vfofanov@users.noreply.github.com>
Date: Sat, 3 Oct 2026 21:24:06 +0200
Subject: [PATCH 2/3] Generate XML docs ahead of the kit's late default
MSBuildKit 0.1.0 sets GenerateDocumentationFile after the SDK has
defaulted it to false, so the packages lost their XML docs and the
EnforcePublicApiDocs CS1591 gate stopped firing. Set it in
Directory.Build.props until the kit fix ships. Also mark
.toolkit/update.sh executable.
---
.toolkit/update.sh | 0
Directory.Build.props | 2 ++
2 files changed, 2 insertions(+)
mode change 100644 => 100755 .toolkit/update.sh
diff --git a/.toolkit/update.sh b/.toolkit/update.sh
old mode 100644
new mode 100755
diff --git a/Directory.Build.props b/Directory.Build.props
index 5e33a71..e226558 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,6 +2,8 @@
net8.0;net9.0;net10.0
Copyright (c) 2025 DragoAnt
+
+ true
From aa54088e501282daf1451c024078dd6997868ed7 Mon Sep 17 00:00:00 2001
From: VasiliyF <5789590+vfofanov@users.noreply.github.com>
Date: Sun, 4 Oct 2026 01:28:42 +0200
Subject: [PATCH 3/3] Update DragoAnt.MSBuildKit to 0.1.1
0.1.1 sets GenerateDocumentationFile in its props phase, so the
Directory.Build.props workaround goes.
---
.toolkit/kit.json | 4 ++--
.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props | 2 ++
.../msbuild/DragoAnt.MSBuildKit.Packaging/package.targets | 1 -
Directory.Build.props | 2 --
4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/.toolkit/kit.json b/.toolkit/kit.json
index dcb1eef..cfb9460 100644
--- a/.toolkit/kit.json
+++ b/.toolkit/kit.json
@@ -1,6 +1,6 @@
{
"repository": "DragoAnt/MSBuildKit",
- "version": "0.1.0",
- "sha256": "55c2f40a21fed8bcb5f727a56cf4830e476277574463437dd41560980dbec887",
+ "version": "0.1.1",
+ "sha256": "a16b4320b85318ed187b040a6d078e80587c201e918aaadea17f1a7af759c71e",
"parts": ["PackageAsProj"]
}
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
index e739d5c..4d34098 100644
--- a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props
@@ -7,6 +7,8 @@
true
true
true
+
+ True
true
diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
index 89204e3..05add92 100644
--- a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
+++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets
@@ -6,7 +6,6 @@
$(MSBuildProjectName)
- True
false
git
$(RepositoryUrl)
diff --git a/Directory.Build.props b/Directory.Build.props
index e226558..5e33a71 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,8 +2,6 @@
net8.0;net9.0;net10.0
Copyright (c) 2025 DragoAnt
-
- true