From 3a6783ff7b7eca56f5579b794eccf191382faf75 Mon Sep 17 00:00:00 2001
From: qwsdcvghyu89 <61093706+qwsdcvghyu89@users.noreply.github.com>
Date: Sun, 21 Sep 2025 14:57:41 +1000
Subject: [PATCH] Revert "First Commit"
This reverts commit a9a9733e663f09e954d52196fd31ba102063c0b9.
---
.../.idea/.gitignore | 13 -
.../.idea/encodings.xml | 4 -
.../.idea/indexLayout.xml | 8 -
.../.idea.aeqw89.tools.Publish/.idea/vcs.xml | 6 -
aeqw89.tools.Publish.sln | 16 -
aeqw89.tools.Publish.sln.DotSettings.user | 15 -
aeqw89.tools.Publish/.gitignore | 0
aeqw89.tools.Publish/Content.cs | 7 -
aeqw89.tools.Publish/Exceptions.Designer.cs | 224 ---------
aeqw89.tools.Publish/Exceptions.resx | 75 ---
aeqw89.tools.Publish/IncrementTarget.cs | 7 -
aeqw89.tools.Publish/Item.cs | 55 --
aeqw89.tools.Publish/ItemGroup.cs | 26 -
aeqw89.tools.Publish/Mode.cs | 6 -
aeqw89.tools.Publish/PackageReference.cs | 30 --
aeqw89.tools.Publish/PrivateAssetsValue.cs | 6 -
aeqw89.tools.Publish/Program.cs | 473 ------------------
aeqw89.tools.Publish/Project.cs | 54 --
aeqw89.tools.Publish/ProjectFile.cs | 216 --------
aeqw89.tools.Publish/ProjectReference.cs | 7 -
aeqw89.tools.Publish/PropertyGroup.cs | 28 --
aeqw89.tools.Publish/RemotePath.cs | 90 ----
aeqw89.tools.Publish/SshHosts.cs | 423 ----------------
.../aeqw89.tools.Publish.csproj | 32 --
.../net9.0/BouncyCastle.Cryptography.dll | Bin 4870808 -> 0 bytes
...sions.DependencyInjection.Abstractions.dll | Bin 63768 -> 0 bytes
...rosoft.Extensions.Logging.Abstractions.dll | Bin 65288 -> 0 bytes
.../bin/Debug/net9.0/Renci.SshNet.dll | Bin 522752 -> 0 bytes
.../bin/Debug/net9.0/Spectre.Console.Cli.dll | Bin 192512 -> 0 bytes
.../bin/Debug/net9.0/Spectre.Console.dll | Bin 754176 -> 0 bytes
.../bin/Debug/net9.0/VsTools.Projects.dll | Bin 30208 -> 0 bytes
.../net9.0/aeqw89.tools.Publish.deps.json | 176 -------
.../bin/Debug/net9.0/aeqw89.tools.Publish.dll | Bin 66048 -> 0 bytes
.../bin/Debug/net9.0/aeqw89.tools.Publish.exe | Bin 145408 -> 0 bytes
.../bin/Debug/net9.0/aeqw89.tools.Publish.pdb | Bin 31956 -> 0 bytes
.../aeqw89.tools.Publish.runtimeconfig.json | 12 -
.../de/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../es/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../fr/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../it/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../ja/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../ko/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../pt/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../ru/Spectre.Console.Cli.resources.dll | Bin 5632 -> 0 bytes
.../sv/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
.../zh-Hans/Spectre.Console.Cli.resources.dll | Bin 5120 -> 0 bytes
...CoreApp,Version=v9.0.AssemblyAttributes.cs | 4 -
.../Debug/net9.0/aeqw89.t.65D2674F.Up2Date | 0
.../aeqw89.tools.Publish.AssemblyInfo.cs | 22 -
...w89.tools.Publish.AssemblyInfoInputs.cache | 1 -
.../aeqw89.tools.Publish.Exceptions.resources | Bin 2735 -> 0 bytes
....GeneratedMSBuildEditorConfig.editorconfig | 15 -
.../aeqw89.tools.Publish.GlobalUsings.g.cs | 8 -
.../net9.0/aeqw89.tools.Publish.assets.cache | Bin 7731 -> 0 bytes
...ols.Publish.csproj.AssemblyReference.cache | Bin 3222 -> 0 bytes
...ols.Publish.csproj.CoreCompileInputs.cache | 1 -
....tools.Publish.csproj.FileListAbsolute.txt | 35 --
...ools.Publish.csproj.GenerateResource.cache | Bin 64 -> 0 bytes
.../obj/Debug/net9.0/aeqw89.tools.Publish.dll | Bin 66048 -> 0 bytes
...eqw89.tools.Publish.genruntimeconfig.cache | 1 -
.../obj/Debug/net9.0/aeqw89.tools.Publish.pdb | Bin 31956 -> 0 bytes
.../obj/Debug/net9.0/apphost.exe | Bin 145408 -> 0 bytes
.../Debug/net9.0/ref/aeqw89.tools.Publish.dll | Bin 17920 -> 0 bytes
.../net9.0/refint/aeqw89.tools.Publish.dll | Bin 17920 -> 0 bytes
...w89.tools.Publish.csproj.nuget.dgspec.json | 86 ----
.../aeqw89.tools.Publish.csproj.nuget.g.props | 15 -
...eqw89.tools.Publish.csproj.nuget.g.targets | 6 -
aeqw89.tools.Publish/obj/project.assets.json | 464 -----------------
aeqw89.tools.Publish/obj/project.nuget.cache | 16 -
.../obj/project.packagespec.json | 1 -
.../obj/rider.project.model.nuget.info | 1 -
.../obj/rider.project.restore.info | 1 -
72 files changed, 2686 deletions(-)
delete mode 100644 .idea/.idea.aeqw89.tools.Publish/.idea/.gitignore
delete mode 100644 .idea/.idea.aeqw89.tools.Publish/.idea/encodings.xml
delete mode 100644 .idea/.idea.aeqw89.tools.Publish/.idea/indexLayout.xml
delete mode 100644 .idea/.idea.aeqw89.tools.Publish/.idea/vcs.xml
delete mode 100644 aeqw89.tools.Publish.sln
delete mode 100644 aeqw89.tools.Publish.sln.DotSettings.user
delete mode 100644 aeqw89.tools.Publish/.gitignore
delete mode 100644 aeqw89.tools.Publish/Content.cs
delete mode 100644 aeqw89.tools.Publish/Exceptions.Designer.cs
delete mode 100644 aeqw89.tools.Publish/Exceptions.resx
delete mode 100644 aeqw89.tools.Publish/IncrementTarget.cs
delete mode 100644 aeqw89.tools.Publish/Item.cs
delete mode 100644 aeqw89.tools.Publish/ItemGroup.cs
delete mode 100644 aeqw89.tools.Publish/Mode.cs
delete mode 100644 aeqw89.tools.Publish/PackageReference.cs
delete mode 100644 aeqw89.tools.Publish/PrivateAssetsValue.cs
delete mode 100644 aeqw89.tools.Publish/Program.cs
delete mode 100644 aeqw89.tools.Publish/Project.cs
delete mode 100644 aeqw89.tools.Publish/ProjectFile.cs
delete mode 100644 aeqw89.tools.Publish/ProjectReference.cs
delete mode 100644 aeqw89.tools.Publish/PropertyGroup.cs
delete mode 100644 aeqw89.tools.Publish/RemotePath.cs
delete mode 100644 aeqw89.tools.Publish/SshHosts.cs
delete mode 100644 aeqw89.tools.Publish/aeqw89.tools.Publish.csproj
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/BouncyCastle.Cryptography.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/Microsoft.Extensions.Logging.Abstractions.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/Renci.SshNet.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/Spectre.Console.Cli.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/Spectre.Console.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/VsTools.Projects.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/aeqw89.tools.Publish.deps.json
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/aeqw89.tools.Publish.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/aeqw89.tools.Publish.exe
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/aeqw89.tools.Publish.pdb
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/aeqw89.tools.Publish.runtimeconfig.json
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/de/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/es/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/fr/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/it/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/ja/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/ko/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/pt/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/ru/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/sv/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/bin/Debug/net9.0/zh-Hans/Spectre.Console.Cli.resources.dll
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.t.65D2674F.Up2Date
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.AssemblyInfo.cs
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.AssemblyInfoInputs.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.Exceptions.resources
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.GeneratedMSBuildEditorConfig.editorconfig
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.GlobalUsings.g.cs
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.assets.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.csproj.AssemblyReference.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.csproj.CoreCompileInputs.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.csproj.FileListAbsolute.txt
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.csproj.GenerateResource.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.dll
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.genruntimeconfig.cache
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/aeqw89.tools.Publish.pdb
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/apphost.exe
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/ref/aeqw89.tools.Publish.dll
delete mode 100644 aeqw89.tools.Publish/obj/Debug/net9.0/refint/aeqw89.tools.Publish.dll
delete mode 100644 aeqw89.tools.Publish/obj/aeqw89.tools.Publish.csproj.nuget.dgspec.json
delete mode 100644 aeqw89.tools.Publish/obj/aeqw89.tools.Publish.csproj.nuget.g.props
delete mode 100644 aeqw89.tools.Publish/obj/aeqw89.tools.Publish.csproj.nuget.g.targets
delete mode 100644 aeqw89.tools.Publish/obj/project.assets.json
delete mode 100644 aeqw89.tools.Publish/obj/project.nuget.cache
delete mode 100644 aeqw89.tools.Publish/obj/project.packagespec.json
delete mode 100644 aeqw89.tools.Publish/obj/rider.project.model.nuget.info
delete mode 100644 aeqw89.tools.Publish/obj/rider.project.restore.info
diff --git a/.idea/.idea.aeqw89.tools.Publish/.idea/.gitignore b/.idea/.idea.aeqw89.tools.Publish/.idea/.gitignore
deleted file mode 100644
index 2784543..0000000
--- a/.idea/.idea.aeqw89.tools.Publish/.idea/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Rider ignored files
-/projectSettingsUpdater.xml
-/.idea.aeqw89.tools.Publish.iml
-/modules.xml
-/contentModel.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/.idea.aeqw89.tools.Publish/.idea/encodings.xml b/.idea/.idea.aeqw89.tools.Publish/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/.idea/.idea.aeqw89.tools.Publish/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.aeqw89.tools.Publish/.idea/indexLayout.xml b/.idea/.idea.aeqw89.tools.Publish/.idea/indexLayout.xml
deleted file mode 100644
index 7b08163..0000000
--- a/.idea/.idea.aeqw89.tools.Publish/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.aeqw89.tools.Publish/.idea/vcs.xml b/.idea/.idea.aeqw89.tools.Publish/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/.idea.aeqw89.tools.Publish/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/aeqw89.tools.Publish.sln b/aeqw89.tools.Publish.sln
deleted file mode 100644
index 5edac2c..0000000
--- a/aeqw89.tools.Publish.sln
+++ /dev/null
@@ -1,16 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aeqw89.tools.Publish", "aeqw89.tools.Publish\aeqw89.tools.Publish.csproj", "{B7F78AEB-BAC3-4D34-A655-BC0B5677EA42}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B7F78AEB-BAC3-4D34-A655-BC0B5677EA42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B7F78AEB-BAC3-4D34-A655-BC0B5677EA42}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B7F78AEB-BAC3-4D34-A655-BC0B5677EA42}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B7F78AEB-BAC3-4D34-A655-BC0B5677EA42}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/aeqw89.tools.Publish.sln.DotSettings.user b/aeqw89.tools.Publish.sln.DotSettings.user
deleted file mode 100644
index 57d78f9..0000000
--- a/aeqw89.tools.Publish.sln.DotSettings.user
+++ /dev/null
@@ -1,15 +0,0 @@
-
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- ForceIncluded
- True
- True
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/.gitignore b/aeqw89.tools.Publish/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/aeqw89.tools.Publish/Content.cs b/aeqw89.tools.Publish/Content.cs
deleted file mode 100644
index 03a7e7a..0000000
--- a/aeqw89.tools.Publish/Content.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal sealed class Content : Item {
- public Content(XmlElement node) : base(node) { }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/Exceptions.Designer.cs b/aeqw89.tools.Publish/Exceptions.Designer.cs
deleted file mode 100644
index ce608e7..0000000
--- a/aeqw89.tools.Publish/Exceptions.Designer.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace aeqw89.tools.Publish {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Exceptions {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Exceptions() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("aeqw89.tools.Publish.Exceptions", typeof(Exceptions).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized string similar to The cloud host '{0}' is not an entry on this user's config file..
- ///
- internal static string cloud_host_not_found {
- get {
- return ResourceManager.GetString("cloud_host_not_found", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The mode '{0}' is invalid, the valid modes are [overwrite|increment].
- ///
- internal static string could_not_parse_mode {
- get {
- return ResourceManager.GetString("could_not_parse_mode", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The increment target '{0}' is invalid, the valid increment targets are [patch|minor|patch].
- ///
- internal static string could_not_parse_target {
- get {
- return ResourceManager.GetString("could_not_parse_target", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The 'dotnet nuget push' command failed with error message '{0}'.
- ///
- internal static string dotnet_nuget_push_failure {
- get {
- return ResourceManager.GetString("dotnet_nuget_push_failure", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Failed to pack; ensure that 'dotnet build' succeeds before running this program..
- ///
- internal static string dotnet_pack_failure {
- get {
- return ResourceManager.GetString("dotnet_pack_failure", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Could not delete temporary directory '{0}' due to error '{1}'.
- ///
- internal static string failed_to_clean_up {
- get {
- return ResourceManager.GetString("failed_to_clean_up", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Failde to prepare an upload directory on the path {0} for the remote host '{1}', after being detected as a {2} host. Server error is '{3}'.
- ///
- internal static string failed_to_prepare_server_directory {
- get {
- return ResourceManager.GetString("failed_to_prepare_server_directory", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The flag '{0}' requires exactly '{1}' parameters. You have entered '{2}'..
- ///
- internal static string flag_parameter_length_incorrect {
- get {
- return ResourceManager.GetString("flag_parameter_length_incorrect", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The '{0}' flag requires that argument with index '{1}' be of type '{2}'. You have entered '{3}' which has failed to be converted..
- ///
- internal static string flag_parameter_type_incorrect {
- get {
- return ResourceManager.GetString("flag_parameter_type_incorrect", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The directory '{0}' contains multiple .csproj files; this tool can only process one at a time..
- ///
- internal static string found_multiple_csproj {
- get {
- return ResourceManager.GetString("found_multiple_csproj", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Something went wrong loading this file; {0}.
- ///
- internal static string generic_error {
- get {
- return ResourceManager.GetString("generic_error", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to You must specify at least one destination..
- ///
- internal static string missing_destinations {
- get {
- return ResourceManager.GetString("missing_destinations", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to You must specify an increment target if you specified an increment mode; allowed increment targets are [patch|minor|major].
- ///
- internal static string missing_increment_target {
- get {
- return ResourceManager.GetString("missing_increment_target", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to You must specify a mode; allowed modes are [overwrite|increment].
- ///
- internal static string missing_mode {
- get {
- return ResourceManager.GetString("missing_mode", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to No project file was found within the current directory..
- ///
- internal static string no_project_in_directory {
- get {
- return ResourceManager.GetString("no_project_in_directory", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The project file '{0}' is irreparable becuase it is missing a '{1}' property, and the value cannot be guessed..
- ///
- internal static string project_file_irreparable {
- get {
- return ResourceManager.GetString("project_file_irreparable", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Something went wrong; an attempt was made to load a non .csproj file as a project file..
- ///
- internal static string tried_loading_non_csproj_file {
- get {
- return ResourceManager.GetString("tried_loading_non_csproj_file", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The version string '{0}' is in an unidentifiable format..
- ///
- internal static string version_string_not_formatted_correctly {
- get {
- return ResourceManager.GetString("version_string_not_formatted_correctly", resourceCulture);
- }
- }
- }
-}
diff --git a/aeqw89.tools.Publish/Exceptions.resx b/aeqw89.tools.Publish/Exceptions.resx
deleted file mode 100644
index 640185f..0000000
--- a/aeqw89.tools.Publish/Exceptions.resx
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- You must specify a mode; allowed modes are [overwrite|increment]
-
-
- The mode '{0}' is invalid, the valid modes are [overwrite|increment]
-
-
- The increment target '{0}' is invalid, the valid increment targets are [patch|minor|patch]
-
-
- You must specify an increment target if you specified an increment mode; allowed increment targets are [patch|minor|major]
-
-
- You must specify at least one destination.
-
-
- No project file was found within the current directory.
-
-
- The flag '{0}' requires exactly '{1}' parameters. You have entered '{2}'.
-
-
- The '{0}' flag requires that argument with index '{1}' be of type '{2}'. You have entered '{3}' which has failed to be converted.
-
-
- The version string '{0}' is in an unidentifiable format.
-
-
- Something went wrong; an attempt was made to load a non .csproj file as a project file.
-
-
- Something went wrong loading this file; {0}
-
-
- The directory '{0}' contains multiple .csproj files; this tool can only process one at a time.
-
-
- The project file '{0}' is irreparable becuase it is missing a '{1}' property, and the value cannot be guessed.
-
-
- Failed to pack; ensure that 'dotnet build' succeeds before running this program.
-
-
- Could not delete temporary directory '{0}' due to error '{1}'
-
-
- The cloud host '{0}' is not an entry on this user's config file.
-
-
- Failde to prepare an upload directory on the path {0} for the remote host '{1}', after being detected as a {2} host. Server error is '{3}'
-
-
- The 'dotnet nuget push' command failed with error message '{0}'
-
-
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/IncrementTarget.cs b/aeqw89.tools.Publish/IncrementTarget.cs
deleted file mode 100644
index 57242c8..0000000
--- a/aeqw89.tools.Publish/IncrementTarget.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace aeqw89.tools.Publish;
-
-public enum IncrementTarget {
- Patch,
- Minor,
- Major,
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/Item.cs b/aeqw89.tools.Publish/Item.cs
deleted file mode 100644
index 6a4ed7e..0000000
--- a/aeqw89.tools.Publish/Item.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal class Item {
- public string ElementName { get; protected set; }
- public string Include {
- get => Node.GetAttribute("Include");
- set => Node.SetAttribute("Include", value);
- }
-
- public string Version {
- get => Node.GetAttribute("Version");
- set => Node.SetAttribute("Version", value);
- }
-
- public string? Value {
- get => Node.InnerText;
- set { Node.InnerText = value ?? string.Empty; }
- }
- public XmlElement Node { get; }
-
- protected Item(XmlElement node) {
- Node = node;
- ElementName = node.Name;
- }
-
- public static Item FromElement(XmlElement element) {
- return element.Name switch {
- "PackageReference" => new PackageReference(element),
- "ProjectReference" => new ProjectReference(element),
- "Content" => new Content(element),
- _ => new Item(element),
- };
- }
-
- public void AddChild(Item child) {
- var imported = Node.OwnerDocument!.ImportNode(child.Node, true);
- Node.AppendChild(imported);
- }
-
- public string? GetAttribute(string name) => Node.HasAttribute(name) ? Node.GetAttribute(name) : null;
- public void SetAttribute(string name, string? value) {
- if (value is null) {
- if (Node.HasAttribute(name)) Node.RemoveAttribute(name);
- return;
- }
- Node.SetAttribute(name, value);
- }
-
- public IEnumerable- GetChildElements() {
- foreach (var e in Node.ChildNodes.OfType())
- yield return new Item(e);
- }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/ItemGroup.cs b/aeqw89.tools.Publish/ItemGroup.cs
deleted file mode 100644
index 88824a4..0000000
--- a/aeqw89.tools.Publish/ItemGroup.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal class ItemGroup {
- private readonly XmlElement _element;
- public List
- Items { get; }
-
- public void Remove() {
- _element.ParentNode!.RemoveChild(_element);
- }
-
- public ItemGroup(XmlElement element) {
- _element = element;
- Items = element.ChildNodes
- .OfType()
- .Select(Item.FromElement)
- .ToList();
- }
-
- public void Add(Item item) {
- var imported = _element.OwnerDocument!.ImportNode(item.Node, true);
- _element.AppendChild(imported);
- Items.Add(Item.FromElement((XmlElement)imported));
- }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/Mode.cs b/aeqw89.tools.Publish/Mode.cs
deleted file mode 100644
index 8d13c46..0000000
--- a/aeqw89.tools.Publish/Mode.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace aeqw89.tools.Publish;
-
-public enum Mode {
- Overwrite,
- Increment,
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/PackageReference.cs b/aeqw89.tools.Publish/PackageReference.cs
deleted file mode 100644
index 7413954..0000000
--- a/aeqw89.tools.Publish/PackageReference.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal sealed class PackageReference : Item {
- public PackageReference(XmlElement node) : base(node) { }
-
- // inside PackageReference
- public string? GetPackageVersion() {
- // Prefer attribute, then child
- var attr = GetAttribute("Version");
- if (!string.IsNullOrEmpty(attr)) return attr;
-
- var child = Node.SelectSingleNode("./Version") as XmlElement;
- return child?.InnerText;
- }
-
- public void SetPackageVersion(string? version) {
- if (Node.HasAttribute("Version") || (Node.SelectSingleNode("./Version") == null)) {
- // If attribute exists (or no child yet), use attribute
- SetAttribute("Version", version);
- return;
- }
-
- // Else write to existing child
- var child = (XmlElement)Node.SelectSingleNode("./Version")!;
- child.InnerText = version ?? string.Empty;
- }
-
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/PrivateAssetsValue.cs b/aeqw89.tools.Publish/PrivateAssetsValue.cs
deleted file mode 100644
index 39e923a..0000000
--- a/aeqw89.tools.Publish/PrivateAssetsValue.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace aeqw89.tools.Publish;
-
-public enum PrivateAssetsValue {
- All,
- None,
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/Program.cs b/aeqw89.tools.Publish/Program.cs
deleted file mode 100644
index 8a37de3..0000000
--- a/aeqw89.tools.Publish/Program.cs
+++ /dev/null
@@ -1,473 +0,0 @@
-using System.Collections;
-using System.Diagnostics;
-using Renci.SshNet;
-using Spectre.Console;
-using Spectre.Console.Cli;
-using VsTools.Projects;
-
-namespace aeqw89.tools.Publish;
-
-/*
- * Structure of the program:
- * - publish (executable)
- * - overwrite
- * - destinations
- * - flags
- * - increment
- * - patch|minor|major
- * - destinations
- * - flags
- * e.g. publish overwrite|increment [patch|minor|major] destinations [flags]
- */
-
-public static class Program {
- public static Mode Mode { get; set; }
- public static IncrementTarget? Target { get; set; }
- public static string[] Destinations { get; set; }
- public static Dictionary Flags { get; set; }
- public static bool Verbose { get; set; } = false;
-
- public static void ReadArgs(string[] args) {
- if (args.Length < 1) {
- ShowError(Exceptions.missing_mode.EscapeMarkup());
- ShowHelp();
- return;
- }
-
- Mode = args[0] switch {
- "overwrite" => Mode.Overwrite,
- "increment" => Mode.Increment,
- _ => (Mode)(-1)
- };
-
- if (Mode == (Mode)(-1)) {
- ShowError(Exceptions.could_not_parse_mode.EscapeMarkup(), args[0].EscapeMarkup());
- ShowHelp();
- return;
- }
-
- if (args.Length < 2) {
- if (Mode == Mode.Increment)
- ShowError(Exceptions.missing_increment_target.EscapeMarkup());
- else if (Mode == Mode.Overwrite)
- ShowError(Exceptions.missing_destinations.EscapeMarkup());
- ShowHelp();
- return;
- }
-
- Destinations = args[1..];
- Flags = [];
- if (Mode == Mode.Increment) {
- if (args.Length < 3) {
- ShowError(Exceptions.missing_destinations.EscapeMarkup());
- ShowHelp();
- return;
- }
-
- Destinations = args[2..];
-
- Target = args[1] switch {
- "patch" => IncrementTarget.Patch,
- "minor" => IncrementTarget.Minor,
- "major" => IncrementTarget.Major,
- _ => (IncrementTarget)(-1)
- };
-
- if (Target == (IncrementTarget)(-1)) {
- ShowError(Exceptions.could_not_parse_target.EscapeMarkup(), args[1].EscapeMarkup());
- ShowHelp();
- return;
- }
- }
-
- string? firstFlag = Destinations.FirstOrDefault(x => x.StartsWith('-'));
- if (firstFlag == null) return;
- string[] flags = Destinations.SkipWhile(x => x != firstFlag).ToArray();
- Flags = ReadFlags(flags);
- Destinations = Destinations.TakeWhile(x => x != firstFlag).ToArray();
- Verbose = Flags.ContainsKey("--verbose") || Flags.ContainsKey("-v");
- }
-
- private static Dictionary ReadFlags(string[] flags) {
- Dictionary result = [];
- List collected = [];
- string lastKey = flags[0];
- if (flags.Length == 1)
- result[lastKey] = [];
- foreach (var flag in flags.Skip(1)) {
- if (flag.StartsWith('-')) {
- result[lastKey] = collected.ToArray();
- collected = [];
- lastKey = flag;
- } else
- collected.Add(flag);
- }
-
- return result;
- }
-
- public static async Task Main(string[] args) {
- ReadArgs(args);
-
- string packageId = "";
- string version = "";
-
- var result = AnsiConsole.Status()
- .Spinner(Spinner.Known.Dots)
- .Start("Preparing project", ctx => {
- ctx.Status = "Locating project file";
- if (!ProjectFile.TryLoad(Environment.CurrentDirectory, out var projectFile, out var error)) {
- ShowError(error.EscapeMarkup());
- return false;
- }
-
- packageId = projectFile.GetPackageId();
-
- try {
- projectFile.Backup();
- if (Verbose)
- AnsiConsole.WriteLine(
- $"Created project file backup at {projectFile.GetDefaultBackupLocation()}");
-
- ctx.Status = "Repairing project file";
- if (!Flags.ContainsKey("--skip-repair"))
- if (!projectFile.TryRepair(out error)) {
- ShowError(error.EscapeMarkup());
- projectFile.Restore();
- return false;
- }
-
- if (Mode == Mode.Increment && !Flags.ContainsKey("--simulate")) {
- int delta = 1;
- if (Flags.TryGetValue("--delta", out var deltaStrings)) {
- if (deltaStrings.Length != 1) {
- ShowError(Exceptions.flag_parameter_length_incorrect.EscapeMarkup(), "--delta", 1,
- deltaStrings.Length);
- projectFile.Restore();
- ShowHelp();
- return false;
- }
-
- if (!int.TryParse(deltaStrings[0], out delta)) {
- ShowError(Exceptions.flag_parameter_type_incorrect.EscapeMarkup(), "--delta", 0, nameof(Int32),
- deltaStrings[0]);
- projectFile.Restore();
- ShowHelp();
- return false;
- }
- }
-
- ctx.Status = "Updating version";
- var version = projectFile.GetVersion();
- version = ChangeVersion(version,
- Target == IncrementTarget.Patch ? delta : 0,
- Target == IncrementTarget.Minor ? delta : 0,
- Target == IncrementTarget.Major ? delta : 0,
- (x, y) => x + y);
-
- projectFile.SetVersion(version);
- }
- }
- catch (Exception e) {
- ShowError(Exceptions.generic_error.EscapeMarkup(), e.ToString().EscapeMarkup());
- projectFile.Restore();
- return false;
- }
-
- version = projectFile.GetVersion();
-
- if (!Flags.ContainsKey("--simulate")) {
- try {
- var packageReferences = projectFile.GetPackageReferences();
- foreach (var reference in packageReferences.Where(x => !projectFile.IsTransitive(x)))
- projectFile.SetPrivateAssets(reference, PrivateAssetsValue.All);
- foreach (var reference in packageReferences.Where(x => projectFile.IsTransitive(x)))
- projectFile.RemovePackage(reference);
-
- HashSet visited = [];
- var projectReferences = new Queue
- (projectFile.GetProjectReferences().Cast
- ());
- while (projectReferences.Count != 0) {
- var reference = projectReferences.Dequeue();
- visited.Add(reference.Include);
-
- if (Verbose)
- AnsiConsole.WriteLine($"Processing project reference {reference.Include} out of {visited.Count} so far");
-
- projectFile.SetPrivateAssets(reference, PrivateAssetsValue.All);
- string pathToReferencedProjectFile = projectFile.GetAbsoluteIncludePath(reference);
- if (!ProjectFile.TryLoad(pathToReferencedProjectFile, out var referencedProjectFile,
- out error)) {
- ShowError(error.EscapeMarkup());
- projectFile.Restore();
- return false;
- }
-
- var referencedPackageReferences = referencedProjectFile.GetPackageReferences();
- foreach (var package in referencedPackageReferences) {
- if (Verbose)
- AnsiConsole.WriteLine($"Hoisting package {package.Include} from {pathToReferencedProjectFile}");
- var hoisted = projectFile.AddPackage(package);
- projectFile.SetTransitive(hoisted, true);
- projectFile.SetPrivateAssets(hoisted, PrivateAssetsValue.None);
- referencedProjectFile.SetPrivateAssets(package, PrivateAssetsValue.All);
- }
-
- var referencedProjectReferences = referencedProjectFile.GetProjectReferences();
- foreach (var project in referencedProjectReferences) {
- if (!visited.Contains(project.Include))
- projectReferences.Enqueue(project);
- }
- }
- } catch (Exception e) {
- ShowError(Exceptions.generic_error.EscapeMarkup(), e.ToString().EscapeMarkup());
- projectFile.Restore();
- return false;
- }
- }
-
- projectFile.Save();
- return true;
- });
-
- if (!result) {
- return;
- }
-
- var outDir = Path.GetRandomFileName();
- result = AnsiConsole.Status()
- .Spinner(Spinner.Known.Dots)
- .Start("Creating package with 'dotnet pack' ", ctx => {
- var p = Process.Start(new ProcessStartInfo() {
- FileName = "dotnet",
- Arguments = $"pack -o {outDir}",
- WorkingDirectory = Environment.CurrentDirectory,
- UseShellExecute = Verbose,
- RedirectStandardOutput = !Verbose,
- RedirectStandardError = !Verbose
- });
- p?.WaitForExit();
- return p?.ExitCode == 0;
- });
-
- if (!result) {
- ShowError(Exceptions.dotnet_pack_failure.EscapeMarkup());
- return;
- }
-
- var package = Directory.GetFiles(outDir, "*.nupkg").FirstOrDefault();
- if (package == null) {
- ShowError(Exceptions.generic_error.EscapeMarkup());
- return;
- }
-
- var inMemory = await File.ReadAllBytesAsync(package);
- var size = new FileInfo(package).Length;
- const long bufferSize = 80 * 1024; // 80 KB
- try {
- await AnsiConsole.Progress()
- .AutoClear(true)
- .HideCompleted(true)
- .Columns(new ProgressColumn[] {
- new TaskDescriptionColumn(),
- new ProgressBarColumn()
- .RemainingStyle(Style.Parse("dim gray slowblink"))
- .CompletedStyle(Style.Parse("green strikethrough"))
- .FinishedStyle("green strikethrough"),
- new DownloadedColumn(),
- new RemainingTimeColumn(),
- new TransferSpeedColumn(),
- })
- .StartAsync(async ctx => {
- await Parallel.ForEachAsync(Destinations, new ParallelOptions() {
- MaxDegreeOfParallelism = Environment.ProcessorCount,
- }, async (dest, ct) => {
- using var reader = new MemoryStream(inMemory);
- var task = ctx.AddTask(dest, new ProgressTaskSettings() {
- MaxValue = size
- });
-
- if (dest.StartsWith("local-")) {
- var name = dest[("local-".Length)..];
- var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
- name, Path.GetFileName(package));
- if (!Directory.Exists(Path.GetDirectoryName(path)))
- Directory.CreateDirectory(Path.GetDirectoryName(path)!);
- await using var writer = File.OpenWrite(path);
- var buffer = new byte[bufferSize];
- int read;
- do {
- read = await reader.ReadAsync(buffer, ct);
- writer.Write(buffer, 0, read);
- task.Increment(read);
- } while (read > 0);
- }
-
- else if (dest.StartsWith("cloud-")) {
- var name = dest[("cloud-".Length)..];
- var connectionTask = ctx.AddTaskBefore($"Preparing cloud-{name}", new ProgressTaskSettings() {
- MaxValue = 100
- }, task);
-
- if (!SshHosts.TryGetHost(name, out var host)) {
- ShowError(Exceptions.cloud_host_not_found.EscapeMarkup(), name);
- return;
- }
-
- var connectionInfo = SshHosts.GetConnection(name);
- using var sshClient = new SshClient(connectionInfo);
- if (!sshClient.IsConnected)
- await sshClient.ConnectAsync(ct);
- connectionTask.Increment(33);
-
- var winC = sshClient.RunCommand("cmd /c ver");
- var othC = sshClient.RunCommand("uname -s");
-
- var os = (winC.ExitStatus, othC.ExitStatus) switch {
- (0, _) => "windows",
- (_, 0) => "linux",
- _ => "unknown"
- };
-
- string remoteDirectory;
- string packageFileDirectory;
- if (os == "windows") {
- var userDirC = sshClient.RunCommand("cmd /c echo %USERPROFILE%");
- if (userDirC.ExitStatus != 0) {
- ShowError(Exceptions.failed_to_prepare_server_directory, "n/a", name, os, userDirC.Result);
- return;
- }
-
- var userDir = userDirC.Result.Trim();
- remoteDirectory = RemotePath.Combine(RemoteOs.Windows,userDir, "dotnet-packages");
- packageFileDirectory = RemotePath.Combine(RemoteOs.Windows, remoteDirectory, Path.GetFileName(package));
-
- var mkdirC = sshClient.RunCommand($"cmd /c if not exist \"{remoteDirectory}\" mkdir \"{remoteDirectory}\"");
- if (mkdirC.ExitStatus != 0) {
- ShowError(Exceptions.failed_to_prepare_server_directory, remoteDirectory, name, os, mkdirC.Result);
- return;
- }
- }
- else if (os == "linux") {
- var homeDirC = sshClient.RunCommand("printf %s \"$HOME\"");
- if (homeDirC.ExitStatus != 0) {
- ShowError(Exceptions.failed_to_prepare_server_directory, "n/a", name, os, homeDirC.Result);
- return;
- }
- var homeDir = homeDirC.Result.Trim(); // no CRLF on unix, but Trim() is safest
- remoteDirectory = RemotePath.Combine(RemoteOs.Unix, homeDir, ".dotnet-packages");
- packageFileDirectory = RemotePath.Combine(RemoteOs.Unix, remoteDirectory, Path.GetFileName(package));
-
- // Use -p and single quotes to handle spaces safely
- var mkdirC = sshClient.RunCommand($"mkdir -p '{remoteDirectory}'");
- if (mkdirC.ExitStatus != 0) {
- ShowError(Exceptions.failed_to_prepare_server_directory, remoteDirectory, name, os, mkdirC.Result);
- return;
- }
- }
- else {
- ShowError(Exceptions.failed_to_prepare_server_directory, "n/a", name, os, "Unsupported OS");
- return;
- }
- connectionTask.Increment(33);
-
- sshClient.Disconnect();
-
- using var client = new SftpClient(connectionInfo);
- if (!client.IsConnected)
- await client.ConnectAsync(ct);
- connectionTask.Increment(33);
- connectionTask.StopTask();
-
- await using var writer = client.OpenWrite(packageFileDirectory);
- byte[] buffer = new byte[bufferSize];
- int read;
- do {
- read = await reader.ReadAsync(buffer, ct);
- writer.Write(buffer, 0, read);
- task.Increment(read);
- } while (read > 0);
- }
-
- else if (dest == "github") {
- var p = Process.Start(new ProcessStartInfo() {
- FileName = "dotnet",
- Arguments = $"nuget push {package} --source github",
- WorkingDirectory = Environment.CurrentDirectory,
- UseShellExecute = false,
- RedirectStandardOutput = !Verbose,
- RedirectStandardError = !Verbose
- });
-
- if (p == null) {
- ShowError(Exceptions.generic_error.EscapeMarkup());
- }
-
- task.Increment(size / 2);
- if (p != null)
- await p.WaitForExitAsync(ct);
- if (p?.ExitCode != 0) {
- ShowError(Exceptions.dotnet_nuget_push_failure, p.ExitCode);
- }
- task.Increment(size / 2);
- }
-
- task.StopTask();
- });
- });
- }
- finally {
- try {
- Directory.Delete(outDir, true);
- }
- catch (Exception e) {
- ShowError(string.Format(Exceptions.failed_to_clean_up.EscapeMarkup(), outDir.EscapeMarkup(), e.ToString().EscapeMarkup()));
- }
- }
- AnsiConsole.MarkupLine("Completed processing of all destinations.");
- AnsiConsole.MarkupLine("Example usage:\n\t ".EscapeMarkup(), packageId, version);
- }
-
- ///
- /// Updates the version string by applying the specified operation to the major, minor, and patch components of the version.
- ///
- /// The current version string in the format "major.minor.patch[-tag]".
- /// The value to apply to the patch component.
- /// The value to apply to the minor component.
- /// The value to apply to the major component.
- /// A function that defines the adjustment operation to be performed on each version component.
- /// A new version string with the updated major, minor, and patch components, preserving any existing tag.
- /// Thrown if the version string is not in the correct format.
- private static string ChangeVersion(string version, int patch, int minor, int major,
- Func operation) {
- string[] split = version.Split('.');
- if (split.Length != 3) {
- throw new Exception(string.Format(Exceptions.version_string_not_formatted_correctly, version));
- }
-
- string tag = "";
- if (split[2].Contains('-')) {
- var split2 = split[2].Split('-');
- split[2] = split2[0];
- tag = "-" + split2[1];
- }
-
- if (split.Any(x => !int.TryParse(x, out _)))
- throw new Exception(string.Format(Exceptions.version_string_not_formatted_correctly, version));
-
- int[] parsedVersion = split.Select(int.Parse).ToArray();
-
- return
- $"{operation(parsedVersion[0], major)}.{operation(parsedVersion[1], minor)}.{operation(parsedVersion[2], patch)}{tag}";
- }
-
- private static void ShowError(string message, params object[] args) {
- AnsiConsole.MarkupLine($"[bold red]{message}[/]", args);
- }
-
- private static void ShowHelp() {
- AnsiConsole.Markup(("Usage: publish overwrite|increment [patch|minor|major] destinations [flags]\n" +
- "\t if mode: overwrite destinations [flags]\n" +
- "\t if mode: increment patch|minor|major [flags]\n").EscapeMarkup());
-
- }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/Project.cs b/aeqw89.tools.Publish/Project.cs
deleted file mode 100644
index c5d2e73..0000000
--- a/aeqw89.tools.Publish/Project.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal class Project {
- public string Path { get; }
- private XmlDocument Document { get; }
- public List PropertyGroups { get; }
- public List ItemGroups { get; }
-
- private Project(string path, XmlDocument doc) {
- Path = path;
- Document = doc;
-
- // Build PropertyGroups
- PropertyGroups = doc.DocumentElement!
- .SelectNodes("./PropertyGroup")!
- .OfType()
- .Select(e => new PropertyGroup(e))
- .ToList();
-
- // Build ItemGroups (+ their Items)
- ItemGroups = doc.DocumentElement!
- .SelectNodes("./ItemGroup")!
- .OfType()
- .Select(e => new ItemGroup(e))
- .ToList();
-
- // Ensure at least one ItemGroup exists (some csprojs omit it until first item is added)
- if (ItemGroups.Count == 0) {
- var ig = doc.CreateElement("ItemGroup", doc.DocumentElement!.NamespaceURI);
- doc.DocumentElement!.AppendChild(ig);
- ItemGroups.Add(new ItemGroup((XmlElement)ig));
- }
- }
-
- public static Project Load(string path) {
- var doc = new XmlDocument();
- doc.PreserveWhitespace = false;
- doc.Load(path);
- return new Project(path, doc);
- }
-
- public void Save() {
- var settings = new XmlWriterSettings {
- Indent = true,
- IndentChars = " ",
- NewLineChars = Environment.NewLine,
- NewLineHandling = NewLineHandling.Replace
- };
- using var writer = XmlWriter.Create(Path, settings);
- Document.Save(writer);
- }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/ProjectFile.cs b/aeqw89.tools.Publish/ProjectFile.cs
deleted file mode 100644
index 20f1270..0000000
--- a/aeqw89.tools.Publish/ProjectFile.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-// -------------------------------------------------------------------------------------------------
-// Minimal replacements for VsTools.Projects so ProjectFile can keep its public surface intact
-// -------------------------------------------------------------------------------------------------
-
-// -------------------------------------------------------------------------------------------------
-// Your original public surface, now backed by System.Xml
-// -------------------------------------------------------------------------------------------------
-
-internal class ProjectFile {
- public Project Project { get; private set; }
- public string Path { get; private set; }
- private PropertyGroup MainPropertyGroup { get; set; }
-
- private ProjectFile(Project project, string path) {
- MainPropertyGroup = project.PropertyGroups.FirstOrDefault()!;
- Project = project;
- Path = path;
- }
-
- public static bool TryLoad(string path, [NotNullWhen(true)] out ProjectFile? projectFile, [NotNullWhen(false)] out string? error) {
- projectFile = null;
- error = null;
-
- if (!path.EndsWith(".csproj")) {
- if (!Directory.Exists(path)) {
- error = Exceptions.tried_loading_non_csproj_file;
- return false;
- }
-
- var csproj = Directory.EnumerateFiles(path, "*.csproj", SearchOption.TopDirectoryOnly).ToArray();
- if (csproj.Length == 0) {
- error = Exceptions.no_project_in_directory;
- return false;
- }
-
- if (csproj.Length > 1) {
- error = Exceptions.found_multiple_csproj;
- return false;
- }
-
- path = csproj[0];
- }
-
- try {
- projectFile = new ProjectFile(Project.Load(path), path);
- return true;
- }
- catch (Exception e) {
- error = string.Format(Exceptions.generic_error, e);
- return false;
- }
- }
-
- public void Backup(string? backupPath = null) {
- backupPath ??= Path + ".bak";
- File.Copy(Path, backupPath, true);
- }
-
- public string GetDefaultBackupLocation() => Path + ".bak";
-
- public bool Restore(string? backupPath = null) {
- backupPath ??= GetDefaultBackupLocation();
- if (!File.Exists(backupPath)) return false;
- File.Copy(backupPath, Path, true);
- return true;
- }
-
- public void Save() {
- // Check for empty property or item groups
- foreach (var ig in Project.ItemGroups.ToList().Where(ig => ig.Items.Count == 0)) {
- ig.Remove();
- }
- foreach (var pg in Project.PropertyGroups.ToList().Where(pg => pg.Count == 0)) {
- pg.Remove();
- }
-
- Project.Save();
- }
-
- public bool TryRepair([NotNullWhen(false)] out string? error) {
- // Ensure we have a PropertyGroup with TargetFramework
- if (MainPropertyGroup?.HasProperty("TargetFramework") != true) {
- if (!Project.PropertyGroups.Any(x => x.HasProperty("TargetFramework"))) {
- error = string.Format(Exceptions.project_file_irreparable, Path, "TargetFramework");
- return false;
- }
- MainPropertyGroup = Project.PropertyGroups.First(x => x.HasProperty("TargetFramework"));
- }
-
- List failed = [];
-
- void set(string key, string value, bool required = false) {
- if (!MainPropertyGroup.HasProperty(key) || string.IsNullOrEmpty(MainPropertyGroup.GetProperty(key))) {
- if (required) {
- failed.Add(key);
- return;
- }
- MainPropertyGroup.SetProperty(key, value);
- }
- }
-
- set("Version", "1.0.0");
- set("Title", System.IO.Path.GetFileNameWithoutExtension(Path));
- set("Authors", "");
- set("Company", "");
- set("Description", "");
- set("PackageProjectUrl", "", required: false);
- set("RepositoryUrl", "", required: true);
- set("PackageId", "", required: true);
-
- if (failed.Count > 0) {
- error = string.Format(Exceptions.project_file_irreparable, Path, string.Join(", ", failed));
- return false;
- }
-
- error = null;
- return true;
- }
-
- public List GetPackageReferences() {
- return Project.ItemGroups
- .SelectMany(g => g.Items)
- .Where(i => i.ElementName == "PackageReference")
- .OfType()
- .ToList();
- }
-
- public List GetProjectReferences() {
- return Project.ItemGroups
- .SelectMany(g => g.Items)
- .Where(i => i.ElementName == "ProjectReference")
- .OfType()
- .ToList();
- }
-
- public List GetPackageDependencies() {
- return Project.ItemGroups
- .SelectMany(g => g.Items)
- .Where(i => i.ElementName == "Content")
- .OfType()
- .ToList();
- }
-
- private void CreateOrUpdateChild(Item item, string childName, string value) {
- var child = item.Node.SelectSingleNode(childName) as XmlElement;
- if (child != null) {
- child.InnerText = value;
- return;
- }
-
- child = item.Node.OwnerDocument!.CreateElement(childName, item.Node.NamespaceURI);
- child.InnerText = value;
- item.Node.AppendChild(child);
- }
-
- public string GetPackageId() {
- return MainPropertyGroup.GetProperty("PackageId");
- }
-
- public void SetPrivateAssets(Item item, PrivateAssetsValue value) {
- if (value == PrivateAssetsValue.None) {
- var child = item.Node.SelectSingleNode("./PrivateAssets") as XmlElement;
- if (child != null)
- item.Node.RemoveChild(child);
- return;
- }
-
- CreateOrUpdateChild(item, "PrivateAssets", value.ToString().ToLowerInvariant());
- }
-
- public void SetTransitive(Item item, bool value)
- => CreateOrUpdateChild(item, "Transitive", value.ToString().ToLowerInvariant());
-
- public bool IsTransitive(Item item) {
- var transitive = item.Node.SelectSingleNode("./Transitive") as XmlElement;
- return transitive?.InnerText == "true";
- }
-
- public string GetAbsoluteIncludePath(Item item) {
- return System.IO.Path.GetFullPath(item.Include);
- }
-
- public Item AddPackage(Item otherPackage) {
- var allItems = Project.ItemGroups.SelectMany(x => x.Items);
- var existing = allItems.FirstOrDefault(x =>
- x.ElementName == "PackageReference" && x.Include == otherPackage.Include);
- if (existing != null) return existing;
-
- var itemGroup = Project.ItemGroups.First();
- // Import the original XmlElement to preserve Version (attr or child) and any metadata
- itemGroup.Add(otherPackage);
- return itemGroup.Items.Last();
- }
-
-
- public bool RemovePackage(Item otherPackage) {
- var grp = Project.ItemGroups
- .FirstOrDefault(g => g.Items.Any(y => y.ElementName == "PackageReference" && y.Include == otherPackage.Include));
-
- var pkg = grp?.Items.FirstOrDefault(x => x.ElementName == otherPackage.ElementName && x.Include == otherPackage.Include);
- if (pkg == null) return false;
-
- pkg.Node.ParentNode!.RemoveChild(pkg.Node);
- grp!.Items.Remove(pkg);
- return true;
- }
-
- public string GetVersion() => MainPropertyGroup.GetProperty("Version");
-
- public void SetVersion(string version) => MainPropertyGroup.SetProperty("Version", version);
-}
diff --git a/aeqw89.tools.Publish/ProjectReference.cs b/aeqw89.tools.Publish/ProjectReference.cs
deleted file mode 100644
index acf6799..0000000
--- a/aeqw89.tools.Publish/ProjectReference.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal sealed class ProjectReference : Item {
- public ProjectReference(XmlElement node) : base(node) { }
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/PropertyGroup.cs b/aeqw89.tools.Publish/PropertyGroup.cs
deleted file mode 100644
index 56f966f..0000000
--- a/aeqw89.tools.Publish/PropertyGroup.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Xml;
-
-namespace aeqw89.tools.Publish;
-
-internal class PropertyGroup {
- private readonly XmlElement _element;
- public PropertyGroup(XmlElement element) => _element = element;
-
- public bool HasProperty(string name) => _element.SelectSingleNode($"./{name}") is XmlElement;
-
- public string GetProperty(string name) {
- var node = _element.SelectSingleNode($"./{name}") as XmlElement;
- return node?.InnerText ?? string.Empty;
- }
-
- public void SetProperty(string name, string value) {
- var node = _element.SelectSingleNode($"./{name}") as XmlElement;
- if (node == null) {
- node = _element.OwnerDocument!.CreateElement(name, _element.NamespaceURI);
- _element.AppendChild(node);
- }
- node.InnerText = value ?? string.Empty;
- }
-
- public int Count => _element.ChildNodes.OfType().Count();
-
- public void Remove() => _element.ParentNode!.RemoveChild(_element);
-}
\ No newline at end of file
diff --git a/aeqw89.tools.Publish/RemotePath.cs b/aeqw89.tools.Publish/RemotePath.cs
deleted file mode 100644
index 6f9d29b..0000000
--- a/aeqw89.tools.Publish/RemotePath.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Required namespaces: System, System.Linq, System.Text.RegularExpressions
-
-using System.Text.RegularExpressions;
-
-namespace aeqw89.tools.Publish;
-
-public enum RemoteOs { Windows, Unix }
-
-public static partial class RemotePath
-{
- public static string Combine(RemoteOs os, params string[] parts)
- {
- if (parts == null || parts.Length == 0) return string.Empty;
-
- // Normalize null/empty segments and trim whitespace
- var cleaned = parts.Where(p => !string.IsNullOrWhiteSpace(p))
- .Select(p => p.Trim())
- .ToArray();
- if (cleaned.Length == 0) return string.Empty;
-
- return os == RemoteOs.Windows
- ? CombineWindows(cleaned)
- : CombineUnix(cleaned);
- }
-
- private static string CombineUnix(string[] parts)
- {
- // Keep a single leading '/' if the first segment is rooted
- bool rooted = parts[0].StartsWith("/", StringComparison.Ordinal);
- var body = parts.Select((p, i) =>
- {
- var s = p.Replace("\\", "/");
- // Trim both ends except preserve leading '/' only for first segment
- if (i == 0)
- return s.TrimEnd('/');
- return s.Trim('/'); // internal segments never carry separators
- })
- .Where(s => s.Length > 0)
- .ToArray();
-
- var joined = string.Join("/", body);
- return rooted ? (joined.StartsWith("/") ? joined : "/" + joined) : joined;
- }
-
- private static string CombineWindows(string[] parts)
- {
- // Windows separators are backslashes for cmd.exe/PowerShell paths.
- // Preserve drive letters like "C:" and UNC roots like "\\server".
- var first = parts[0].Replace("/", "\\").Trim();
- var rest = parts.Skip(1)
- .Select(p => p.Replace("/", "\\").Trim('\\'))
- .Where(s => s.Length > 0)
- .ToArray();
-
- // Detect UNC root (\\server\share...) or device prefix (\\?\ or \\.\)
- bool isUncOrDevice = first.StartsWith(@"\\", StringComparison.Ordinal);
- bool isDrive = IsDrive().IsMatch(first);
-
- if (isUncOrDevice)
- {
- // Keep exactly two leading backslashes; trim trailing ones
- first = @"\\" + first.TrimStart('\\').TrimEnd('\\');
- }
- else if (isDrive)
- {
- // Normalize "C:" or "C:\" to "C:\"
- first = first.Length == 2 ? first + "\\" : first;
- }
- else
- {
- // For relative first segment, strip surrounding slashes
- first = first.Trim('\\');
- }
-
- string joined = rest.Length > 0
- ? first + (first.EndsWith("\\") ? "" : "\\") + string.Join("\\", rest)
- : first;
-
- // Collapse any accidental doubles that can appear from user input (but keep UNC prefix)
- if (!joined.StartsWith(@"\\"))
- joined = Collapse().Replace(joined, @"\");
-
- return joined;
- }
-
- [System.Text.RegularExpressions.GeneratedRegex(@"^[A-Za-z]:\\?$")]
- private static partial System.Text.RegularExpressions.Regex IsDrive();
- [GeneratedRegex(@"\\{2,}")]
- private static partial Regex Collapse();
-}
diff --git a/aeqw89.tools.Publish/SshHosts.cs b/aeqw89.tools.Publish/SshHosts.cs
deleted file mode 100644
index ff6ada2..0000000
--- a/aeqw89.tools.Publish/SshHosts.cs
+++ /dev/null
@@ -1,423 +0,0 @@
-// Required namespaces:
-// System, System.IO, System.Linq, System.Text, System.Text.RegularExpressions, System.Collections.Generic, Renci.SshNet
-
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace aeqw89.tools.Publish;
-
-public record Host(
- string Name,
- string Hostname,
- string User,
- string Password,
- int Port,
- List IdentityFiles,
- Renci.SshNet.ProxyTypes? ProxyType,
- string? ProxyHost,
- int? ProxyPort,
- string? ProxyUser,
- string? ProxyPassword
-);
-
-public static class SshHosts {
- public static List Hosts { get; set; }
-
- static SshHosts() {
- Hosts = new List();
-
- var path = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
- ".ssh",
- "config"
- );
-
- if (!File.Exists(path)) return;
-
- var lines = File.ReadAllLines(path);
-
- string[]? currentNames = null;
- string? currentHostName = null;
- string? currentUser = null;
- string? currentPassword = null;
- int? currentPort = null;
- List? currentIdentityFiles = null;
-
- // Proxy (explicit)
- Renci.SshNet.ProxyTypes? currentProxyType = null;
- string? currentProxyHost = null;
- int? currentProxyPort = null;
- string? currentProxyUser = null;
- string? currentProxyPassword = null;
-
- // Proxy (derived from ProxyCommand)
- string? currentProxyCommand = null;
-
- void ResetBlock()
- {
- currentNames = null;
- currentHostName = null;
- currentUser = null;
- currentPassword = null;
- currentPort = null;
- currentIdentityFiles = null;
-
- currentProxyType = null;
- currentProxyHost = null;
- currentProxyPort = null;
- currentProxyUser = null;
- currentProxyPassword = null;
-
- currentProxyCommand = null;
- }
-
- void MaybeDeriveProxyFromProxyCommand()
- {
- if (string.IsNullOrWhiteSpace(currentProxyCommand)) return;
- if (currentProxyType != null && currentProxyHost != null && currentProxyPort != null) return;
-
- // Very common forms:
- // nc -x host:port -X 5 %h %p (SOCKS5)
- // nc -x host:port -X 4 %h %p (SOCKS4)
- // nc -x host:port %h %p (default: treat as SOCKS5)
- // nc -X connect -x host:port %h %p (HTTP CONNECT)
- // connect -S host:port %h %p (treat as SOCKS5)
- var s = currentProxyCommand;
-
- // host:port extraction
- var hp = Regex.Match(s, @"(?:(?:-x|-S)\s+|\s)([A-Za-z0-9.\-]+):(\d{1,5})");
- if (hp.Success) {
- currentProxyHost ??= hp.Groups[1].Value;
- if (int.TryParse(hp.Groups[2].Value, out var pp) && pp > 0 && pp <= 65535)
- currentProxyPort ??= pp;
- }
-
- // type extraction
- if (Regex.IsMatch(s, @"-X\s+5\b", RegexOptions.IgnoreCase))
- currentProxyType ??= Renci.SshNet.ProxyTypes.Socks5;
- else if (Regex.IsMatch(s, @"-X\s+4\b", RegexOptions.IgnoreCase))
- currentProxyType ??= Renci.SshNet.ProxyTypes.Socks4;
- else if (Regex.IsMatch(s, @"-X\s+connect\b", RegexOptions.IgnoreCase))
- currentProxyType ??= Renci.SshNet.ProxyTypes.Http;
- else if (s.Contains("connect ", System.StringComparison.OrdinalIgnoreCase))
- currentProxyType ??= Renci.SshNet.ProxyTypes.Http;
- else if (s.Contains("nc ", System.StringComparison.OrdinalIgnoreCase))
- currentProxyType ??= Renci.SshNet.ProxyTypes.Socks5;
-
- // If we still don't have enough, leave proxy unset.
- }
-
- void Flush()
- {
- if (currentNames == null || currentNames.Length == 0) {
- ResetBlock();
- return;
- }
-
- // Try deriving proxy from ProxyCommand if explicit values weren't set
- MaybeDeriveProxyFromProxyCommand();
-
- foreach (var n in currentNames) {
- var hn = string.IsNullOrWhiteSpace(currentHostName) ? n : currentHostName!;
- var idFiles = new List();
- if (currentIdentityFiles != null) {
- foreach (var f in currentIdentityFiles) idFiles.Add(ExpandPath(f));
- }
-
- Hosts.Add(new Host(
- Name: n,
- Hostname: hn,
- User: currentUser ?? string.Empty,
- Password: currentPassword ?? string.Empty,
- Port: currentPort ?? 22,
- IdentityFiles: idFiles,
- ProxyType: currentProxyType,
- ProxyHost: currentProxyHost,
- ProxyPort: currentProxyPort,
- ProxyUser: currentProxyUser,
- ProxyPassword: currentProxyPassword
- ));
- }
-
- ResetBlock();
- }
-
- foreach (var raw in lines) {
- var line = raw.Trim();
- if (line.Length == 0 || line.StartsWith("#")) continue;
-
- int idx = line.IndexOfAny(new[] { ' ', '\t' });
- string key, value;
- if (idx < 0) {
- key = line;
- value = string.Empty;
- } else {
- key = line[..idx];
- value = line[idx..].Trim();
- }
-
- switch (key.ToLowerInvariant()) {
- case "host":
- Flush();
- currentNames = SplitArgs(value).ToArray();
- break;
-
- case "hostname":
- if (currentNames != null) currentHostName = value;
- break;
-
- case "user":
- if (currentNames != null) currentUser = value;
- break;
-
- case "password":
- // Non-standard; supported here as a convenience (used for password auth or key passphrase)
- if (currentNames != null) currentPassword = value;
- break;
-
- case "port":
- if (currentNames != null && int.TryParse(value, out var p) && p > 0 && p <= 65535)
- currentPort = p;
- break;
-
- case "identityfile":
- if (currentNames != null) {
- currentIdentityFiles ??= new List();
- foreach (var f in SplitArgs(value)) {
- if (!string.IsNullOrWhiteSpace(f)) currentIdentityFiles.Add(f);
- }
- }
- break;
-
- // --- Proxy settings (explicit custom keys) ---
- case "proxytype":
- if (currentNames != null) {
- var v = value.ToLowerInvariant();
- currentProxyType =
- v switch {
- "socks5" or "socks" or "socks5h" => Renci.SshNet.ProxyTypes.Socks5,
- "socks4" => Renci.SshNet.ProxyTypes.Socks4,
- "http" or "https" or "connect" => Renci.SshNet.ProxyTypes.Http,
- _ => currentProxyType
- };
- }
- break;
-
- case "proxyhost":
- if (currentNames != null) currentProxyHost = value;
- break;
-
- case "proxyport":
- if (currentNames != null && int.TryParse(value, out var prxP) && prxP > 0 && prxP <= 65535)
- currentProxyPort = prxP;
- break;
-
- case "proxyuser":
- if (currentNames != null) currentProxyUser = value;
- break;
-
- case "proxypassword":
- if (currentNames != null) currentProxyPassword = value;
- break;
-
- // --- OpenSSH-style hints we try to interpret ---
- case "proxycommand":
- if (currentNames != null) currentProxyCommand = value;
- break;
-
- // (Note: ProxyJump is non-trivial to replicate in SSH.NET; not parsed here.)
-
- default:
- break;
- }
- }
-
- Flush();
- }
-
- // Builds a ConnectionInfo from a parsed host, ensuring all ~/.ssh private keys are tried.
- private static Renci.SshNet.ConnectionInfo BuildConnection(Host h) {
- var authMethods = new List();
-
- // 1) Collect candidate key file paths: from config + everything that looks like a private key in ~/.ssh
- var keyPaths = new HashSet(StringComparer.OrdinalIgnoreCase);
-
- foreach (var f in h.IdentityFiles)
- if (!string.IsNullOrWhiteSpace(f))
- keyPaths.Add(f);
-
- foreach (var f in EnumerateAllSshPrivateKeys())
- keyPaths.Add(f);
-
- // 2) Load keys (try with passphrase, then without)
- var pkFiles = new List();
- foreach (var p in keyPaths) {
- if (!File.Exists(p)) continue;
- try {
- if (!string.IsNullOrEmpty(h.Password)) {
- try {
- pkFiles.Add(new Renci.SshNet.PrivateKeyFile(p, h.Password));
- continue;
- }
- catch { /* fall through to try without passphrase */
- }
- }
-
- pkFiles.Add(new Renci.SshNet.PrivateKeyFile(p));
- }
- catch { /* skip unreadable/unparsable key */
- }
- }
-
- if (pkFiles.Count > 0)
- authMethods.Add(new Renci.SshNet.PrivateKeyAuthenticationMethod(h.User, pkFiles.ToArray()));
-
- // 3) Optional password auth (remote account password)
- if (!string.IsNullOrEmpty(h.Password))
- authMethods.Add(new Renci.SshNet.PasswordAuthenticationMethod(h.User, h.Password));
-
- if (authMethods.Count == 0)
- throw new InvalidOperationException($"No authentication methods available for host '{h.Name}'.");
-
- // 4) Proxy-aware ConnectionInfo
- if (h.ProxyType.HasValue && !string.IsNullOrWhiteSpace(h.ProxyHost) && h.ProxyPort.HasValue) {
- return new Renci.SshNet.ConnectionInfo(
- h.Hostname,
- h.Port,
- h.User,
- h.ProxyType.Value,
- h.ProxyHost!,
- h.ProxyPort.Value,
- h.ProxyUser,
- h.ProxyPassword,
- authMethods.ToArray()
- );
- }
-
- return new Renci.SshNet.ConnectionInfo(h.Hostname, h.Port, h.User, authMethods.ToArray());
- }
-
- // Enumerate everything in ~/.ssh that *looks* like a private key.
- // Skips obvious non-keys like *.pub, known_hosts, config, and directories.
- private static IEnumerable EnumerateAllSshPrivateKeys() {
- var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- var sshDir = Path.Combine(home, ".ssh");
- if (!Directory.Exists(sshDir)) yield break;
-
- // Common private key basenames to prioritize
- var preferred = new HashSet(StringComparer.OrdinalIgnoreCase) {
- "id_rsa", "id_ecdsa", "id_ed25519", "id_dsa"
- };
-
- // First yield preferred names if present
- foreach (var name in preferred) {
- var p = Path.Combine(sshDir, name);
- if (File.Exists(p)) yield return p;
- }
-
- // Then yield everything else that looks like a key
- foreach (var file in Directory.EnumerateFiles(sshDir)) {
- var name = Path.GetFileName(file);
-
- // Skip ones we already yielded
- if (preferred.Contains(name)) continue;
-
- // Exclude common non-key files and public keys
- if (name.EndsWith(".pub", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.Equals("config", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.Equals("known_hosts", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.Equals("authorized_keys", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.EndsWith(".crt", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.EndsWith(".csr", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.EndsWith(".pem.pub", StringComparison.OrdinalIgnoreCase)) continue; // guard for odd combos
- if (name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase)) continue;
- if (name.EndsWith(".conf", StringComparison.OrdinalIgnoreCase)) continue;
-
- // Heuristic: accept files with no extension, or with .key/.pem
- var ext = Path.GetExtension(name);
- if (string.IsNullOrEmpty(ext) ||
- ext.Equals(".key", StringComparison.OrdinalIgnoreCase) ||
- ext.Equals(".pem", StringComparison.OrdinalIgnoreCase)) {
- yield return file;
- }
- }
- }
-
-
- public static Host Get(string name) {
- for (int i = 0; i < Hosts.Count; i++) {
- if (string.Equals(Hosts[i].Name, name, StringComparison.OrdinalIgnoreCase)) {
- return Hosts[i];
- }
- }
- throw new KeyNotFoundException($"SSH host '{name}' not found.");
- }
-
- public static bool TryGetHost(string name, out Host host) {
- for (int i = 0; i < Hosts.Count; i++) {
- if (string.Equals(Hosts[i].Name, name, StringComparison.OrdinalIgnoreCase)) {
- host = Hosts[i];
- return true;
- }
- }
- host = default!;
- return false;
- }
-
- public static Renci.SshNet.ConnectionInfo GetConnection(string name)
- {
- var h = Get(name);
- return BuildConnection(h);
- }
-
- public static bool TryGetConnection(string name, out Renci.SshNet.ConnectionInfo connectionInfo)
- {
- if (TryGetHost(name, out var h)) {
- try {
- connectionInfo = BuildConnection(h);
- return true;
- } catch {
- // If auth material is unusable, return false.
- }
- }
- connectionInfo = default!;
- return false;
- }
-
- // --- Helpers ---
-
- // Splits a value into whitespace-delimited tokens while respecting double/single quotes.
- static IEnumerable SplitArgs(string input)
- {
- if (string.IsNullOrWhiteSpace(input)) yield break;
-
- bool inSingle = false, inDouble = false;
- var sb = new StringBuilder();
-
- for (int i = 0; i < input.Length; i++) {
- char c = input[i];
-
- if (c == '"' && !inSingle) { inDouble = !inDouble; continue; }
- if (c == '\'' && !inDouble) { inSingle = !inSingle; continue; }
-
- if (!inSingle && !inDouble && char.IsWhiteSpace(c)) {
- if (sb.Length > 0) { yield return sb.ToString(); sb.Clear(); }
- } else {
- sb.Append(c);
- }
- }
- if (sb.Length > 0) yield return sb.ToString();
- }
-
- // Expands leading "~" to user home. Leaves %h, %r, etc. untouched.
- static string ExpandPath(string p)
- {
- if (string.IsNullOrEmpty(p)) return p;
- if (p == "~") return Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- if (p.StartsWith("~/")) {
- var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- return Path.Combine(home, p[2..]);
- }
- return p;
- }
-}
diff --git a/aeqw89.tools.Publish/aeqw89.tools.Publish.csproj b/aeqw89.tools.Publish/aeqw89.tools.Publish.csproj
deleted file mode 100644
index 26c14ea..0000000
--- a/aeqw89.tools.Publish/aeqw89.tools.Publish.csproj
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
- Exe
- net9.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
- ResXFileCodeGenerator
- Exceptions.Designer.cs
-
-
-
-
-
- True
- True
- Exceptions.resx
-
-
-
-
diff --git a/aeqw89.tools.Publish/bin/Debug/net9.0/BouncyCastle.Cryptography.dll b/aeqw89.tools.Publish/bin/Debug/net9.0/BouncyCastle.Cryptography.dll
deleted file mode 100644
index bf1a8a176befe550e2d81e3916cb200077a65ca8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4870808
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