diff --git a/.gitattributes b/.gitattributes
index 06ec582cb..fb2ccc79f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1 @@
-src/wingetui/choco-cli/** linguist-vendored
-src/wingetui/ExternalLibraries/** linguist-vendored
\ No newline at end of file
+src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/** linguist-vendored
\ No newline at end of file
diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml
index 4d34a1217..26cfa365b 100644
--- a/.github/workflows/dotnet-desktop.yml
+++ b/.github/workflows/dotnet-desktop.yml
@@ -1,11 +1,10 @@
-name: Build
+name: Test and Build
on:
pull_request:
branches: [ "main" ]
workflow_dispatch:
-
jobs:
build:
@@ -13,7 +12,7 @@ jobs:
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
steps:
- - name: Checkout
+ - name: Checkout the repository
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -24,28 +23,17 @@ jobs:
with:
dotnet-version: 8.0.x
- - name: Install winget
+ - name: Install WinGet
uses: Cyberboss/install-winget@v1
-
- # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- - name: Setup MSBuild.exe
- uses: microsoft/setup-msbuild@v2.0.0
-
- # Execute all unit tests in the solution
- # - name: Execute unit tests
- # run: dotnet test
-
- # Restore the application to populate the obj folder with RuntimeIdentifiers
-
- - name: Setup App Sdk
+ - name: Run Tests
run: |
- cd InstallerExtras
- ./appsdk.exe
+ cd src
+ dotnet test -v q --nologo
cd ..
- - name: build and run
+ - name: Build solution
run: |
- mkdir out
- msbuild src/UniGetUI.sln /noLogo /property:Configuration=Release /property:Platform=x64 /restore:True /interactive:False /property:OutputPath=.\out
- exit $LASTEXITCODE
+ cd src
+ dotnet publish -v q UniGetUI.sln /noLogo /restore:True /interactive:False
+ exit $LASTEXITCODE
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b45c8f383..3f049dfa3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,9 +32,20 @@ src/packages/
src/UniGetUI/bin
src/UniGetUI/obj
-
src/WindowsPackageManager.Interop/bin
src/WindowsPackageManager.Interop/obj
+src/WindowsPackageManager.Interop/out
+src/WindowsPackageManager.Interop/outpublish
+
+src/UniGetU*/bin
+src/UniGetU*/obj
+src/UniGetU*/out
+src/UniGetU*/outpublish
+
+src/ExternalLibraries.*/bin
+src/ExternalLibraries.*/obj
+src/ExternalLibraries.*/out
+src/ExternalLibraries.*/outpublish
src/.vs
src/.vscode
@@ -65,3 +76,5 @@ src/UniGetUI/choco-cli/redirects/cup.exe.ignore
src/UniGetUI/choco-cli/bin/ssh-copy-id.exe
src/UniGetUI/choco-cli/extensions/chocolatey-visualstudio/
src/UniGetUI/choco-cli/extensions/chocolatey-dotnetfx/
+
+*.user
diff --git a/WingetUI.iss b/WingetUI.iss
index c05a66952..316d6ff47 100644
--- a/WingetUI.iss
+++ b/WingetUI.iss
@@ -1,7 +1,7 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
-#define MyAppVersion "3.1.0-beta"
+#define MyAppVersion "3.1.0-alpha"
#define MyAppName "UniGetUI (formerly WingetUI)"
#define MyAppPublisher "Martí Climent"
#define MyAppURL "https://github.com/marticliment/WingetUI"
diff --git a/readme.md b/readme.md
index 576e20f85..3dd231cec 100644
--- a/readme.md
+++ b/readme.md
@@ -126,7 +126,7 @@ To translate WingetUI to other languages or to update an old translation, please
| English - English | 100% | [marticliment](https://github.com/marticliment), [ppvnf](https://github.com/ppvnf) |
| Spanish - Castellano | 100% | [apazga](https://github.com/apazga), [dalbitresb12](https://github.com/dalbitresb12), [evaneliasyoung](https://github.com/evaneliasyoung), [guplem](https://github.com/guplem), [JMoreno97](https://github.com/JMoreno97), [marticliment](https://github.com/marticliment), [rubnium](https://github.com/rubnium), [uKER](https://github.com/uKER) |
| Persian - فارسی | 66% | [Imorate](https://github.com/Imorate), [itsarian](https://github.com/itsarian), [Mahdi-Hazrati](https://github.com/Mahdi-Hazrati), [smsi2001](https://github.com/smsi2001) |
-| Finnish - Suomi | 43% | [simakuutio](https://github.com/simakuutio) |
+| Finnish - Suomi | 50% | [simakuutio](https://github.com/simakuutio) |
| French - Français | 100% | BreatFR, Evans Costa, [PikPakPik](https://github.com/PikPakPik), Rémi Guerrero, [W1L7dev](https://github.com/W1L7dev) |
| Hindi - हिंदी | 56% | [atharva_xoxo](https://github.com/atharva_xoxo), [satanarious](https://github.com/satanarious) |
| Croatian - Hrvatski | 60% | Stjepan Treger |
@@ -156,7 +156,7 @@ To translate WingetUI to other languages or to update an old translation, please
| Simplified Chinese (China) | 100% | Aaron Liu, adfnekc, [arthurfsy2](https://github.com/arthurfsy2), [bai0012](https://github.com/bai0012), BUGP Association, ciaran, CnYeSheng, Cololi, [FloatStream](https://github.com/FloatStream), [SpaceTimee](https://github.com/SpaceTimee), Yisme |
| Traditional Chinese (Taiwan) | 100% | Aaron Liu, CnYeSheng, Cololi, [Henryliu880922](https://github.com/Henryliu880922), [yrctw](https://github.com/yrctw) |
-Last updated: Fri May 17 00:11:37 2024
+Last updated: Sun May 19 14:36:17 2024
diff --git a/scripts/Languages/LangData.py b/scripts/Languages/LangData.py
index 40580c7fd..540c76ac7 100644
--- a/scripts/Languages/LangData.py
+++ b/scripts/Languages/LangData.py
@@ -9,29 +9,29 @@
import os
import json
-if os.path.exists("../src/UniGetUI/Assets/Data/Contributors.list"):
- f = open("../src/UniGetUI/Assets/Data/Contributors.list", "r", encoding="utf-8")
+if os.path.exists("../src/UniGetUI.Core.Data/Assets/Data/Contributors.list"):
+ f = open("../src/UniGetUI.Core.Data/Assets/Data/Contributors.list", "r", encoding="utf-8")
contributors = f.readlines()
else:
print("No contributors file!")
contributors = []
-if os.path.exists("../src/UniGetUI/Assets/Data/Translators.json"):
- f = open("../src/UniGetUI/Assets/Data/Translators.json", "r", encoding="utf-8")
+if os.path.exists("../src/UniGetUI.Core.LanguageEngine/Assets/Data/Translators.json"):
+ f = open("../src/UniGetUI.Core.LanguageEngine/Assets/Data/Translators.json", "r", encoding="utf-8")
languageCredits = json.load(f)
else:
print("No translators file!")
languageCredits = {}
-if os.path.exists("../src/UniGetUI/Assets/Data/TranslatedPercentages.json"):
- f = open("../src/UniGetUI/Assets/Data/TranslatedPercentages.json", "r", encoding="utf-8")
+if os.path.exists("../src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json"):
+ f = open("../src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json", "r", encoding="utf-8")
untranslatedPercentage = json.load(f)
else:
print("No translated percent file!")
untranslatedPercentage = {}
-if os.path.exists("../src/UniGetUI/Assets/Data/LanguagesReference.json"):
- f = open("../src/UniGetUI/Assets/Data/LanguagesReference.json", "r", encoding="utf-8")
+if os.path.exists("../src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json"):
+ f = open("../src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json", "r", encoding="utf-8")
languageReference = json.load(f)
else:
print("No translated percent file!")
@@ -88,7 +88,7 @@ def getMarkdownSupportLangs():
dir = os.path.dirname(__file__)
for lang, langName in languageReference.items():
- if (not os.path.exists(f"{dir}/../../src/UniGetUI/Assets/Languages/lang_{lang}.json")):
+ if (not os.path.exists(f"{dir}/../../src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_{lang}.json")):
continue
perc = untranslatedPercentage[lang] if (lang in untranslatedPercentage) else "100%"
diff --git a/scripts/apply_versions.py b/scripts/apply_versions.py
index a5ab0cf11..1c5a8d7fd 100644
--- a/scripts/apply_versions.py
+++ b/scripts/apply_versions.py
@@ -24,14 +24,15 @@ def fileReplaceLinesWith(filename: str, list: dict[str, str], encoding="utf-8"):
f.write(data)
f.truncate()
- fileReplaceLinesWith("src/UniGetUI/Core/Data/Core.cs", {
+ fileReplaceLinesWith("src/UniGetUI.Core.Data/Core.cs", {
" public static string VersionName = ": f" \"{versionName}\"; // Do not modify this line, use file scripts/apply_versions.py\n",
" public static double VersionNumber = ": f" {versionCode}; // Do not modify this line, use file scripts/apply_versions.py\n",
}, encoding="utf-8-sig")
- fileReplaceLinesWith("src/UniGetUI/UniGetUI.csproj", {
+ fileReplaceLinesWith("src/Solution.props", {
"\t": f"{versionISS}\n",
"\t": f"{versionName}\n",
+ "\t": f"{versionName}\n",
}, encoding="utf-8-sig")
fileReplaceLinesWith("WingetUI.iss", {
diff --git a/scripts/download_translations.py b/scripts/download_translations.py
index 7e7d6e7e9..69dd7ae68 100644
--- a/scripts/download_translations.py
+++ b/scripts/download_translations.py
@@ -29,7 +29,7 @@
print("nocommit")
print(sys.argv[1])
- os.chdir(os.path.normpath(os.path.join(root_dir, "src/UniGetUI/Assets/Languages")))
+ os.chdir(os.path.normpath(os.path.join(root_dir, "src/UniGetUI.Core.LanguageEngine/Assets/Languages")))
print()
print("-------------------------------------------------------")
@@ -133,13 +133,13 @@
# languageCredits = {json.dumps(langCredits, indent=2, ensure_ascii=False)}
# """
- with open(os.path.join(root_dir, "src/UniGetUI/Assets/Data/Translators.json"), "w", encoding="utf-8") as f:
+ with open(os.path.join(root_dir, "src/UniGetUI.Core.LanguageEngine/Assets/Data/Translators.json"), "w", encoding="utf-8") as f:
f.write(json.dumps(langCredits, indent=2, ensure_ascii=False))
- with open(os.path.join(root_dir, "src/UniGetUI/Assets/Data/TranslatedPercentages.json"), "w", encoding="utf-8") as f:
+ with open(os.path.join(root_dir, "src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json"), "w", encoding="utf-8") as f:
f.write(json.dumps(langPerc, indent=2, ensure_ascii=False))
- # translations_filepath = os.path.normpath(os.path.join(root_dir, "UniGetUI/Core/Data/Translations.py"))
+ # translations_filepath = os.path.normpath(os.path.join(root_dir, "UniGetUI.Core.LanguageEngine/Core/Data/Translations.py"))
# with open(translations_filepath, "w", encoding="utf-8") as f:
# f.write(outputString.strip())
diff --git a/scripts/generate_json_from_excel.py b/scripts/generate_json_from_excel.py
index 4f22952c2..a02e41ab6 100644
--- a/scripts/generate_json_from_excel.py
+++ b/scripts/generate_json_from_excel.py
@@ -22,7 +22,7 @@
try:
workbook = xlrd.open_workbook('screenshot_database.xlsx')
except:
- os.system("python -m pip install xlrd==1.2.0")
+ os.system("python -m pip install xlrd==1.0.0")
import xlrd
workbook = xlrd.open_workbook('screenshot_database.xlsx')
diff --git a/scripts/get_contributors.py b/scripts/get_contributors.py
index 439be58f1..22540893d 100644
--- a/scripts/get_contributors.py
+++ b/scripts/get_contributors.py
@@ -35,7 +35,7 @@
# contributorsInfo = {json.dumps(contributorsInfo, indent=2, ensure_ascii=False)}
# """
-contributors_filepath = os.path.normpath(os.path.join(root_dir, "src/UniGetUI/Assets/Data/Contributors.list"))
+contributors_filepath = os.path.normpath(os.path.join(root_dir, "src/UniGetUI.Core.Data/Assets/Data/Contributors.list"))
with open(contributors_filepath, "w", encoding="utf-8") as f:
f.writelines(contributors)
diff --git a/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj b/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj
new file mode 100644
index 000000000..293f74341
--- /dev/null
+++ b/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj
@@ -0,0 +1,10 @@
+
+
+
+ net8.0
+ enable
+ enable
+ AnyCPU;x64;ARM64
+
+
+
diff --git a/src/UniGetUI/ExternalLibraries/Clipboard.cs b/src/ExternalLibraries.Clipboard/WindowsClipboard.cs
similarity index 91%
rename from src/UniGetUI/ExternalLibraries/Clipboard.cs
rename to src/ExternalLibraries.Clipboard/WindowsClipboard.cs
index 94e43e574..69773aa0a 100644
--- a/src/UniGetUI/ExternalLibraries/Clipboard.cs
+++ b/src/ExternalLibraries.Clipboard/WindowsClipboard.cs
@@ -1,25 +1,10 @@
-using System;
-using System.ComponentModel;
+using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
-using System.Threading;
-namespace UniGetUI.ExternalLibraries.Clipboard
+namespace ExternalLibraries.Clipboard
{
- public class Main
- {
- public static string? GetText()
- {
- return WindowsClipboard.GetText();
- }
-
- public static void SetText(string text)
- {
- WindowsClipboard.SetText(text);
- }
- }
-
- static class WindowsClipboard
+ public static class WindowsClipboard
{
const uint cfUnicodeText = 13;
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Classes/FileOpenDialogRCW.cs b/src/ExternalLibraries.FilePickers/Classes/FileOpenDialogRCW.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Classes/FileOpenDialogRCW.cs
rename to src/ExternalLibraries.FilePickers/Classes/FileOpenDialogRCW.cs
index 40797179c..b54f8c31b 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Classes/FileOpenDialogRCW.cs
+++ b/src/ExternalLibraries.FilePickers/Classes/FileOpenDialogRCW.cs
@@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Classes;
+namespace ExternalLibraries.Pickers.Classes;
// ---------------------------------------------------
// .NET classes representing runtime callable wrappers
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Classes/FileSaveDialogRCW.cs b/src/ExternalLibraries.FilePickers/Classes/FileSaveDialogRCW.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Classes/FileSaveDialogRCW.cs
rename to src/ExternalLibraries.FilePickers/Classes/FileSaveDialogRCW.cs
index 3f5f07e8b..96a69092f 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Classes/FileSaveDialogRCW.cs
+++ b/src/ExternalLibraries.FilePickers/Classes/FileSaveDialogRCW.cs
@@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Classes;
+namespace ExternalLibraries.Pickers.Classes;
// ---------------------------------------------------
// .NET classes representing runtime callable wrappers
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Classes/Helper.cs b/src/ExternalLibraries.FilePickers/Classes/Helper.cs
similarity index 70%
rename from src/UniGetUI/ExternalLibraries/Pickers/Classes/Helper.cs
rename to src/ExternalLibraries.FilePickers/Classes/Helper.cs
index 0b64472c6..e71cbf16f 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Classes/Helper.cs
+++ b/src/ExternalLibraries.FilePickers/Classes/Helper.cs
@@ -1,11 +1,11 @@
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using UniGetUI.ExternalLibraries.Pickers.Interfaces;
-using UniGetUI.ExternalLibraries.Pickers.Structures;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
+using ExternalLibraries.Pickers.Enums;
+using ExternalLibraries.Pickers.Interfaces;
+using ExternalLibraries.Pickers.Structures;
-namespace UniGetUI.ExternalLibraries.Pickers.Classes;
+namespace ExternalLibraries.Pickers.Classes;
internal static class Helper
{
@@ -18,7 +18,7 @@ internal static class Helper
/// Path to selected file, folder or empty string.
internal static string ShowOpen(nint windowHandle, FOS fos, List? typeFilters = null)
{
- var dialog = new FileOpenDialog();
+ FileOpenDialog dialog = new();
try
{
dialog.SetOptions(fos);
@@ -26,7 +26,7 @@ internal static string ShowOpen(nint windowHandle, FOS fos, List? typeFi
if (typeFilters != null)
{
typeFilters.Insert(0, string.Join("; ", typeFilters));
- var filterSpecs = typeFilters.Select(f => new COMDLG_FILTERSPEC(f)).ToArray();
+ COMDLG_FILTERSPEC[] filterSpecs = typeFilters.Select(f => new COMDLG_FILTERSPEC(f)).ToArray();
dialog.SetFileTypes((uint)filterSpecs.Length, filterSpecs);
}
@@ -34,8 +34,8 @@ internal static string ShowOpen(nint windowHandle, FOS fos, List? typeFi
if (dialog.Show(windowHandle) != 0)
return string.Empty;
- dialog.GetResult(out var item);
- item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out var path);
+ dialog.GetResult(out IShellItem item);
+ item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out string path);
return path;
}
finally
@@ -48,14 +48,14 @@ internal static string ShowOpen(nint windowHandle, FOS fos, List? typeFi
internal static string ShowSave(nint windowHandle, FOS fos, List? typeFilters = null, string name = "")
{
- var dialog = new FileSaveDialog();
+ FileSaveDialog dialog = new();
try
{
dialog.SetOptions(fos);
if (typeFilters != null)
{
- var filterSpecs = typeFilters.Select(f => new COMDLG_FILTERSPEC(f)).ToArray();
+ COMDLG_FILTERSPEC[] filterSpecs = typeFilters.Select(f => new COMDLG_FILTERSPEC(f)).ToArray();
dialog.SetFileTypes((uint)filterSpecs.Length, filterSpecs);
}
@@ -66,8 +66,8 @@ internal static string ShowSave(nint windowHandle, FOS fos, List? typeFi
if (dialog.Show(windowHandle) != 0)
return string.Empty;
- dialog.GetResult(out var item);
- item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out var path);
+ dialog.GetResult(out IShellItem item);
+ item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out string path);
return path;
}
finally
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDAP.cs b/src/ExternalLibraries.FilePickers/Enums/FDAP.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/FDAP.cs
rename to src/ExternalLibraries.FilePickers/Enums/FDAP.cs
index c19ea4a40..c6347e932 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDAP.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/FDAP.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-fdap
internal enum FDAP
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_OVERWRITE_RESPONSE.cs b/src/ExternalLibraries.FilePickers/Enums/FDE_OVERWRITE_RESPONSE.cs
similarity index 81%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_OVERWRITE_RESPONSE.cs
rename to src/ExternalLibraries.FilePickers/Enums/FDE_OVERWRITE_RESPONSE.cs
index 80aeb4b3c..011f2bdaa 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_OVERWRITE_RESPONSE.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/FDE_OVERWRITE_RESPONSE.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-fde_overwrite_response
internal enum FDE_OVERWRITE_RESPONSE
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs b/src/ExternalLibraries.FilePickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs
similarity index 82%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs
rename to src/ExternalLibraries.FilePickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs
index 723eb0f42..71fb59290 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/FDE_SHAREVIOLATION_RESPONSE.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-fde_shareviolation_response
internal enum FDE_SHAREVIOLATION_RESPONSE
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FOS.cs b/src/ExternalLibraries.FilePickers/Enums/FOS.cs
similarity index 95%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/FOS.cs
rename to src/ExternalLibraries.FilePickers/Enums/FOS.cs
index a3eaa6cb6..abfb4aaee 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/FOS.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/FOS.cs
@@ -1,6 +1,6 @@
using System;
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
[Flags]
// https://learn.microsoft.com/ru-ru/windows/win32/api/shobjidl_core/ne-shobjidl_core-_fileopendialogoptions
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/HRESULT.cs b/src/ExternalLibraries.FilePickers/Enums/HRESULT.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/HRESULT.cs
rename to src/ExternalLibraries.FilePickers/Enums/HRESULT.cs
index c2fd533d6..2bbc83dbf 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/HRESULT.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/HRESULT.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
internal enum HRESULT : long
{
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/SIATTRIBFLAGS.cs b/src/ExternalLibraries.FilePickers/Enums/SIATTRIBFLAGS.cs
similarity index 88%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/SIATTRIBFLAGS.cs
rename to src/ExternalLibraries.FilePickers/Enums/SIATTRIBFLAGS.cs
index bc65788af..7b5493018 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/SIATTRIBFLAGS.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/SIATTRIBFLAGS.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitemarray-getattributes
internal enum SIATTRIBFLAGS
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Enums/SIGDN.cs b/src/ExternalLibraries.FilePickers/Enums/SIGDN.cs
similarity index 93%
rename from src/UniGetUI/ExternalLibraries/Pickers/Enums/SIGDN.cs
rename to src/ExternalLibraries.FilePickers/Enums/SIGDN.cs
index 0d3590941..0b2456d0d 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Enums/SIGDN.cs
+++ b/src/ExternalLibraries.FilePickers/Enums/SIGDN.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Enums;
+namespace ExternalLibraries.Pickers.Enums;
// https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-sigdn
internal enum SIGDN : uint
diff --git a/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj b/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj
new file mode 100644
index 000000000..8d819499e
--- /dev/null
+++ b/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj
@@ -0,0 +1,10 @@
+
+
+
+ net8.0
+ enable
+ enable
+ AnyCPU;ARM64;x64
+
+
+
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/FileOpenPicker.cs b/src/ExternalLibraries.FilePickers/FileOpenPicker.cs
similarity index 84%
rename from src/UniGetUI/ExternalLibraries/Pickers/FileOpenPicker.cs
rename to src/ExternalLibraries.FilePickers/FileOpenPicker.cs
index 624820504..766104a39 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/FileOpenPicker.cs
+++ b/src/ExternalLibraries.FilePickers/FileOpenPicker.cs
@@ -1,9 +1,9 @@
-using UniGetUI.ExternalLibraries.Pickers.Classes;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using System;
+using System;
using System.Collections.Generic;
+using ExternalLibraries.Pickers.Classes;
+using ExternalLibraries.Pickers.Enums;
-namespace UniGetUI.ExternalLibraries.Pickers;
+namespace ExternalLibraries.Pickers;
///
/// Class responsible for file pick dialog.
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/FileSavePicker.cs b/src/ExternalLibraries.FilePickers/FileSavePicker.cs
similarity index 86%
rename from src/UniGetUI/ExternalLibraries/Pickers/FileSavePicker.cs
rename to src/ExternalLibraries.FilePickers/FileSavePicker.cs
index 4a36bc0be..77cde3134 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/FileSavePicker.cs
+++ b/src/ExternalLibraries.FilePickers/FileSavePicker.cs
@@ -1,9 +1,9 @@
-using UniGetUI.ExternalLibraries.Pickers.Classes;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using System;
+using System;
using System.Collections.Generic;
+using ExternalLibraries.Pickers.Classes;
+using ExternalLibraries.Pickers.Enums;
-namespace UniGetUI.ExternalLibraries.Pickers;
+namespace ExternalLibraries.Pickers;
///
/// Class responsible for file pick dialog.
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/FolderPicker.cs b/src/ExternalLibraries.FilePickers/FolderPicker.cs
similarity index 82%
rename from src/UniGetUI/ExternalLibraries/Pickers/FolderPicker.cs
rename to src/ExternalLibraries.FilePickers/FolderPicker.cs
index b2a3a5ae8..bfd302ab9 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/FolderPicker.cs
+++ b/src/ExternalLibraries.FilePickers/FolderPicker.cs
@@ -1,8 +1,8 @@
-using UniGetUI.ExternalLibraries.Pickers.Classes;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using System;
+using System;
+using ExternalLibraries.Pickers.Classes;
+using ExternalLibraries.Pickers.Enums;
-namespace UniGetUI.ExternalLibraries.Pickers;
+namespace ExternalLibraries.Pickers;
///
/// Class responsible for folder pick dialog.
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Guids/CLSIDGuid.cs b/src/ExternalLibraries.FilePickers/Guids/CLSIDGuid.cs
similarity index 86%
rename from src/UniGetUI/ExternalLibraries/Pickers/Guids/CLSIDGuid.cs
rename to src/ExternalLibraries.FilePickers/Guids/CLSIDGuid.cs
index cce14d002..228f4ed35 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Guids/CLSIDGuid.cs
+++ b/src/ExternalLibraries.FilePickers/Guids/CLSIDGuid.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Guids;
+namespace ExternalLibraries.Pickers.Guids;
internal static class CLSIDGuid
{
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Guids/IIDGuid.cs b/src/ExternalLibraries.FilePickers/Guids/IIDGuid.cs
similarity index 95%
rename from src/UniGetUI/ExternalLibraries/Pickers/Guids/IIDGuid.cs
rename to src/ExternalLibraries.FilePickers/Guids/IIDGuid.cs
index 35d78f596..a0f187807 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Guids/IIDGuid.cs
+++ b/src/ExternalLibraries.FilePickers/Guids/IIDGuid.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Guids;
+namespace ExternalLibraries.Pickers.Guids;
internal static class IIDGuid
{
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Guids/KFIDGuid.cs b/src/ExternalLibraries.FilePickers/Guids/KFIDGuid.cs
similarity index 86%
rename from src/UniGetUI/ExternalLibraries/Pickers/Guids/KFIDGuid.cs
rename to src/ExternalLibraries.FilePickers/Guids/KFIDGuid.cs
index 991e7dcae..b51f3740d 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Guids/KFIDGuid.cs
+++ b/src/ExternalLibraries.FilePickers/Guids/KFIDGuid.cs
@@ -1,4 +1,4 @@
-namespace UniGetUI.ExternalLibraries.Pickers.Guids;
+namespace ExternalLibraries.Pickers.Guids;
internal static class KFIDGuid
{
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileOpenDialog.cs b/src/ExternalLibraries.FilePickers/Interfaces/FileOpenDialog.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileOpenDialog.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/FileOpenDialog.cs
index bd6ef1fcc..9cddb1024 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileOpenDialog.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/FileOpenDialog.cs
@@ -1,8 +1,8 @@
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Classes;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Classes;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
// ---------------------------------------------------------
// Coclass interfaces - designed to "look like" the object
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileSaveDialog.cs b/src/ExternalLibraries.FilePickers/Interfaces/FileSaveDialog.cs
similarity index 75%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileSaveDialog.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/FileSaveDialog.cs
index ed9ffcd5d..2f76d7e80 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/FileSaveDialog.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/FileSaveDialog.cs
@@ -1,8 +1,8 @@
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Classes;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Classes;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
// ---------------------------------------------------------
// Coclass interfaces - designed to "look like" the object
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialog.cs b/src/ExternalLibraries.FilePickers/Interfaces/IFileDialog.cs
similarity index 95%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialog.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IFileDialog.cs
index da70b4d81..0f353f9a5 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialog.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IFileDialog.cs
@@ -1,11 +1,11 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
-using UniGetUI.ExternalLibraries.Pickers.Structures;
+using ExternalLibraries.Pickers.Enums;
+using ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Structures;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport(),
Guid(IIDGuid.IFileDialog),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialogEvents.cs b/src/ExternalLibraries.FilePickers/Interfaces/IFileDialogEvents.cs
similarity index 92%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialogEvents.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IFileDialogEvents.cs
index 18ab25d5e..732a52d25 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileDialogEvents.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IFileDialogEvents.cs
@@ -1,9 +1,9 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Enums;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport,
Guid(IIDGuid.IFileDialogEvents),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileOpenDialog.cs b/src/ExternalLibraries.FilePickers/Interfaces/IFileOpenDialog.cs
similarity index 91%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileOpenDialog.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IFileOpenDialog.cs
index 83941f903..61f666d28 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IFileOpenDialog.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IFileOpenDialog.cs
@@ -1,9 +1,9 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
-using UniGetUI.ExternalLibraries.Pickers.Structures;
+using ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Structures;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport(),
Guid(IIDGuid.IFileOpenDialog),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IModalWindow.cs b/src/ExternalLibraries.FilePickers/Interfaces/IModalWindow.cs
similarity index 77%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IModalWindow.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IModalWindow.cs
index 319f062fc..5745b0e79 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IModalWindow.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IModalWindow.cs
@@ -1,9 +1,9 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport(),
Guid(IIDGuid.IModalWindow),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItem.cs b/src/ExternalLibraries.FilePickers/Interfaces/IShellItem.cs
similarity index 88%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItem.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IShellItem.cs
index 1431c0301..64ccf5604 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItem.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IShellItem.cs
@@ -1,10 +1,10 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Enums;
+using ExternalLibraries.Pickers.Guids;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport,
Guid(IIDGuid.IShellItem),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItemArray.cs b/src/ExternalLibraries.FilePickers/Interfaces/IShellItemArray.cs
similarity index 88%
rename from src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItemArray.cs
rename to src/ExternalLibraries.FilePickers/Interfaces/IShellItemArray.cs
index e0752e782..038492d43 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Interfaces/IShellItemArray.cs
+++ b/src/ExternalLibraries.FilePickers/Interfaces/IShellItemArray.cs
@@ -1,11 +1,11 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using UniGetUI.ExternalLibraries.Pickers.Enums;
-using UniGetUI.ExternalLibraries.Pickers.Guids;
-using UniGetUI.ExternalLibraries.Pickers.Structures;
+using ExternalLibraries.Pickers.Enums;
+using ExternalLibraries.Pickers.Guids;
+using ExternalLibraries.Pickers.Structures;
-namespace UniGetUI.ExternalLibraries.Pickers.Interfaces;
+namespace ExternalLibraries.Pickers.Interfaces;
[ComImport,
Guid(IIDGuid.IShellItemArray),
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Structures/COMDLG_FILTERSPEC.cs b/src/ExternalLibraries.FilePickers/Structures/COMDLG_FILTERSPEC.cs
similarity index 89%
rename from src/UniGetUI/ExternalLibraries/Pickers/Structures/COMDLG_FILTERSPEC.cs
rename to src/ExternalLibraries.FilePickers/Structures/COMDLG_FILTERSPEC.cs
index 464f62dc9..2fa3b3110 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Structures/COMDLG_FILTERSPEC.cs
+++ b/src/ExternalLibraries.FilePickers/Structures/COMDLG_FILTERSPEC.cs
@@ -1,6 +1,6 @@
using System.Runtime.InteropServices;
-namespace UniGetUI.ExternalLibraries.Pickers.Structures;
+namespace ExternalLibraries.Pickers.Structures;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
internal struct COMDLG_FILTERSPEC
diff --git a/src/UniGetUI/ExternalLibraries/Pickers/Structures/PROPERTYKEY.cs b/src/ExternalLibraries.FilePickers/Structures/PROPERTYKEY.cs
similarity index 76%
rename from src/UniGetUI/ExternalLibraries/Pickers/Structures/PROPERTYKEY.cs
rename to src/ExternalLibraries.FilePickers/Structures/PROPERTYKEY.cs
index 4ca3d18e0..a062a7ef2 100644
--- a/src/UniGetUI/ExternalLibraries/Pickers/Structures/PROPERTYKEY.cs
+++ b/src/ExternalLibraries.FilePickers/Structures/PROPERTYKEY.cs
@@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
-namespace UniGetUI.ExternalLibraries.Pickers.Structures;
+namespace ExternalLibraries.Pickers.Structures;
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct PROPERTYKEY
diff --git a/src/Solution.props b/src/Solution.props
new file mode 100644
index 000000000..c0fafdd9d
--- /dev/null
+++ b/src/Solution.props
@@ -0,0 +1,23 @@
+
+
+ net8.0-windows10.0.19041.0
+ enable
+ win-x64;win-arm64
+ win-$(Platform)
+ ARM64;x64
+ 10.0.19041.0
+ 10.0.19041.0
+ win-x64;win-arm64
+ 8.0.204
+ true
+ true
+ 3.1.0.0
+ 3.1.0-alpha
+ UniGetUI
+ Martí Climent and the contributors
+ Martí Climent
+ 3.1.0-alpha
+ 2024, Martí Climent
+ enable
+
+
diff --git a/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.dgspec.json b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.dgspec.json
new file mode 100644
index 000000000..440e12339
--- /dev/null
+++ b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.dgspec.json
@@ -0,0 +1,435 @@
+{
+ "format": 1,
+ "restore": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj": {}
+ },
+ "projects": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj",
+ "projectName": "UniGetUI.Core.Tools",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj"
+ }
+ }
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj",
+ "projectName": "UniGetUI.Core.Data",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj"
+ }
+ }
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\UniGetUI.PackageEngine.Enums.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\UniGetUI.PackageEngine.Enums.csproj",
+ "projectName": "UniGetUI.PackageEngine.Enums",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\UniGetUI.PackageEngine.Enums.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj",
+ "projectName": "UniGetUI.Core.Language",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\UniGetUI.PackageEngine.Enums.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Enums\\UniGetUI.PackageEngine.Enums.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj"
+ }
+ }
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj",
+ "projectName": "UniGetUI.Core.Logging",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj",
+ "projectName": "UniGetUI.Core.Settings",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj"
+ }
+ }
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.props b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.props
new file mode 100644
index 000000000..e169dd7ba
--- /dev/null
+++ b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.props
@@ -0,0 +1,16 @@
+
+
+
+ True
+ NuGet
+ $(MSBuildThisFileDirectory)project.assets.json
+ $(UserProfile)\.nuget\packages\
+ C:\Users\marti\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages
+ PackageReference
+ 6.10.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.targets b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.targets
new file mode 100644
index 000000000..3dc06ef3c
--- /dev/null
+++ b/src/Tools/obj/UniGetUI.Core.Tools.csproj.nuget.g.targets
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/Tools/obj/project.assets.json b/src/Tools/obj/project.assets.json
new file mode 100644
index 000000000..95f8bed7c
--- /dev/null
+++ b/src/Tools/obj/project.assets.json
@@ -0,0 +1,187 @@
+{
+ "version": 3,
+ "targets": {
+ "net8.0": {
+ "UniGetUI.Core.Data/1.0.0": {
+ "type": "project",
+ "framework": ".NETCoreApp,Version=v8.0",
+ "dependencies": {
+ "UniGetUI.Core.Logging": "1.0.0"
+ },
+ "compile": {
+ "bin/placeholder/UniGetUI.Core.Data.dll": {}
+ },
+ "runtime": {
+ "bin/placeholder/UniGetUI.Core.Data.dll": {}
+ }
+ },
+ "UniGetUI.Core.Language/1.0.0": {
+ "type": "project",
+ "framework": ".NETCoreApp,Version=v8.0",
+ "dependencies": {
+ "UniGetUI.Core.Data": "1.0.0",
+ "UniGetUI.Core.Logging": "1.0.0",
+ "UniGetUI.Core.Settings": "1.0.0",
+ "UniGetUI.PackageEngine.Enums": "1.0.0"
+ },
+ "compile": {
+ "bin/placeholder/UniGetUI.Core.Language.dll": {}
+ },
+ "runtime": {
+ "bin/placeholder/UniGetUI.Core.Language.dll": {}
+ }
+ },
+ "UniGetUI.Core.Logging/1.0.0": {
+ "type": "project",
+ "framework": ".NETCoreApp,Version=v8.0",
+ "compile": {
+ "bin/placeholder/UniGetUI.Core.Logging.dll": {}
+ },
+ "runtime": {
+ "bin/placeholder/UniGetUI.Core.Logging.dll": {}
+ }
+ },
+ "UniGetUI.Core.Settings/1.0.0": {
+ "type": "project",
+ "framework": ".NETCoreApp,Version=v8.0",
+ "dependencies": {
+ "UniGetUI.Core.Data": "1.0.0",
+ "UniGetUI.Core.Logging": "1.0.0"
+ },
+ "compile": {
+ "bin/placeholder/UniGetUI.Core.Settings.dll": {}
+ },
+ "runtime": {
+ "bin/placeholder/UniGetUI.Core.Settings.dll": {}
+ }
+ },
+ "UniGetUI.PackageEngine.Enums/1.0.0": {
+ "type": "project",
+ "framework": ".NETCoreApp,Version=v8.0",
+ "compile": {
+ "bin/placeholder/UniGetUI.PackageEngine.Enums.dll": {}
+ },
+ "runtime": {
+ "bin/placeholder/UniGetUI.PackageEngine.Enums.dll": {}
+ }
+ }
+ }
+ },
+ "libraries": {
+ "UniGetUI.Core.Data/1.0.0": {
+ "type": "project",
+ "path": "../UniGetUI.Core.Data/UniGetUI.Core.Data.csproj",
+ "msbuildProject": "../UniGetUI.Core.Data/UniGetUI.Core.Data.csproj"
+ },
+ "UniGetUI.Core.Language/1.0.0": {
+ "type": "project",
+ "path": "../UniGetUI.Core.LanguageEngine/UniGetUI.Core.Language.csproj",
+ "msbuildProject": "../UniGetUI.Core.LanguageEngine/UniGetUI.Core.Language.csproj"
+ },
+ "UniGetUI.Core.Logging/1.0.0": {
+ "type": "project",
+ "path": "../UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj",
+ "msbuildProject": "../UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj"
+ },
+ "UniGetUI.Core.Settings/1.0.0": {
+ "type": "project",
+ "path": "../UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj",
+ "msbuildProject": "../UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj"
+ },
+ "UniGetUI.PackageEngine.Enums/1.0.0": {
+ "type": "project",
+ "path": "../UniGetUI.Core.Enums/UniGetUI.PackageEngine.Enums.csproj",
+ "msbuildProject": "../UniGetUI.Core.Enums/UniGetUI.PackageEngine.Enums.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "net8.0": [
+ "UniGetUI.Core.Data >= 1.0.0",
+ "UniGetUI.Core.Language >= 1.0.0",
+ "UniGetUI.Core.Logging >= 1.0.0",
+ "UniGetUI.Core.Settings >= 1.0.0"
+ ]
+ },
+ "packageFolders": {
+ "C:\\Users\\marti\\.nuget\\packages\\": {},
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
+ },
+ "project": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj",
+ "projectName": "UniGetUI.Core.Tools",
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj",
+ "packagesPath": "C:\\Users\\marti\\.nuget\\packages\\",
+ "outputPath": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\obj\\",
+ "projectStyle": "PackageReference",
+ "fallbackFolders": [
+ "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
+ ],
+ "configFilePaths": [
+ "C:\\Users\\marti\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net8.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "c:\\program files\\dotnet\\library-packs": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "projectReferences": {
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Data\\UniGetUI.Core.Data.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.LanguageEngine\\UniGetUI.Core.Language.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Logger\\UniGetUI.Core.Logging.csproj"
+ },
+ "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj": {
+ "projectPath": "C:\\SomePrograms\\WingetUI-Store\\src\\UniGetUI.Core.Settings\\UniGetUI.Core.Settings.csproj"
+ }
+ }
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ }
+ },
+ "frameworks": {
+ "net8.0": {
+ "targetAlias": "net8.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "c:\\program files\\dotnet\\sdk\\8.0.300-preview.24203.14/PortableRuntimeIdentifierGraph.json"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tools/obj/project.nuget.cache b/src/Tools/obj/project.nuget.cache
new file mode 100644
index 000000000..b0c82d585
--- /dev/null
+++ b/src/Tools/obj/project.nuget.cache
@@ -0,0 +1,8 @@
+{
+ "version": 2,
+ "dgSpecHash": "9/dpZuVlARI=",
+ "success": true,
+ "projectFilePath": "C:\\SomePrograms\\WingetUI-Store\\src\\Tools\\UniGetUI.Core.Tools.csproj",
+ "expectedPackageFiles": [],
+ "logs": []
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Classes.Tests/PersonTests.cs b/src/UniGetUI.Core.Classes.Tests/PersonTests.cs
new file mode 100644
index 000000000..4c9782c67
--- /dev/null
+++ b/src/UniGetUI.Core.Classes.Tests/PersonTests.cs
@@ -0,0 +1,32 @@
+using Xunit;
+
+namespace UniGetUI.Core.Classes.Tests
+{
+ public class PersonTests
+ {
+ [Theory]
+ [InlineData("Bernat-Miquel Guimerà", "https://github.com/BernatMiquelG.png", "https://github.com/BernatMiquelG")]
+ [InlineData("Bernat-Miquel Guimerà", "https://github.com/BernatMiquelG.png", null)]
+ [InlineData("Bernat-Miquel Guimerà", null, "https://github.com/BernatMiquelG")]
+ [InlineData("Bernat-Miquel Guimerà", null, null)]
+ public void TestPerson(string name, string? profilePicture, string? gitHubUrl)
+ {
+
+ //arrange
+ Person actual = new(Name: name,
+ ProfilePicture: profilePicture is null ? null : new Uri(profilePicture),
+ GitHubUrl: gitHubUrl is null ? null : new Uri(gitHubUrl));
+
+ //Assert
+ if (string.IsNullOrEmpty(profilePicture))
+ Assert.False(actual.HasPicture);
+ else
+ Assert.True(actual.HasPicture);
+
+ if (string.IsNullOrEmpty(gitHubUrl))
+ Assert.False(actual.HasGitHubProfile);
+ else
+ Assert.True(actual.HasGitHubProfile);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Classes.Tests/SingletonBaseTest.cs b/src/UniGetUI.Core.Classes.Tests/SingletonBaseTest.cs
new file mode 100644
index 000000000..591e135fe
--- /dev/null
+++ b/src/UniGetUI.Core.Classes.Tests/SingletonBaseTest.cs
@@ -0,0 +1,37 @@
+using Xunit;
+
+namespace UniGetUI.Core.Classes.Tests
+{
+ public class SingletonBaseTest
+ {
+
+ private class InheritedClass1 : SingletonBase
+ {
+ public int Attribute1 { get; set; } = 0;
+ }
+
+ private class InheritedClass2 : SingletonBase
+ {
+ public int Attribute1 { get; set; } = 0;
+ }
+
+
+ [Fact]
+ public void TestSingletonClass()
+ {
+ var Type1Instance1 = InheritedClass1.Instance;
+ Type1Instance1.Attribute1 = 1;
+
+ var Type1Instance2 = InheritedClass1.Instance;
+ Type1Instance2.Attribute1 = 3;
+
+ Assert.Equal(Type1Instance1.Attribute1, Type1Instance2.Attribute1);
+ Assert.Equal(Type1Instance1, Type1Instance2);
+
+ var Type2Instance1 = new InheritedClass2();
+ Type2Instance1.Attribute1 = 2;
+
+ Assert.NotEqual(Type1Instance1.Attribute1, Type2Instance1.Attribute1);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Classes.Tests/SortableObservableCollectionTests.cs b/src/UniGetUI.Core.Classes.Tests/SortableObservableCollectionTests.cs
new file mode 100644
index 000000000..5a7ec4e3e
--- /dev/null
+++ b/src/UniGetUI.Core.Classes.Tests/SortableObservableCollectionTests.cs
@@ -0,0 +1,35 @@
+using Xunit;
+
+namespace UniGetUI.Core.Classes.Tests
+{
+ public class SortableObservableCollectionTests
+ {
+ [Fact]
+ public void TestSortableCollection()
+ {
+ int EventTriggeredCount = 0;
+
+ var SortableCollection = new SortableObservableCollection();
+ SortableCollection.CollectionChanged += (s, e) => { EventTriggeredCount++; };
+ SortableCollection.SortingSelector = (s) => { return s; };
+ SortableCollection.Add(1);
+ SortableCollection.Add(3);
+ SortableCollection.Add(4);
+
+ SortableCollection.BlockSorting = true;
+ SortableCollection.Add(5);
+ SortableCollection.Add(2);
+ SortableCollection.BlockSorting = false;
+
+
+ SortableCollection.Sort();
+
+ Assert.Equal(7, EventTriggeredCount);
+ Assert.Equal(1, SortableCollection[0]);
+ Assert.Equal(2, SortableCollection[1]);
+ Assert.Equal(3, SortableCollection[2]);
+ Assert.Equal(4, SortableCollection[3]);
+ Assert.Equal(5, SortableCollection[4]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj
new file mode 100644
index 000000000..fd1a09986
--- /dev/null
+++ b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj
@@ -0,0 +1,33 @@
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Classes/Person.cs b/src/UniGetUI.Core.Classes/Person.cs
new file mode 100644
index 000000000..8668b15e3
--- /dev/null
+++ b/src/UniGetUI.Core.Classes/Person.cs
@@ -0,0 +1,22 @@
+namespace UniGetUI.Core.Classes
+{
+ public readonly struct Person
+ {
+ public readonly string Name;
+ public readonly Uri? ProfilePicture;
+ public readonly Uri? GitHubUrl;
+ public readonly bool HasPicture;
+ public readonly bool HasGitHubProfile;
+ public readonly string Language;
+
+ public Person(string Name, Uri? ProfilePicture = null, Uri? GitHubUrl = null, string Language = "")
+ {
+ this.Name = Name;
+ this.ProfilePicture = ProfilePicture;
+ this.GitHubUrl = GitHubUrl;
+ this.HasPicture = ProfilePicture is not null;
+ this.HasGitHubProfile = GitHubUrl is not null;
+ this.Language = Language;
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Classes/SingletonBase.cs b/src/UniGetUI.Core.Classes/SingletonBase.cs
new file mode 100644
index 000000000..d17cc337b
--- /dev/null
+++ b/src/UniGetUI.Core.Classes/SingletonBase.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace UniGetUI.Core.Classes
+{
+ public abstract class SingletonBase where T : SingletonBase
+ {
+ private static readonly Lazy Lazy =
+ new(() => (Activator.CreateInstance(typeof(T), true) as T)!);
+
+ public static T Instance => Lazy.Value;
+
+ protected SingletonBase() { }
+ }
+}
diff --git a/src/UniGetUI/Core/Classes.cs b/src/UniGetUI.Core.Classes/SortableObservableCollection.cs
similarity index 72%
rename from src/UniGetUI/Core/Classes.cs
rename to src/UniGetUI.Core.Classes/SortableObservableCollection.cs
index 76b8c1c5a..3fc0e61c9 100644
--- a/src/UniGetUI/Core/Classes.cs
+++ b/src/UniGetUI.Core.Classes/SortableObservableCollection.cs
@@ -1,14 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
+using System.Collections.ObjectModel;
using System.Collections.Specialized;
-using System.Linq;
-namespace UniGetUI.Core
+namespace UniGetUI.Core.Classes
{
public class SortableObservableCollection : ObservableCollection
{
- public Func SortingSelector { get; set; }
+ public Func? SortingSelector { get; set; }
public bool Descending { get; set; }
public bool BlockSorting { get; set; } = false;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
@@ -22,12 +19,15 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
return;
Sort();
}
-
}
+
public void Sort()
{
BlockSorting = true;
+ if (SortingSelector == null)
+ throw new Exception("SortableObservableCollection.SortingSelector must not be null when sorting a function");
+
List sorted = Descending ? this.OrderByDescending(SortingSelector).ToList() : this.OrderBy(SortingSelector).ToList();
foreach (T item in sorted)
{
@@ -37,12 +37,4 @@ public void Sort()
base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
-
- public abstract class SingletonBase where T : SingletonBase
- {
- private static readonly Lazy Lazy =
- new(() => (Activator.CreateInstance(typeof(T), true) as T)!);
-
- public static T Instance => Lazy.Value;
- }
}
diff --git a/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj b/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj
new file mode 100644
index 000000000..d82d51cab
--- /dev/null
+++ b/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj
@@ -0,0 +1,8 @@
+
+
+
+
+
+ enable
+
+
diff --git a/src/UniGetUI.Core.Data.Tests/ContributorsTests.cs b/src/UniGetUI.Core.Data.Tests/ContributorsTests.cs
new file mode 100644
index 000000000..9fd992549
--- /dev/null
+++ b/src/UniGetUI.Core.Data.Tests/ContributorsTests.cs
@@ -0,0 +1,12 @@
+namespace UniGetUI.Core.Data.Tests
+{
+ public class ContributorsTests
+ {
+
+ [Fact]
+ public void CheckIfContributorListIsEmpty()
+ {
+ Assert.NotEmpty(ContributorsData.Contributors);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Data.Tests/CoreTests.cs b/src/UniGetUI.Core.Data.Tests/CoreTests.cs
new file mode 100644
index 000000000..8e199959e
--- /dev/null
+++ b/src/UniGetUI.Core.Data.Tests/CoreTests.cs
@@ -0,0 +1,42 @@
+namespace UniGetUI.Core.Data.Tests
+{
+ public class CoreTests
+ {
+ public static object[][] Data =>
+ [
+ [CoreData.UniGetUIDataDirectory],
+ [CoreData.UniGetUIInstallationOptionsDirectory ],
+ [CoreData.UniGetUICacheDirectory_Data ],
+ [CoreData.UniGetUICacheDirectory_Icons ],
+ [CoreData.UniGetUICacheDirectory_Lang ],
+ [CoreData.UniGetUI_DefaultBackupDirectory ]
+ ];
+
+ [Theory]
+ [MemberData(nameof(Data))]
+ public void CheckDirectoryAttributes(string directory)
+ {
+ Assert.True(Directory.Exists(directory), $"Directory ${directory} does not exist, but it should have been created automatically");
+ }
+
+ [Fact]
+ public void CheckOtherAttributes()
+ {
+ Assert.NotEmpty(CoreData.VersionName);
+ Assert.NotEqual(0, CoreData.VersionNumber);
+ Assert.True(File.Exists(CoreData.IgnoredUpdatesDatabaseFile), "The Ignored Updates database file does not exist, but it should have been created automatically.");
+
+ var notif_1 = CoreData.VolatileNotificationIdCounter;
+ var notif_2 = CoreData.VolatileNotificationIdCounter;
+ Assert.NotEqual(notif_1, notif_2);
+
+ var notif_3 = CoreData.UpdatesAvailableNotificationId;
+ var notif_4 = CoreData.UpdatesAvailableNotificationId;
+ Assert.True(notif_3 == notif_4, "The UpdatesAvailableNotificationId must be always the same");
+ Assert.NotEqual(0, CoreData.UpdatesAvailableNotificationId);
+
+ Assert.True(Directory.Exists(CoreData.UniGetUIExecutableDirectory), "Directory where the executable is located does not exist");
+ Assert.True(File.Exists(CoreData.UniGetUIExecutableFile), "The executable file does not exist");
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Data.Tests/LicensesTest.cs b/src/UniGetUI.Core.Data.Tests/LicensesTest.cs
new file mode 100644
index 000000000..3f17a1bae
--- /dev/null
+++ b/src/UniGetUI.Core.Data.Tests/LicensesTest.cs
@@ -0,0 +1,30 @@
+namespace UniGetUI.Core.Data.Tests
+{
+ public class LicensesTest
+ {
+ [Fact]
+ public void EnsureLicenseUrlsExist()
+ {
+ List MissingUrls = new();
+
+ foreach (string library in LicenseData.LicenseNames.Keys)
+ if(!LicenseData.LicenseURLs.ContainsKey(library))
+ MissingUrls.Add(library);
+
+ Assert.True(MissingUrls.Count == 0, "The list of missing licenses is not empty: " + MissingUrls.ToArray().ToString());
+ }
+
+ [Fact]
+ public void EnsureHomepageUrlsExist()
+ {
+ List MissingUrls = new();
+
+ foreach (string library in LicenseData.LicenseNames.Keys)
+ if (!LicenseData.HomepageUrls.ContainsKey(library))
+ MissingUrls.Add(library);
+
+ Assert.True(MissingUrls.Count == 0, "The list of missing licenses is not empty: " + MissingUrls.ToArray().ToString());
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj
new file mode 100644
index 000000000..6e0ca21a7
--- /dev/null
+++ b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj
@@ -0,0 +1,33 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/Assets/Data/Contributors.list b/src/UniGetUI.Core.Data/Assets/Data/Contributors.list
similarity index 100%
rename from src/UniGetUI/Assets/Data/Contributors.list
rename to src/UniGetUI.Core.Data/Assets/Data/Contributors.list
diff --git a/src/UniGetUI/Core/Data/Contributors.cs b/src/UniGetUI.Core.Data/Contributors.cs
similarity index 79%
rename from src/UniGetUI/Core/Data/Contributors.cs
rename to src/UniGetUI.Core.Data/Contributors.cs
index 6bfae5e95..cd274d57b 100644
--- a/src/UniGetUI/Core/Data/Contributors.cs
+++ b/src/UniGetUI.Core.Data/Contributors.cs
@@ -1,7 +1,4 @@
-using System.IO;
-using System.Linq;
-
-namespace UniGetUI.Core.Data
+namespace UniGetUI.Core.Data
{
public static class ContributorsData
{
diff --git a/src/UniGetUI.Core.Data/Core.cs b/src/UniGetUI.Core.Data/Core.cs
new file mode 100644
index 000000000..d0b796877
--- /dev/null
+++ b/src/UniGetUI.Core.Data/Core.cs
@@ -0,0 +1,195 @@
+using System.Reflection.Metadata.Ecma335;
+using UniGetUI.Core.Logging;
+using Windows.Storage.Search;
+using Windows.System.Diagnostics;
+
+namespace UniGetUI.Core.Data
+{
+ public static class CoreData
+ {
+ public static string VersionName = "3.1.0-alpha"; // Do not modify this line, use file scripts/apply_versions.py
+ public static double VersionNumber = 3.099; // Do not modify this line, use file scripts/apply_versions.py
+
+ ///
+ /// The directory where all the user data is stored. The directory is automatically created if it does not exist.
+ ///
+ public static string UniGetUIDataDirectory
+ {
+ get
+ {
+ string old_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".wingetui");
+ string new_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UniGetUI");
+ return GetNewDataDirectoryOrMoveOld(old_path, new_path);
+ }
+ }
+
+ ///
+ /// The directory where the installation options are stored. The directory is automatically created if it does not exist.
+ ///
+ public static string UniGetUIInstallationOptionsDirectory
+ {
+ get
+ {
+ var path = Path.Join(UniGetUIDataDirectory, "InstallationOptions");
+ if(!Directory.Exists(path)) Directory.CreateDirectory(path);
+ return path;
+ }
+ }
+
+ ///
+ /// The directory where the metadata cache is stored. The directory is automatically created if it does not exist.
+ ///
+ public static string UniGetUICacheDirectory_Data
+ {
+ get
+ {
+ string old_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WingetUI", "CachedData");
+ string new_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UniGetUI", "CachedMetadata");
+ return GetNewDataDirectoryOrMoveOld(old_path, new_path);
+ }
+ }
+
+ ///
+ /// The directory where the cached icons and screenshots are saved. The directory is automatically created if it does not exist.
+ ///
+ public static string UniGetUICacheDirectory_Icons
+ {
+ get
+ {
+ string old_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WingetUI", "CachedIcons");
+ string new_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UniGetUI", "CachedMedia");
+ return GetNewDataDirectoryOrMoveOld(old_path, new_path);
+ }
+ }
+
+ ///
+ /// The directory where the cached language files are stored. The directory is automatically created if it does not exist.
+ ///
+ public static string UniGetUICacheDirectory_Lang
+ {
+ get
+ {
+ string old_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WingetUI", "CachedLangFiles");
+ string new_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UniGetUI", "CachedLanguageFiles");
+ return GetNewDataDirectoryOrMoveOld(old_dir, new_dir);
+ }
+ }
+
+ ///
+ /// The directory where package backups will be saved by default.
+ ///
+ public static string UniGetUI_DefaultBackupDirectory
+ {
+ get
+ {
+ string old_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "WingetUI");
+ string new_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "UniGetUI");
+ return GetNewDataDirectoryOrMoveOld(old_dir, new_dir);
+ }
+ }
+
+ ///
+ /// The file where the screenshot metadata is stored. If the file does not exist, it will be created automatically.
+ ///
+ public static string IgnoredUpdatesDatabaseFile
+ {
+ get
+ {
+ // Calling the UniGetUIDataDirectory will create the directory if it does not exist
+ string file_path = Path.Join(UniGetUIDataDirectory, "IgnoredPackageUpdates.json");
+ if (!File.Exists(file_path))
+ File.WriteAllText(file_path, "{}");
+ return file_path;
+ }
+ }
+ public static bool IsDaemon = false;
+
+ public static string ManagerLogs = "";
+
+
+ private static int __volatile_notification_id_counter = 1235;
+
+ ///
+ /// A self-incremented value to generate random notification IDs
+ ///
+ public static int VolatileNotificationIdCounter
+ {
+ get => __volatile_notification_id_counter++;
+ }
+
+ ///
+ /// The ID of the notification that is used to inform the user that updates are available
+ ///
+ public static int UpdatesAvailableNotificationId
+ {
+ get => 1234;
+ }
+
+ ///
+ /// A path pointing to the location where the app is installed
+ ///
+ public static string UniGetUIExecutableDirectory
+ {
+ get {
+ string? dir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+ if (dir != null)
+ return dir;
+ else
+ Logger.Error("System.Reflection.Assembly.GetExecutingAssembly().Location returned an empty path");
+ return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "UiGetUI");
+ }
+ }
+
+ ///
+ /// A path pointing to the executable file of the app
+ ///
+ public static string UniGetUIExecutableFile
+ {
+ get {
+ string? filename = System.Reflection.Assembly.GetExecutingAssembly().Location;
+ if (filename != null)
+ return filename;
+ else
+ Logger.Error("System.Reflection.Assembly.GetExecutingAssembly().Location returned an empty path");
+ return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "UiGetUI", "UniGetUI.exe");
+ }
+ }
+
+
+ ///
+ /// This method will return the most appropriate data directory.
+ /// If the new directory exists, it will be used.
+ /// If the new directory does not exist, but the old directory does, it will be moved to the new location, and the new location will be used.
+ /// If none exist, the new directory will be created.
+ ///
+ /// The old/legacy directory
+ /// The new directory
+ /// The path to an existing, valid directory
+ private static string GetNewDataDirectoryOrMoveOld(string old_path, string new_path)
+ {
+ if (Directory.Exists(new_path))
+ return new_path;
+ else if (Directory.Exists(old_path))
+ {
+ try
+ {
+ Directory.Move(old_path, new_path);
+ return new_path;
+ }
+ catch (Exception e)
+ {
+ Logger.Error("Cannot move old data directory to new location. Directory to move: " + old_path + ". Destination: " + new_path);
+ Logger.Error(e);
+ return old_path;
+ }
+ }
+ else
+ {
+ Logger.Debug("Creating non-existing data directory at: " + new_path);
+ Directory.CreateDirectory(new_path);
+ return new_path;
+ }
+ }
+
+ }
+}
diff --git a/src/UniGetUI/Core/Data/Licenses.cs b/src/UniGetUI.Core.Data/Licenses.cs
similarity index 98%
rename from src/UniGetUI/Core/Data/Licenses.cs
rename to src/UniGetUI.Core.Data/Licenses.cs
index ac0f357e2..2ced3e0d4 100644
--- a/src/UniGetUI/Core/Data/Licenses.cs
+++ b/src/UniGetUI.Core.Data/Licenses.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-
-namespace UniGetUI.Core.Data
+namespace UniGetUI.Core.Data
{
public static class LicenseData
{
diff --git a/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj
new file mode 100644
index 000000000..6a0f6a73a
--- /dev/null
+++ b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/src/UniGetUI.Core.IconEngine.Tests/IconStoreTests.cs b/src/UniGetUI.Core.IconEngine.Tests/IconStoreTests.cs
new file mode 100644
index 000000000..e8494f24e
--- /dev/null
+++ b/src/UniGetUI.Core.IconEngine.Tests/IconStoreTests.cs
@@ -0,0 +1,48 @@
+namespace UniGetUI.Core.IconEngine.Tests
+{
+ public class IconStoreTests
+ {
+ IconDatabase iconStore = new();
+
+ [Fact]
+ public async Task LoadIconsAndScreenshotsDatabaseTest()
+ {
+ // Serializable is implicitly tested when calling the method
+ // LoadIconAndScreenshotsDatabase()
+
+ await iconStore.LoadIconAndScreenshotsDatabaseAsync();
+
+ var iconCount = iconStore.GetIconCount();
+ Assert.NotEqual(0, iconCount.PackagesWithIconCount);
+ Assert.NotEqual(0, iconCount.PackagesWithScreenshotCount);
+ Assert.NotEqual(0, iconCount.TotalScreenshotCount);
+ }
+
+ [Fact]
+ public async Task TestGetExistingIconAndImagesAsync()
+ {
+ await iconStore.LoadIconAndScreenshotsDatabaseAsync();
+
+ var icon = iconStore.GetIconUrlForId("__test_entry_DO_NOT_EDIT_PLEASE");
+ Assert.Equal("https://this.is.a.test/url/used_for/automated_unit_testing.png", icon);
+
+ var screenshots = iconStore.GetScreenshotsUrlForId("__test_entry_DO_NOT_EDIT_PLEASE");
+ Assert.Equal(3, screenshots.Length);
+ Assert.Equal("https://image_number.com/1.png", screenshots[0]);
+ Assert.Equal("https://image_number.com/2.png", screenshots[1]);
+ Assert.Equal("https://image_number.com/3.png", screenshots[2]);
+ }
+
+ [Fact]
+ public async Task TestGetNonExistingIconAndImagesAsync()
+ {
+ await iconStore.LoadIconAndScreenshotsDatabaseAsync();
+
+ var nonexistent_icon = iconStore.GetIconUrlForId("__test_entry_THIS_ICON_DOES_NOT_EXTST");
+ Assert.Empty(nonexistent_icon);
+
+ var nonexistent_screenshots = iconStore.GetScreenshotsUrlForId("__test_entry_THIS_ICON_DOES_NOT_EXTST");
+ Assert.Empty(nonexistent_screenshots);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj
new file mode 100644
index 000000000..52d9d66bd
--- /dev/null
+++ b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj
@@ -0,0 +1,32 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.IconStore/IconCacheEngine.cs b/src/UniGetUI.Core.IconStore/IconCacheEngine.cs
new file mode 100644
index 000000000..8cc7f5297
--- /dev/null
+++ b/src/UniGetUI.Core.IconStore/IconCacheEngine.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection.PortableExecutable;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using Windows.Foundation.Collections;
+
+namespace UniGetUI.Core.IconEngine
+{
+ public enum CachedIconVerificationMethod
+ {
+ None,
+ Sha256Checksum,
+ FileSize,
+ PackageVersion,
+ UriSource
+ }
+
+ public readonly struct CacheableIcon
+ {
+ public readonly Uri Url;
+ public readonly byte[] Sha256 = {};
+ public readonly string Version = "";
+ public readonly long Size = -1;
+ public readonly CachedIconVerificationMethod VerificationMethod;
+
+ public CacheableIcon(Uri uri, byte[] Sha256)
+ {
+ Url = uri;
+ this.Sha256 = Sha256;
+ VerificationMethod = CachedIconVerificationMethod.Sha256Checksum;
+ }
+
+ public CacheableIcon(Uri uri, string version)
+ {
+ Url = uri;
+ this.Version = version;
+ VerificationMethod = CachedIconVerificationMethod.PackageVersion;
+ }
+
+ public CacheableIcon(Uri uri, long size)
+ {
+ Url = uri;
+ this.Size = size;
+ VerificationMethod = CachedIconVerificationMethod.FileSize;
+ }
+
+ public CacheableIcon(Uri icon)
+ {
+ Url = icon;
+ VerificationMethod = CachedIconVerificationMethod.UriSource;
+ }
+ }
+
+ public static class IconCacheEngine
+ {
+ ///
+ /// Returns the path to the icon file, downloading it if necessary
+ ///
+ /// a CacheableIcon object representing the object
+ /// The name of the PackageManager
+ /// the Id of the package
+ /// A path to a local icon file
+ public static async Task DownloadIconOrCache(CacheableIcon? _icon, string ManagerName, string PackageId)
+ {
+ if (_icon is null) return "";
+ CacheableIcon icon = _icon ?? new CacheableIcon();
+
+ var extension = icon.Url.AbsolutePath.Substring(icon.Url.AbsolutePath.LastIndexOf('.'))[1..];
+
+ if (extension.Length > 6)
+ {
+ Logger.Warn($"Extension {extension} for file url {icon.Url} seems to be invalid, defaulting to .png");
+ extension = "png";
+ }
+
+ var FilePath = Path.Join(CoreData.UniGetUICacheDirectory_Icons, ManagerName, $"{PackageId}.{extension}");
+ var VersionPath = Path.Join(CoreData.UniGetUICacheDirectory_Icons, ManagerName, $"{PackageId}.{extension}.version");
+ var UriPath = Path.Join(CoreData.UniGetUICacheDirectory_Icons, ManagerName, $"{PackageId}.{extension}.uri");
+ var FileDirectory = Path.Join(CoreData.UniGetUICacheDirectory_Icons, ManagerName);
+ if (!Directory.Exists(FileDirectory))
+ Directory.CreateDirectory(FileDirectory);
+
+ var FileExists = File.Exists(FilePath);
+ bool IsFileValid = false;
+ if(FileExists)
+ switch (icon.VerificationMethod)
+ {
+ case CachedIconVerificationMethod.FileSize:
+ try
+ {
+ long size = await CoreTools.GetFileSizeAsyncAsLong(icon.Url);
+ IsFileValid = (size == icon.Size);
+ } catch (Exception e)
+ {
+ Logger.Warn($"Failed to verify icon file size for {icon.Url} through FileSize with error {e.Message}");
+ }
+ break;
+
+ case CachedIconVerificationMethod.Sha256Checksum:
+ try
+ {
+ byte[] hash = await CalculateFileHashAsync(FilePath);
+ IsFileValid = (hash == icon.Sha256);
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Failed to verify icon file size for {icon.Url} through Sha256 with error {e.Message}");
+ }
+ break;
+
+ case CachedIconVerificationMethod.PackageVersion:
+ try
+ {
+ if(File.Exists(VersionPath))
+ {
+ var localVersion = File.ReadAllText(VersionPath);
+ IsFileValid = (localVersion == icon.Version);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Failed to verify icon file size for {icon.Url} through PackageVersion with error {e.Message}");
+ }
+ break;
+
+ case CachedIconVerificationMethod.UriSource:
+ try
+ {
+ if (File.Exists(UriPath))
+ {
+ var localVersion = File.ReadAllText(UriPath);
+ IsFileValid = (localVersion == icon.Url.ToString());
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Failed to verify icon file size for {icon.Url} through UriSource with error {e.Message}");
+ }
+ break;
+
+ default:
+ Logger.ImportantInfo($"Icon {icon.Url} for package {PackageId} on manager {ManagerName} does not use a valid cache verification method");
+ IsFileValid = true;
+ break;
+ }
+
+ Logger.Debug($"Icon for package {PackageId} on manager {ManagerName} with Uri={icon.Url} has been determined to be {(IsFileValid? "VALID": "INVALID")} through verification method {icon.VerificationMethod}");
+
+ if(!IsFileValid)
+ using (var client = new HttpClient())
+ {
+ HttpResponseMessage response = await client.GetAsync(icon.Url);
+ response.EnsureSuccessStatusCode();
+ using (var stream = await response.Content.ReadAsStreamAsync())
+ using(FileStream fileStream = File.Create(FilePath))
+ await stream.CopyToAsync(fileStream);
+ if (icon.VerificationMethod == CachedIconVerificationMethod.PackageVersion)
+ await File.WriteAllTextAsync(VersionPath, icon.Version);
+
+ if (icon.VerificationMethod == CachedIconVerificationMethod.UriSource)
+ await File.WriteAllTextAsync(UriPath, icon.Url.ToString());
+ }
+
+ Logger.Info($"Icon for package {PackageId} stored on {FilePath}");
+ return FilePath;
+ }
+
+
+ private static async Task CalculateFileHashAsync(string filePath)
+ {
+ using (var stream = File.OpenRead(filePath))
+ using (var sha256 = SHA256.Create())
+ return await sha256.ComputeHashAsync(stream);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.IconStore/IconDatabase.cs b/src/UniGetUI.Core.IconStore/IconDatabase.cs
new file mode 100644
index 000000000..c8bad1e86
--- /dev/null
+++ b/src/UniGetUI.Core.IconStore/IconDatabase.cs
@@ -0,0 +1,127 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text.Json;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+
+namespace UniGetUI.Core.IconEngine
+{
+ public class IconDatabase
+ {
+ public struct IconCount
+ {
+ public int PackagesWithIconCount = 0;
+ public int TotalScreenshotCount = 0;
+ public int PackagesWithScreenshotCount = 0;
+ public IconCount() { }
+ }
+
+ private static IconDatabase? __instance = null;
+
+ public static IconDatabase Instance
+ {
+ get
+ {
+ if(__instance == null)
+ {
+ Logger.Error("IconStore.Instance was not initialized, creating an empty instance.");
+ InitializeInstance();
+ return Instance;
+ }
+ return __instance;
+ }
+ }
+
+ public static void InitializeInstance()
+ {
+ __instance = new();
+ }
+
+ ///
+ /// The icon and screenshot database
+ ///
+ private Dictionary IconDatabaseData = new();
+ private IconCount __icon_count = new();
+
+ ///
+ /// Tis class represents the structure of the icon and screenshot database. It is used to deserialize the JSON data.
+ ///
+
+
+ ///
+ /// Download the icon and screenshots database to a local file, and load it into memory
+ ///
+ ///
+ public async void LoadIconAndScreenshotsDatabase()
+ {
+ await LoadIconAndScreenshotsDatabaseAsync();
+ }
+
+ public async Task LoadIconAndScreenshotsDatabaseAsync()
+ {
+ string IconsAndScreenshotsFile = Path.Join(CoreData.UniGetUICacheDirectory_Data, "Icon Database.json");
+ try
+ {
+ Uri DownloadUrl = new("https://raw.githubusercontent.com/marticliment/WingetUI/main/WebBasedData/screenshot-database-v2.json");
+ if (Settings.Get("IconDataBaseURL"))
+ DownloadUrl = new Uri(Settings.GetValue("IconDataBaseURL"));
+
+ using (HttpClient client = new())
+ {
+ string fileContents = await client.GetStringAsync(DownloadUrl);
+ await File.WriteAllTextAsync(IconsAndScreenshotsFile, fileContents);
+ }
+
+ Logger.ImportantInfo("Downloaded new icons and screenshots successfully!");
+
+ }
+ catch (Exception e)
+ {
+ Logger.Warn("Failed to download icons and screenshots");
+ Logger.Warn(e);
+ }
+
+
+ if (!File.Exists(IconsAndScreenshotsFile))
+ {
+ Logger.Error("Icon Database file not found");
+ return;
+ }
+
+ try
+ {
+ IconScreenshotDatabase_v2 JsonData = JsonSerializer.Deserialize(await File.ReadAllTextAsync(IconsAndScreenshotsFile));
+ if (JsonData.icons_and_screenshots != null)
+ IconDatabaseData = JsonData.icons_and_screenshots;
+ __icon_count = new IconCount()
+ {
+ PackagesWithIconCount = JsonData.package_count.packages_with_icon,
+ PackagesWithScreenshotCount = JsonData.package_count.packages_with_screenshot,
+ TotalScreenshotCount = JsonData.package_count.total_screenshots,
+ };
+ }
+ catch (Exception ex)
+ {
+ Logger.Error("Failed to load icon and screenshot database");
+ Logger.Error(ex);
+ }
+ }
+
+ public string GetIconUrlForId(string id)
+ {
+ return IconDatabaseData.ContainsKey(id) ? IconDatabaseData[id].icon : "";
+ }
+
+ public string[] GetScreenshotsUrlForId(string id)
+ {
+ return IconDatabaseData.ContainsKey(id) ? IconDatabaseData[id].images.ToArray() : [];
+ }
+
+ public IconCount GetIconCount()
+ {
+ return __icon_count;
+ }
+
+ }
+}
diff --git a/src/UniGetUI.Core.IconStore/Serializable.cs b/src/UniGetUI.Core.IconStore/Serializable.cs
new file mode 100644
index 000000000..543fa263c
--- /dev/null
+++ b/src/UniGetUI.Core.IconStore/Serializable.cs
@@ -0,0 +1,22 @@
+namespace UniGetUI.Core.IconEngine
+{
+ internal struct IconScreenshotDatabase_v2
+ {
+ public struct PackageCount
+ {
+ public int total { get; set; }
+ public int done { get; set; }
+ public int packages_with_icon { get; set; }
+ public int packages_with_screenshot { get; set; }
+ public int total_screenshots { get; set; }
+ }
+ public struct PackageIconAndScreenshots
+ {
+ public string icon { get; set; }
+ public List images { get; set; }
+ }
+
+ public PackageCount package_count { get; set; }
+ public Dictionary icons_and_screenshots { get; set; }
+ }
+}
diff --git a/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj b/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj
new file mode 100644
index 000000000..2bc2b1dfb
--- /dev/null
+++ b/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj
@@ -0,0 +1,16 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Language.Tests/LanguageDataTests.cs b/src/UniGetUI.Core.Language.Tests/LanguageDataTests.cs
new file mode 100644
index 000000000..622aa2e1f
--- /dev/null
+++ b/src/UniGetUI.Core.Language.Tests/LanguageDataTests.cs
@@ -0,0 +1,48 @@
+using System.Text.Json.Nodes;
+using UniGetUI.Core.Classes;
+
+namespace UniGetUI.Core.Language.Tests
+{
+ public class LanguageDataTests
+ {
+ public static object[][] Translators =>
+ LanguageData.TranslatorsList.Select(x => new object[] { x }).ToArray();
+
+ public static object[][] LanguageReferences =>
+ LanguageData.LanguageReference.Select(x => new object[] { x.Key, x.Value }).ToArray();
+
+ [Fact]
+ public void TranslatorsListNotEmptyTest()
+ => Assert.NotEmpty(LanguageData.TranslatorsList);
+
+ [Theory]
+ [MemberData(nameof(Translators))]
+ public void TranslatorsListTest(Person translator)
+ => Assert.NotEmpty(translator.Name);
+
+
+ [Fact]
+ public void LanguageReferenceNotEmptyTest()
+ {
+ Assert.NotEmpty(LanguageData.LanguageReference);
+ }
+
+ [Theory]
+ [MemberData(nameof(LanguageReferences))]
+ public void LanguageReferenceTest(string key, string value)
+ {
+ Assert.False(value.Contains("NoNameLang_"), $"The language with key {key} has no assigned name");
+ }
+
+ [Fact]
+ public void TranslatedPercentageNotEmptyTests()
+ {
+ var TranslatedPercent = LanguageData.TranslationPercentages;
+ foreach (var key in TranslatedPercent.Keys)
+ {
+ Assert.True(LanguageData.LanguageReference.ContainsKey(key), $"The language key {key} was not found on LanguageReference");
+ Assert.False(LanguageData.TranslationPercentages[key].Contains("404%"), $"Somehow the key {key} has no value");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Language.Tests/LanguageEngineTests.cs b/src/UniGetUI.Core.Language.Tests/LanguageEngineTests.cs
new file mode 100644
index 000000000..667202706
--- /dev/null
+++ b/src/UniGetUI.Core.Language.Tests/LanguageEngineTests.cs
@@ -0,0 +1,80 @@
+using UniGetUI.Core.Data;
+using UniGetUI.PackageEngine.Enums;
+
+namespace UniGetUI.Core.Language.Tests
+{
+ public class LanguageEngineTests
+ {
+ [Theory]
+ [InlineData("ca", "Fes una còpia de seguretat dels paquets instal·lats")]
+ [InlineData("es", "Respaldar paquetes instalados")]
+ public void TestLoadingLanguage(string language, string translation)
+ {
+ var engine = new LanguageEngine();
+
+ engine.LoadLanguage(language);
+ Assert.Equal(translation, engine.Translate("Backup installed packages"));
+ }
+
+ [Fact]
+ public void TestLoadingLanguageForNonExistentKey()
+ {
+ //arrange
+ var engine = new LanguageEngine();
+ engine.LoadLanguage("es");
+ //act
+ var NONEXISTENT_KEY = "This is a nonexistent key thay should be returned as-is";
+ //assert
+ Assert.Equal(NONEXISTENT_KEY, engine.Translate(NONEXISTENT_KEY));
+ }
+
+ [Theory]
+ [InlineData("en", "UniGetUI Log", "UniGetUI (formerly WingetUI)")]
+ [InlineData("ca", "Registre del UniGetUI", "UniGetUI (abans WingetUI)")]
+ public void TestUniGetUIRefactoring(string language, string uniGetUILogTranslation, string uniGetUITranslation)
+ {
+ var engine = new LanguageEngine();
+
+ engine.LoadLanguage(language);
+ Assert.Equal(uniGetUILogTranslation, engine.Translate("WingetUI Log"));
+ Assert.Equal(uniGetUITranslation, engine.Translate("WingetUI"));
+ }
+
+
+ [Fact]
+ public void LocalFallbackTest()
+ {
+ var engine = new LanguageEngine();
+ engine.LoadLanguage("random-nonexistent-language");
+ Assert.Equal("en", engine.Translate("locale"));
+ }
+
+ [Fact]
+ public void TestStaticallyLoadedLanguages()
+ {
+ var engine = new LanguageEngine();
+ engine.LoadLanguage("ca");
+ engine.LoadStaticTranslation();
+ Assert.Equal("Usuari | Local", CommonTranslations.ScopeNames[PackageScope.Local]);
+ Assert.Equal("Màquina | Global", CommonTranslations.ScopeNames[PackageScope.Global]);
+
+ Assert.Equal(PackageScope.Global, CommonTranslations.InvertedScopeNames["Màquina | Global"]);
+ Assert.Equal(PackageScope.Local, CommonTranslations.InvertedScopeNames["Usuari | Local"]);
+ }
+
+ [Fact]
+ public async Task TestDownloadUpdatedTranslationsAsync()
+ {
+ var expected_file = Path.Join(CoreData.UniGetUICacheDirectory_Lang, "lang_ca.json");
+ if (File.Exists(expected_file))
+ File.Delete(expected_file);
+
+ var engine = new LanguageEngine();
+ engine.LoadLanguage("ca");
+ await engine.DownloadUpdatedLanguageFile("ca");
+
+ Assert.True(File.Exists(expected_file), "The updated file was not created");
+ File.Delete(expected_file);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj
new file mode 100644
index 000000000..14d35bf21
--- /dev/null
+++ b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj
@@ -0,0 +1,33 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/Assets/Data/LanguagesReference.json b/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
similarity index 98%
rename from src/UniGetUI/Assets/Data/LanguagesReference.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
index 986a87737..bb4d68654 100644
--- a/src/UniGetUI/Assets/Data/LanguagesReference.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Data/LanguagesReference.json
@@ -31,6 +31,7 @@
"ro": "Romanian - Română",
"ru": "Russian - Русский",
"sr": "Serbian - Srpski",
+ "sq": "Albanian - Shqip",
"si": "Sinhala - සිංහල",
"sl": "Slovene - Slovenščina",
"sv": "Swedish - Svenska",
diff --git a/src/UniGetUI/Assets/Data/TranslatedPercentages.json b/src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json
similarity index 56%
rename from src/UniGetUI/Assets/Data/TranslatedPercentages.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json
index 106c284ba..0c4cb7286 100644
--- a/src/UniGetUI/Assets/Data/TranslatedPercentages.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Data/TranslatedPercentages.json
@@ -1,22 +1,34 @@
{
- "ar": "80%",
+ "ar": "79%",
"bg": "63%",
"bn": "87%",
+ "cs": "99%",
"da": "79%",
+ "de": "99%",
"el": "99%",
"fa": "66%",
- "fi": "50%",
+ "fi": "49%",
+ "fr": "99%",
"he": "50%",
"hi": "56%",
"hr": "60%",
+ "hu": "99%",
"id": "88%",
+ "it": "99%",
"ja": "98%",
"ko": "88%",
"mk": "66%",
+ "nb": "99%",
+ "nl": "99%",
+ "nn": "99%",
"pl": "99%",
"pt_BR": "99%",
+ "pt_PT": "99%",
+ "ro": "99%",
"ru": "99%",
"si": "6%",
+ "sl": "99%",
+ "sq": "99%",
"sr": "70%",
"sv": "0%",
"tg": "15%",
@@ -24,5 +36,7 @@
"tr": "99%",
"ua": "59%",
"ur": "0%",
- "vi": "99%"
+ "vi": "99%",
+ "zh_CN": "99%",
+ "zh_TW": "99%"
}
\ No newline at end of file
diff --git a/src/UniGetUI/Assets/Data/Translators.json b/src/UniGetUI.Core.LanguageEngine/Assets/Data/Translators.json
similarity index 100%
rename from src/UniGetUI/Assets/Data/Translators.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Data/Translators.json
diff --git a/src/UniGetUI/Assets/Languages/lang_ar.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ar.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ar.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ar.json
index 30e1b8255..758f514ba 100644
--- a/src/UniGetUI/Assets/Languages/lang_ar.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ar.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "تلقائياً قم بحفظ قائمة لكل حُزمِك المثبتة لاستعادتها بسهولة.",
"Automatically save a list of your installed packages on your computer." : "تلقائياً قم بحفظ قائمة لكل حُزمِك المثبتة على جهازك.",
"Autostart WingetUI in the notifications area" : "تشغيل WingetUI تلقائياً في منطقة الإشعارات",
+ "Available Updates" : null,
"Available updates: {0}" : "التحديثات المتاحة: {0}",
"Available updates: {0}, not finished yet..." : "التحديثات المتاحة: {0}, لم يتم الانتهاء بعد...",
"Backup" : "النسخ الإحتياطي",
diff --git a/src/UniGetUI/Assets/Languages/lang_bg.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bg.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_bg.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bg.json
index 88f1bc8ee..021f39477 100644
--- a/src/UniGetUI/Assets/Languages/lang_bg.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bg.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : "Автоматично запазване на списъка на Вашите инсталирани пакети на Вашия компютър.",
"Autostart WingetUI in the notifications area" : "Автоматично стартиране на WingetUI в зоната за известия",
+ "Available Updates" : null,
"Available updates: {0}" : "Налични актуализации: {0}",
"Available updates: {0}, not finished yet..." : "Налични актуализации: {0}, още не сме готови...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_bn.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bn.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_bn.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bn.json
index ee3426d89..033559b8f 100644
--- a/src/UniGetUI/Assets/Languages/lang_bn.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_bn.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "সহজেই পুনরুদ্ধার করতে আপনার সমস্ত ইনস্টল করা প্যাকেজগুলির একটি তালিকা স্বয়ংক্রিয়ভাবে সংরক্ষণ করুন।",
"Automatically save a list of your installed packages on your computer." : "আপনার কম্পিউটারে আপনার ইনস্টল করা প্যাকেজগুলির একটি তালিকা স্বয়ংক্রিয়ভাবে সংরক্ষণ করুন।",
"Autostart WingetUI in the notifications area" : "বিজ্ঞপ্তি এলাকায় WingetUI অটোস্টার্ট করুন",
+ "Available Updates" : null,
"Available updates: {0}" : "উপলভ্য আপডেটগুলিঃ {0}",
"Available updates: {0}, not finished yet..." : "উপলব্ধ আপডেটগুলি: {0}, এখনো শেষ হয়নি...",
"Backup" : "ব্যাকআপ",
diff --git a/src/UniGetUI/Assets/Languages/lang_ca.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ca.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ca.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ca.json
index 07958f4b2..f63a335dc 100644
--- a/src/UniGetUI/Assets/Languages/lang_ca.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ca.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Desa automàticament una llista de tots els paquets instal·lats per a restaurar-los fàcilment.",
"Automatically save a list of your installed packages on your computer." : "Desa una llista dels paquets instal·lats al vostre ordinador de forma automàtica",
"Autostart WingetUI in the notifications area" : "Inicia el WingetUI a l'àrea de notificacions",
+ "Available Updates" : "Actualitzacions disponibles",
"Available updates: {0}" : "Actualitzacions disponibles: {0}",
"Available updates: {0}, not finished yet..." : "Actualitzacions disponibles: {0}, encara no hem acabat...",
"Backup" : "Fes la còpia",
diff --git a/src/UniGetUI/Assets/Languages/lang_cs.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_cs.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_cs.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_cs.json
index 4f2888346..3448d9921 100644
--- a/src/UniGetUI/Assets/Languages/lang_cs.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_cs.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Automatické uložení seznamu všech nainstalovaných balíčků pro jejich snadné obnovení.",
"Automatically save a list of your installed packages on your computer." : "Automatické uložení seznamu nainstalovaných balíčků do počítače.",
"Autostart WingetUI in the notifications area" : "Automatické spuštění WingetUI do notifikační oblasti",
+ "Available Updates" : null,
"Available updates: {0}" : "Dostupných aktualizací: {0}",
"Available updates: {0}, not finished yet..." : "Dostupných aktualizací: {0}, ještě nedokončeno...",
"Backup" : "Zálohovat",
diff --git a/src/UniGetUI/Assets/Languages/lang_da.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_da.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_da.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_da.json
index fcbc73ba4..0d452aa24 100644
--- a/src/UniGetUI/Assets/Languages/lang_da.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_da.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Gem automatisk en liste af dine installerede pakker til genoprettelse.",
"Automatically save a list of your installed packages on your computer." : "Gem automatisk en liste af dine installerede pakker på din computer.",
"Autostart WingetUI in the notifications area" : "Start WingetUI automatisk i notifikations området",
+ "Available Updates" : null,
"Available updates: {0}" : "Tilgængelige opdateringer: {0}",
"Available updates: {0}, not finished yet..." : "Tilgængelige opdateringer: {0}, endnu ikke færdiggjorte...",
"Backup" : "Backup",
diff --git a/src/UniGetUI/Assets/Languages/lang_de.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_de.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_de.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_de.json
index f4380dc77..06b6036a8 100644
--- a/src/UniGetUI/Assets/Languages/lang_de.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_de.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Liste von alle auf dem Computer installierten Paketen automatisch speichern",
"Automatically save a list of your installed packages on your computer." : "Liste von auf dem Computer installierten Paketen automatisch speichern",
"Autostart WingetUI in the notifications area" : "WingetUI automatisch im Infobereich starten",
+ "Available Updates" : null,
"Available updates: {0}" : "Verfügbare Updates: {0}",
"Available updates: {0}, not finished yet..." : "Verfügbare Updates: {0}, noch nicht abgeschlossen...",
"Backup" : "Sichern",
diff --git a/src/UniGetUI/Assets/Languages/lang_el.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_el.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_el.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_el.json
index ce5b6af2d..1982d4d3b 100644
--- a/src/UniGetUI/Assets/Languages/lang_el.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_el.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Αυτόματη αποθήκευση μιας λίστας με όλα τα εγκατεστημένα πακέτα σας για εύκολη επαναφορά.",
"Automatically save a list of your installed packages on your computer." : "Αυτόματη αποθήκευση μιας λίστας με τα εγκατεστημένα πακέτα στον υπολογιστή σας.",
"Autostart WingetUI in the notifications area" : "Αυτόματη εκκίνηση του WingetUI στην περιοχή ειδοποιήσεων",
+ "Available Updates" : null,
"Available updates: {0}" : "Διαθέσιμες ενημερώσεις: {0}",
"Available updates: {0}, not finished yet..." : "Διαθέσιμες ενημερώσεις: {0}, δεν έχει ολοκληρωθεί ακόμα...",
"Backup" : "Δημιουργία αντιγράφου ασφαλείας",
diff --git a/src/UniGetUI/Assets/Languages/lang_en.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_en.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_en.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_en.json
index 675207044..3f7c62147 100644
--- a/src/UniGetUI/Assets/Languages/lang_en.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_en.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : null,
+ "Available Updates" : null,
"Available updates: {0}" : null,
"Available updates: {0}, not finished yet..." : null,
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_es.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_es.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_es.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_es.json
index 8cea74976..a1fa5752c 100644
--- a/src/UniGetUI/Assets/Languages/lang_es.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_es.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Salvar automáticamente una lista de todos tus paquetes instalados para fácilmente restaurarlos.",
"Automatically save a list of your installed packages on your computer." : "Salvar automáticamente una lista de tus paquetes instalados en tu computador.",
"Autostart WingetUI in the notifications area" : "Iniciar WingetUI automáticamente en el área de notificaciones",
+ "Available Updates" : "Actualizaciones disponibles",
"Available updates: {0}" : "Actualizaciones disponibles: {0}",
"Available updates: {0}, not finished yet..." : "Actualizaciones disponibles: {0}, no ha acabado todavía...",
"Backup" : "Respaldar",
diff --git a/src/UniGetUI/Assets/Languages/lang_fa.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fa.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_fa.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fa.json
index 98268fa2e..1216496fb 100644
--- a/src/UniGetUI/Assets/Languages/lang_fa.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fa.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "WingetUI را به صورت خودکار در قسمت اعلان ها راه اندازی کنید\n",
+ "Available Updates" : null,
"Available updates: {0}" : "به روز رسانی های موجود: {0}",
"Available updates: {0}, not finished yet..." : "به روز رسانی های موجود: {0}، هنوز تمام نشده است...\n",
"Backup" : "پشتیبان گیری",
diff --git a/src/UniGetUI/Assets/Languages/lang_fi.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fi.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_fi.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fi.json
index df9dd9704..bf9683f30 100644
--- a/src/UniGetUI/Assets/Languages/lang_fi.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fi.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Tallenna automaattisesti luettelo kaikista asennetuista paketeista, jotta voit palauttaa ne helposti.",
"Automatically save a list of your installed packages on your computer." : "Tallenna automaattisesti luettelo asennetuista paketeista tietokoneellesi.",
"Autostart WingetUI in the notifications area" : "Käynnistä WingetUI automaattisesti ilmoitusalueella",
+ "Available Updates" : null,
"Available updates: {0}" : "Saatavilla olevat päivitykset: {0},",
"Available updates: {0}, not finished yet..." : "Saatavilla olevat päivitykset: {0}, ei vielä valmis...",
"Backup" : "Varmuuskopioi",
diff --git a/src/UniGetUI/Assets/Languages/lang_fr.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fr.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_fr.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fr.json
index aaf33d263..3fe3f4339 100644
--- a/src/UniGetUI/Assets/Languages/lang_fr.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_fr.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Enregistrer automatiquement une liste de tous les paquets installés pour les restaurer facilement.",
"Automatically save a list of your installed packages on your computer." : "Enregistrer automatiquement une liste de vos paquets installés sur votre ordinateur.",
"Autostart WingetUI in the notifications area" : "Démarrer automatiquement WingetUI dans la zone de notification",
+ "Available Updates" : null,
"Available updates: {0}" : "Mises à jour disponibles : {0}",
"Available updates: {0}, not finished yet..." : "Mises à jour disponibles : {0}, pas encore terminé...",
"Backup" : "Sauvegarder",
diff --git a/src/UniGetUI/Assets/Languages/lang_he.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_he.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_he.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_he.json
index ad7cad576..745b1247f 100644
--- a/src/UniGetUI/Assets/Languages/lang_he.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_he.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "הפעל אוטומטית את WingetUI במרכז ההודעות",
+ "Available Updates" : null,
"Available updates: {0}" : "עדכונים זמינים: {0}",
"Available updates: {0}, not finished yet..." : "עדכונים זמינים: {0}, טרם הושלמו...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_hi.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hi.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_hi.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hi.json
index b3128b2d3..db4d0e35d 100644
--- a/src/UniGetUI/Assets/Languages/lang_hi.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hi.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "सूचना क्षेत्र में WingetUI ऑटोस्टार्ट करें",
+ "Available Updates" : null,
"Available updates: {0}" : "उपलब्ध अपडेट: {0}",
"Available updates: {0}, not finished yet..." : "\nउपलब्ध अपडेट: {0}, अभी तक समाप्त नहीं हुआ...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_hr.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hr.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_hr.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hr.json
index 7638663fa..029e83c47 100644
--- a/src/UniGetUI/Assets/Languages/lang_hr.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hr.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "Automatski pokrenite WingetUI u području obavijesti",
+ "Available Updates" : null,
"Available updates: {0}" : "Dostupna ažuriranja: {0}",
"Available updates: {0}, not finished yet..." : "Dostupna ažuriranja: {0}, još nisu završena...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_hu.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hu.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_hu.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hu.json
index cdf382c7d..a504ccca3 100644
--- a/src/UniGetUI/Assets/Languages/lang_hu.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_hu.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Autom. elmenti az összes telepített csomag listáját, hogy könnyen visszaállíthassa azokat.",
"Automatically save a list of your installed packages on your computer." : "Automatikusan elmenti a telepített csomagok listáját a számítógépen.",
"Autostart WingetUI in the notifications area" : "A WingetUI auto. indítása az értesítési területen",
+ "Available Updates" : null,
"Available updates: {0}" : "Elérhető frissítések: {0}",
"Available updates: {0}, not finished yet..." : "Elérhető frissítések: {0}, még nincs kész...",
"Backup" : "Biztonsági mentés",
diff --git a/src/UniGetUI/Assets/Languages/lang_id.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_id.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_id.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_id.json
index 41e458cfc..826064431 100644
--- a/src/UniGetUI/Assets/Languages/lang_id.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_id.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Secara otomatis menyimpan daftar semua paket yang Anda instal untuk memulihkannya dengan mudah.",
"Automatically save a list of your installed packages on your computer." : "Secara otomatis menyimpan daftar paket yang Anda instal di komputer Anda.",
"Autostart WingetUI in the notifications area" : "Mulai otomatis WingetUI di bagian notifikasi",
+ "Available Updates" : null,
"Available updates: {0}" : "Pembaruan tersedia: {0}",
"Available updates: {0}, not finished yet..." : "Pembaruan tersedia: {0}, belum selesai...\n",
"Backup" : "Cadangkan",
diff --git a/src/UniGetUI/Assets/Languages/lang_it.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_it.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_it.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_it.json
index 35946afdd..5fece446d 100644
--- a/src/UniGetUI/Assets/Languages/lang_it.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_it.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Salva automaticamente un elenco di tutti i pacchetti installati per ripristinarli facilmente.",
"Automatically save a list of your installed packages on your computer." : "Salva automaticamente l'elenco dei pacchetti installati sul computer.",
"Autostart WingetUI in the notifications area" : "Avvia automaticamente WingetUI nell'area delle notifiche",
+ "Available Updates" : null,
"Available updates: {0}" : "Aggiornamenti disponibili: {0}",
"Available updates: {0}, not finished yet..." : "Aggiornamenti disponibili: {0}, ma non ho ancora terminato il controllo...",
"Backup" : "Backup",
diff --git a/src/UniGetUI/Assets/Languages/lang_ja.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ja.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ja.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ja.json
index 095c80264..6ac9c612b 100644
--- a/src/UniGetUI/Assets/Languages/lang_ja.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ja.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "インストール済みパッケージの一覧を自動的に保存し、簡単に復元できるようにします。",
"Automatically save a list of your installed packages on your computer." : "インストール済みパッケージの一覧を自動的にコンピューターに保存する",
"Autostart WingetUI in the notifications area" : "WingetUIを通知領域で自動起動する",
+ "Available Updates" : null,
"Available updates: {0}" : "利用可能なアップデート: {0}",
"Available updates: {0}, not finished yet..." : "利用可能なアップデート: {0}、進行中...",
"Backup" : "バックアップ",
diff --git a/src/UniGetUI/Assets/Languages/lang_ko.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ko.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ko.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ko.json
index 62e3c3a90..6181295a4 100644
--- a/src/UniGetUI/Assets/Languages/lang_ko.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ko.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "설치된 모든 패키지 목록을 자동으로 저장하여 쉽게 복원할 수 있습니다.",
"Automatically save a list of your installed packages on your computer." : "설치된 패키지 목록을 컴퓨터에 자동으로 저장합니다.",
"Autostart WingetUI in the notifications area" : "알림 영역에서 WingetUI 자동 시작",
+ "Available Updates" : null,
"Available updates: {0}" : "사용 가능한 업데이트: {0}",
"Available updates: {0}, not finished yet..." : "사용 가능한 업데이트: {0}, 진행 중...",
"Backup" : "백업",
diff --git a/src/UniGetUI/Assets/Languages/lang_mk.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_mk.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_mk.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_mk.json
index cedc53bce..9a66545d4 100644
--- a/src/UniGetUI/Assets/Languages/lang_mk.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_mk.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Автоматски зачувајте листа со сите ваши инсталирани пакети за лесно да ги вратите.",
"Automatically save a list of your installed packages on your computer." : "Автоматски зачувајте листа со инсталираните пакети на вашиот компјутер.",
"Autostart WingetUI in the notifications area" : "Автоматско стартување на WingetUI во областа за известувања",
+ "Available Updates" : null,
"Available updates: {0}" : "Достапни ажурирања: {0}",
"Available updates: {0}, not finished yet..." : "Достапни ажурирања: {0}, сè уште не е завршено...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_nb.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nb.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_nb.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nb.json
index 46cc43ca7..a6e71a64d 100644
--- a/src/UniGetUI/Assets/Languages/lang_nb.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nb.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Lagre en liste over alle dine installerte pakker automatisk for å forenkle gjenoppretting av dem.",
"Automatically save a list of your installed packages on your computer." : "Lagre en liste over dine installerte pakker på datamaskinen din automatisk.",
"Autostart WingetUI in the notifications area" : "Start WingetUI automatisk i varselfeltet",
+ "Available Updates" : null,
"Available updates: {0}" : "Tilgjengelige oppdateringer: {0}",
"Available updates: {0}, not finished yet..." : "Tilgjengelige oppdateringer: {0}, jobber fortsatt...",
"Backup" : "Ta backup",
diff --git a/src/UniGetUI/Assets/Languages/lang_nl.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nl.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_nl.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nl.json
index 85f4376eb..16a1785a1 100644
--- a/src/UniGetUI/Assets/Languages/lang_nl.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nl.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Automatisch een lijst opslaan van al je geïnstalleerde pakketten om ze gemakkelijk te herstellen.",
"Automatically save a list of your installed packages on your computer." : "Automatisch een lijst opslaan met de op je computer geïnstalleerde pakketten.",
"Autostart WingetUI in the notifications area" : "WingetUI automatisch starten in het systeemvak",
+ "Available Updates" : null,
"Available updates: {0}" : "Beschikbare updates: {0}",
"Available updates: {0}, not finished yet..." : "Beschikbare updates: {0}, bijna klaar…",
"Backup" : "Back-up",
diff --git a/src/UniGetUI/Assets/Languages/lang_nn.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nn.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_nn.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nn.json
index 7e08754c8..cbbbc484d 100644
--- a/src/UniGetUI/Assets/Languages/lang_nn.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_nn.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Lagre ei liste over alle dine installerte pakkar automatisk for å forenkle gjenoppretting av dei.",
"Automatically save a list of your installed packages on your computer." : "Lagre ei liste over dine installerte pakkar på datamaskina di automatisk",
"Autostart WingetUI in the notifications area" : "Start WingetUI automatisk i varslingsfeltet",
+ "Available Updates" : null,
"Available updates: {0}" : "Tilgjengelege oppdateringar: {0}",
"Available updates: {0}, not finished yet..." : "Tilgjengelege oppdateringar: {0}, jobbar framleis...",
"Backup" : "Ta backup",
diff --git a/src/UniGetUI/Assets/Languages/lang_pl.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pl.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_pl.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pl.json
index ee5a8ed6d..2492e202b 100644
--- a/src/UniGetUI/Assets/Languages/lang_pl.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pl.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Automatyczne zapisywanie listy wszystkich zainstalowanych pakietów w celu ich łatwego przywrócenia.",
"Automatically save a list of your installed packages on your computer." : "Automatycznie zapisz listę zainstalowanych pakietów na komputerze.",
"Autostart WingetUI in the notifications area" : "Autostart WingetUI w obszarze powiadomień",
+ "Available Updates" : null,
"Available updates: {0}" : "Dostępne aktualizacje: {0}",
"Available updates: {0}, not finished yet..." : "Dostępne aktualizacje: {0}, jeszcze szukam...",
"Backup" : "Zrób kopię",
diff --git a/src/UniGetUI/Assets/Languages/lang_pt_BR.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_BR.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_pt_BR.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_BR.json
index 0ce98465a..620a61bcd 100644
--- a/src/UniGetUI/Assets/Languages/lang_pt_BR.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_BR.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Salve automaticamente uma lista de todos os seus pacotes instalados para restaurá-los facilmente.",
"Automatically save a list of your installed packages on your computer." : "Salvar automaticamente uma lista dos pacotes instalados no seu computador.",
"Autostart WingetUI in the notifications area" : "Iniciar o WingetUI na área de notificações",
+ "Available Updates" : null,
"Available updates: {0}" : "Atualizações disponíveis: {0} ",
"Available updates: {0}, not finished yet..." : "Atualizações disponíveis: {0}, ainda não terminou...",
"Backup" : "Backup",
diff --git a/src/UniGetUI/Assets/Languages/lang_pt_PT.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_PT.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_pt_PT.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_PT.json
index ad02b7001..f248b7411 100644
--- a/src/UniGetUI/Assets/Languages/lang_pt_PT.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_pt_PT.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Guardar automaticamente uma lista de todos os pacotes instalados para ser mas fácil reinstalá-los.",
"Automatically save a list of your installed packages on your computer." : "Guardar automaticamente uma lista dos pacotes instalados no teu computador.",
"Autostart WingetUI in the notifications area" : "Iniciar automaticamente o WingetUI para a área de notificações",
+ "Available Updates" : null,
"Available updates: {0}" : "Atualizações disponíveis: {0} ",
"Available updates: {0}, not finished yet..." : "Atualizações disponíveis: {0}, ainda não terminou...",
"Backup" : "Cópia de segurança",
diff --git a/src/UniGetUI/Assets/Languages/lang_ro.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ro.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ro.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ro.json
index 5aab22e19..b7cf3efd0 100644
--- a/src/UniGetUI/Assets/Languages/lang_ro.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ro.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Salvează automat o listă a tuturor pachetelor instalate pentru a putea să le restaurezi cu ușurință",
"Automatically save a list of your installed packages on your computer." : "Salvează automat o listă a pachetelor instalate pe calculatorul tău.",
"Autostart WingetUI in the notifications area" : "Pornește automat WingetUI în zona de notificări",
+ "Available Updates" : null,
"Available updates: {0}" : "Actualizări disponibile: {0}",
"Available updates: {0}, not finished yet..." : "Actualizări disponibile: {0}, căutare în curs...",
"Backup" : "Fă o copie de siguranță",
diff --git a/src/UniGetUI/Assets/Languages/lang_ru.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ru.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ru.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ru.json
index a10fd9bcf..d1d9b9297 100644
--- a/src/UniGetUI/Assets/Languages/lang_ru.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ru.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Автоматически сохраняйте список всех установленных вами пакетов, чтобы легко восстановить их.",
"Automatically save a list of your installed packages on your computer." : "Автоматическое сохранение списка установленных пакетов на вашем компьютере.",
"Autostart WingetUI in the notifications area" : "Автозапуск WingetUI в области уведомлений",
+ "Available Updates" : null,
"Available updates: {0}" : "Доступно обновлений: {0}",
"Available updates: {0}, not finished yet..." : "Доступно обновлений: {0}, еще не завершено...",
"Backup" : "Сделать копию",
diff --git a/src/UniGetUI/Assets/Languages/lang_si.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_si.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_si.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_si.json
index 68a70e61a..85dad01f5 100644
--- a/src/UniGetUI/Assets/Languages/lang_si.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_si.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : null,
+ "Available Updates" : null,
"Available updates: {0}" : null,
"Available updates: {0}, not finished yet..." : null,
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_sl.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sl.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_sl.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sl.json
index 9863ae79f..bf1b41093 100644
--- a/src/UniGetUI/Assets/Languages/lang_sl.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sl.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Samodejno shranite seznam vseh nameščenih paketov, da jih preprosto obnovite.",
"Automatically save a list of your installed packages on your computer." : "Samodejno shranite seznam svojih nameščenih paketov v svoj računalnik.",
"Autostart WingetUI in the notifications area" : "Samodejni zagon WingetUI v območje za obvestila",
+ "Available Updates" : null,
"Available updates: {0}" : "Razpoložljive posodobitve: {0}",
"Available updates: {0}, not finished yet..." : "Razpoložljive posodobitve: {0}, še nedokončane...",
"Backup" : "Varnostna kopija",
diff --git a/src/UniGetUI/Assets/Languages/lang_sq.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sq.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_sq.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sq.json
index b72b5da78..4ddc9befe 100644
--- a/src/UniGetUI/Assets/Languages/lang_sq.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sq.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Ruaj automatikisht një listë të të gjitha paketave tuaja të instaluara për t'i rikthyer ato lehtësisht.",
"Automatically save a list of your installed packages on your computer." : "Ruaj automatikisht një listë të paketave tuaja të instaluara në kompjuterin tënd.",
"Autostart WingetUI in the notifications area" : "Nis automatikisht WingetUI në hapësirën e njoftimeve",
+ "Available Updates" : null,
"Available updates: {0}" : "Përditësimet e ofruara: {0}",
"Available updates: {0}, not finished yet..." : "Përditësimet e ofruara: {0}, nuk ka përfunduar ende...",
"Backup" : "Bëj një kopje rezervë",
diff --git a/src/UniGetUI/Assets/Languages/lang_sr.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sr.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_sr.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sr.json
index fb3d83b10..9d3ef0c72 100644
--- a/src/UniGetUI/Assets/Languages/lang_sr.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sr.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Аутоматски сачувај листу свих инсталираних пакета због лакшег враћања.",
"Automatically save a list of your installed packages on your computer." : "Аутоматски сачувај листу инсталираних пакета на рачунару.",
"Autostart WingetUI in the notifications area" : "Аутоматски покрени WingetUI међу нотификацијама",
+ "Available Updates" : null,
"Available updates: {0}" : "Доступне надоградње: {0}",
"Available updates: {0}, not finished yet..." : "Доспутне надоградње: {0}, није још завршено...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_sv.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sv.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_sv.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sv.json
index 4132720ad..67b23261e 100644
--- a/src/UniGetUI/Assets/Languages/lang_sv.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_sv.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : null,
+ "Available Updates" : null,
"Available updates: {0}" : null,
"Available updates: {0}, not finished yet..." : null,
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_tg.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tg.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_tg.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tg.json
index bdff7e1f5..fb05f73a4 100644
--- a/src/UniGetUI/Assets/Languages/lang_tg.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tg.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "Laging buksan ang WingetUI sa lugar ng mga abiso",
+ "Available Updates" : null,
"Available updates: {0}" : "Mga maaaring i-update: {0}",
"Available updates: {0}, not finished yet..." : "Mga maaaring i-update: {0}, hindi pa nakakatapos ang iba...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_th.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_th.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_th.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_th.json
index 025979136..5081faf4d 100644
--- a/src/UniGetUI/Assets/Languages/lang_th.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_th.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "บันทึกรายการแพ็กเกจทั้งหมดที่ติดตั้งไว้โดยอัตโนมัติเพื่อทำให้การกู้คืนง่ายขึ้น",
"Automatically save a list of your installed packages on your computer." : "บันทึกรายการแพ็กเกจที่ติดตั้งบนคอมพิวเตอร์ของคุณโดยอัตโนมัติ",
"Autostart WingetUI in the notifications area" : "เริ่ม WingetUI อัตโนมัติในถาดการแจ้งเตือน",
+ "Available Updates" : null,
"Available updates: {0}" : "อัปเดตที่พบ: {0}",
"Available updates: {0}, not finished yet..." : "อัปเดตที่พบ: {0} และยังไม่เสร็จ...",
"Backup" : "สำรองข้อมูล",
diff --git a/src/UniGetUI/Assets/Languages/lang_tr.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tr.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_tr.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tr.json
index cffbf3bcc..f3998b59c 100644
--- a/src/UniGetUI/Assets/Languages/lang_tr.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_tr.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Kolayca geri yüklemek için yüklü tüm paketlerinizin bir listesini otomatik olarak kaydedin.",
"Automatically save a list of your installed packages on your computer." : "Yüklü paketlerinizin bir listesini otomatik olarak bilgisayarınıza kaydedin.",
"Autostart WingetUI in the notifications area" : "WingetUI'yi bildirim alanında otomatik başlat",
+ "Available Updates" : null,
"Available updates: {0}" : "Mevcut güncellemeler : {0}",
"Available updates: {0}, not finished yet..." : "Mevcut güncellemeler : {0}, henüz bitmedi...",
"Backup" : "Yedekle",
diff --git a/src/UniGetUI/Assets/Languages/lang_ua.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ua.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ua.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ua.json
index 0f5dba1ee..7b5671bc4 100644
--- a/src/UniGetUI/Assets/Languages/lang_ua.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ua.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : "Автозапуск WingetUI в області сповіщень",
+ "Available Updates" : null,
"Available updates: {0}" : "Доступні оновлення: {0}",
"Available updates: {0}, not finished yet..." : "Доступні оновлення: {0}, ще не завершено...",
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_ur.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ur.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_ur.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ur.json
index 0759cd34d..7384d081b 100644
--- a/src/UniGetUI/Assets/Languages/lang_ur.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_ur.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : null,
"Automatically save a list of your installed packages on your computer." : null,
"Autostart WingetUI in the notifications area" : null,
+ "Available Updates" : null,
"Available updates: {0}" : null,
"Available updates: {0}, not finished yet..." : null,
"Backup" : null,
diff --git a/src/UniGetUI/Assets/Languages/lang_vi.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_vi.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_vi.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_vi.json
index b2b6e9fbe..5a5ef11ef 100644
--- a/src/UniGetUI/Assets/Languages/lang_vi.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_vi.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "Tự động lưu một danh sách tất cả các gói bạn đã cài đặt để dễ dàng khôi phục chúng sau này.",
"Automatically save a list of your installed packages on your computer." : "Tự động lưu danh sách những gói đã cài đặt trên máy tính của bạn.",
"Autostart WingetUI in the notifications area" : "Tự động chạy WingetUI trong khu vực thông báo",
+ "Available Updates" : null,
"Available updates: {0}" : "Cập nhật khả dụng: {0}",
"Available updates: {0}, not finished yet..." : "Cập nhật khả dụng: {0}, chưa hoàn tất...",
"Backup" : "Sao lưu",
diff --git a/src/UniGetUI/Assets/Languages/lang_zh_CN.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_CN.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_zh_CN.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_CN.json
index 239d4aba2..4d0e1cfd5 100644
--- a/src/UniGetUI/Assets/Languages/lang_zh_CN.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_CN.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "自动保存所有已安装软件的列表以便于恢复它们。",
"Automatically save a list of your installed packages on your computer." : "在您的计算机上自动保存所有已安装软件包的列表。",
"Autostart WingetUI in the notifications area" : "开机自动启动 WingetUI 并最小化到任务栏",
+ "Available Updates" : null,
"Available updates: {0}" : "可用更新:{0}",
"Available updates: {0}, not finished yet..." : "可用更新:{0},仍在进行中...",
"Backup" : "备份",
diff --git a/src/UniGetUI/Assets/Languages/lang_zh_TW.json b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_TW.json
similarity index 99%
rename from src/UniGetUI/Assets/Languages/lang_zh_TW.json
rename to src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_TW.json
index c6eb3b2f4..158d0e876 100644
--- a/src/UniGetUI/Assets/Languages/lang_zh_TW.json
+++ b/src/UniGetUI.Core.LanguageEngine/Assets/Languages/lang_zh_TW.json
@@ -59,6 +59,7 @@
"Automatically save a list of all your installed packages to easily restore them." : "自動儲存已安裝的套件清單以便輕鬆還原它們。",
"Automatically save a list of your installed packages on your computer." : "將已安裝的套件清單自動儲存到您的電腦。",
"Autostart WingetUI in the notifications area" : "開機時啟動 WingetUI 並顯示系統匣圖示",
+ "Available Updates" : null,
"Available updates: {0}" : "{0} 個可用的更新",
"Available updates: {0}, not finished yet..." : "已發現 {0} 個可用的更新,仍在繼續進行中...",
"Backup" : "備份",
diff --git a/src/UniGetUI.Core.LanguageEngine/LanguageData.cs b/src/UniGetUI.Core.LanguageEngine/LanguageData.cs
new file mode 100644
index 000000000..f05952ea4
--- /dev/null
+++ b/src/UniGetUI.Core.LanguageEngine/LanguageData.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text.Json.Nodes;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Classes;
+using System.Collections.ObjectModel;
+
+namespace UniGetUI.Core.Language
+{
+ public static class LanguageData
+ {
+ ///
+ /// Returns
+ ///
+ private static Person[]? __translators_list;
+
+ public static Person[] TranslatorsList
+ {
+ get
+ {
+ if (__translators_list == null)
+ __translators_list = LoadLanguageTranslatorList();
+
+ return __translators_list;
+ }
+ }
+
+ private static ReadOnlyDictionary? __language_reference;
+ public static ReadOnlyDictionary LanguageReference
+ {
+ get {
+ if (__language_reference == null)
+ __language_reference = LoadLanguageReference();
+ return __language_reference;
+ }
+ }
+
+ private static ReadOnlyDictionary? __translation_percentages;
+ public static ReadOnlyDictionary TranslationPercentages
+ {
+ get
+ {
+ if (__translation_percentages == null)
+ __translation_percentages = LoadTranslationPercentages();
+ return __translation_percentages;
+ }
+ }
+
+ private static ReadOnlyDictionary LoadTranslationPercentages()
+ {
+ JsonObject? val = JsonObject.Parse(File.ReadAllText(Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Data", "TranslatedPercentages.json"))) as JsonObject;
+ if (val != null)
+ return new(val.ToDictionary(x => x.Key, x => (x.Value ?? ("404%" + x.Key)).ToString()));
+ else
+ return new(new Dictionary());
+ }
+
+ private static ReadOnlyDictionary LoadLanguageReference()
+ {
+ JsonObject? val = JsonObject.Parse(File.ReadAllText(Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Data", "LanguagesReference.json"))) as JsonObject;
+ if (val != null)
+ return new(val.ToDictionary(x => x.Key, x => (x.Value ?? ("NoNameLang_" + x.Key)).ToString()));
+ else
+ return new(new Dictionary());
+ }
+
+ private static Person[] LoadLanguageTranslatorList()
+ {
+ var JsonContents = File.ReadAllText(Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Data", "Translators.json"));
+ JsonObject? TranslatorsInfo = JsonNode.Parse(JsonContents) as JsonObject;
+
+ if (TranslatorsInfo == null) return [];
+
+ List result = new();
+ foreach (var langKey in TranslatorsInfo)
+ {
+ if (!LanguageReference.ContainsKey(langKey.Key))
+ {
+ Logger.Warn($"Language {langKey.Key} not in list, maybe has not been added yet?");
+ continue;
+ }
+
+ JsonArray TranslatorsForLang = (langKey.Value ?? new JsonArray()).AsArray();
+ bool LangShown = false;
+ foreach (JsonNode? translator in TranslatorsForLang)
+ {
+ if (translator is null) continue;
+
+ Uri? url = null;
+ if (translator["link"] != null && translator["link"]?.ToString() != "")
+ url = new Uri((translator["link"] ?? "").ToString());
+
+ Person person = new(
+ Name: (url != null ? "@" : "") + (translator["name"] ?? "").ToString(),
+ ProfilePicture: url != null ? new Uri(url.ToString() + ".png") : null,
+ GitHubUrl: url,
+ Language: !LangShown ? LanguageData.LanguageReference[langKey.Key] : ""
+ );
+ LangShown = true;
+ result.Add(person);
+ }
+ }
+
+ return result.ToArray();
+ }
+ }
+
+ public static class CommonTranslations
+ {
+ public static readonly Dictionary ArchNames = new()
+ {
+ { Architecture.X64, "x64" },
+ { Architecture.X86, "x86" },
+ { Architecture.Arm64, "arm64" },
+ { Architecture.Arm, "arm32" },
+ };
+
+ public static readonly Dictionary InvertedArchNames = new()
+ {
+ { "x64", Architecture.X64 },
+ { "x86", Architecture.X86 },
+ { "arm64", Architecture.Arm64 },
+ { "arm32", Architecture.Arm },
+ };
+
+ public static readonly Dictionary ScopeNames = new()
+ {
+ { PackageScope.Global, "Machine | Global" },
+ { PackageScope.Local, "User | Local" },
+ };
+
+ public static readonly Dictionary InvertedScopeNames = new()
+ {
+ { "Machine | Global", PackageScope.Global },
+ { "User | Local", PackageScope.Local },
+ };
+
+ public static readonly Dictionary ScopeNames_NonLang = new()
+ {
+ { PackageScope.Global, "mac" +
+ "hine" },
+ { PackageScope.Local, "user" },
+ };
+
+ public static readonly Dictionary InvertedScopeNames_NonLang = new()
+ {
+ { "machine", PackageScope.Global },
+ { "user", PackageScope.Local },
+ };
+ }
+}
+
diff --git a/src/UniGetUI.Core.LanguageEngine/LanguageEngine.cs b/src/UniGetUI.Core.LanguageEngine/LanguageEngine.cs
new file mode 100644
index 000000000..bccf0a302
--- /dev/null
+++ b/src/UniGetUI.Core.LanguageEngine/LanguageEngine.cs
@@ -0,0 +1,152 @@
+using System.Text.Json.Nodes;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.PackageEngine.Enums;
+
+namespace UniGetUI.Core.Language
+{
+ public class LanguageEngine
+ {
+ private Dictionary MainLangDict = new();
+
+ public LanguageEngine(string ForceLanguage = "")
+ {
+ string LangName = Settings.GetValue("PreferredLanguage");
+ if (LangName == "default" || LangName == "")
+ {
+ LangName = System.Globalization.CultureInfo.CurrentCulture.ToString().Replace("-", "_");
+ }
+ LoadLanguage((ForceLanguage != "")? ForceLanguage: LangName);
+ }
+
+ ///
+ /// Loads the specified language into the current instance
+ ///
+ /// the language code
+ public void LoadLanguage(string lang)
+ {
+ if (LanguageData.LanguageReference.ContainsKey(lang))
+ {
+ MainLangDict = LoadLanguageFile(lang);
+ MainLangDict.TryAdd("locale", lang);
+ }
+ else if (LanguageData.LanguageReference.ContainsKey(lang[0..2]))
+ {
+ MainLangDict = LoadLanguageFile(lang[0..2]);
+ MainLangDict.TryAdd("locale", lang[0..2]);
+ }
+ else
+ {
+ MainLangDict = LoadLanguageFile("en");
+ MainLangDict.TryAdd("locale", "en");
+ }
+ LoadStaticTranslation();
+ Logger.Info("Loaded language locale: " + MainLangDict["locale"]);
+ }
+
+ public Dictionary LoadLanguageFile(string LangKey, bool ForceBundled = false)
+ {
+ try
+ {
+ Dictionary LangDict = new();
+ string LangFileToLoad = Path.Join(CoreData.UniGetUICacheDirectory_Lang, "lang_" + LangKey + ".json");
+
+ if (!File.Exists(LangFileToLoad) || Settings.Get("DisableLangAutoUpdater"))
+ {
+ ForceBundled = true;
+ }
+
+ if (ForceBundled)
+ {
+ LangFileToLoad = Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Languages", "lang_" + LangKey + ".json");
+ }
+
+ var __LangDict = (JsonNode.Parse(File.ReadAllText(LangFileToLoad)) as JsonObject)?.ToDictionary(x => x.Key, x => x.Value != null ? x.Value.ToString() : "");
+
+ if (__LangDict != null)
+ LangDict = __LangDict;
+ else
+ Logger.Error($"Deserialization of language file {LangFileToLoad} resulted in a null object");
+
+ if (!Settings.Get("DisableLangAutoUpdater"))
+ _ = DownloadUpdatedLanguageFile(LangKey);
+
+ return LangDict;
+ }
+ catch (Exception e)
+ {
+ Logger.Error($"LoadLanguageFile Failed for LangKey={LangKey}, ForceBundled={ForceBundled}");
+ Logger.Error(e);
+ return new Dictionary();
+ }
+ }
+
+ ///
+ /// Downloads and saves an updated version of the translations for the specified language.
+ ///
+ /// The Id of the language to download
+ /// Use the new or the old Url (should not be used manually)
+ ///
+ public async Task DownloadUpdatedLanguageFile(string LangKey, bool UseOldUrl = false)
+ {
+ try
+ {
+ Uri NewFile = new("https://raw.githubusercontent.com/marticliment/WingetUI/main/src/" + (UseOldUrl ? "wingetui" : "UniGetUI") + "/Assets/Languages/lang_" + LangKey + ".json");
+
+ HttpClient client = new();
+ string fileContents = await client.GetStringAsync(NewFile);
+
+ if (!Directory.Exists(CoreData.UniGetUICacheDirectory_Lang))
+ Directory.CreateDirectory(CoreData.UniGetUICacheDirectory_Lang);
+
+ File.WriteAllText(Path.Join(CoreData.UniGetUICacheDirectory_Lang, "lang_" + LangKey + ".json"), fileContents);
+
+ Logger.ImportantInfo("Lang files were updated successfully from GitHub");
+ }
+ catch (Exception e)
+ {
+ if (e is HttpRequestException && !UseOldUrl)
+ await DownloadUpdatedLanguageFile(LangKey, true);
+ else
+ {
+ Logger.Warn("Could not download updated translations from GitHub");
+ Logger.Warn(e);
+ }
+ }
+ }
+
+ public void LoadStaticTranslation()
+ {
+ CommonTranslations.ScopeNames[PackageScope.Local] = Translate("User | Local");
+ CommonTranslations.ScopeNames[PackageScope.Global] = Translate("Machine | Global");
+
+ CommonTranslations.InvertedScopeNames.Clear();
+ CommonTranslations.InvertedScopeNames.Add(Translate("Machine | Global"), PackageScope.Global);
+ CommonTranslations.InvertedScopeNames.Add(Translate("User | Local"), PackageScope.Local);
+ }
+
+ public string Translate(string key)
+ {
+ if (key == "WingetUI")
+ {
+ if (MainLangDict.ContainsKey("formerly WingetUI") && MainLangDict["formerly WingetUI"] != "")
+ return "UniGetUI (" + MainLangDict["formerly WingetUI"] + ")";
+ return "UniGetUI (formerly WingetUI)";
+ }
+ else if (key == "Formerly known as WingetUI")
+ {
+ if (MainLangDict.ContainsKey(key))
+ return MainLangDict[key];
+ return key;
+ }
+
+ if (key == null || key == "")
+ return "";
+ else if (MainLangDict.ContainsKey(key) && MainLangDict[key] != "")
+ return MainLangDict[key].Replace("WingetUI", "UniGetUI");
+ else
+ return key.Replace("WingetUI", "UniGetUI");
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj b/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj
new file mode 100644
index 000000000..5f08487d6
--- /dev/null
+++ b/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj
@@ -0,0 +1,86 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/src/UniGetUI.Core.Logger/LogEntry.cs b/src/UniGetUI.Core.Logger/LogEntry.cs
new file mode 100644
index 000000000..25dba2fff
--- /dev/null
+++ b/src/UniGetUI.Core.Logger/LogEntry.cs
@@ -0,0 +1,26 @@
+namespace UniGetUI.Core.Logging
+{
+ public readonly struct LogEntry
+ {
+ public enum SeverityLevel
+ {
+ Debug,
+ Info,
+ Success,
+ Warning,
+ Error,
+ }
+
+ public readonly DateTime Time { get; }
+ public readonly String Content { get; }
+ public readonly SeverityLevel Severity { get; }
+
+ public LogEntry(string content, SeverityLevel severity)
+ {
+ Time = DateTime.Now;
+ Content = content;
+ Severity = severity;
+ }
+
+ }
+}
diff --git a/src/UniGetUI.Core.Logger/Logger.cs b/src/UniGetUI.Core.Logger/Logger.cs
new file mode 100644
index 000000000..27b8ee172
--- /dev/null
+++ b/src/UniGetUI.Core.Logger/Logger.cs
@@ -0,0 +1,78 @@
+using Diagnostics = System.Diagnostics;
+
+namespace UniGetUI.Core.Logging
+{
+ public static class Logger
+ {
+ private static readonly List LogContents = new();
+
+ // String parameter log functions
+ public static void ImportantInfo(string s)
+ {
+ Diagnostics.Debug.WriteLine(s);
+ LogContents.Add(new LogEntry(s, LogEntry.SeverityLevel.Success));
+ }
+
+ public static void Debug(string s)
+ {
+ Diagnostics.Debug.WriteLine(s);
+ LogContents.Add(new LogEntry(s, LogEntry.SeverityLevel.Debug));
+ }
+
+ public static void Info(string s)
+ {
+ Diagnostics.Debug.WriteLine(s);
+ LogContents.Add(new LogEntry(s, LogEntry.SeverityLevel.Info));
+ }
+
+ public static void Warn(string s)
+ {
+ Diagnostics.Debug.WriteLine(s);
+ LogContents.Add(new LogEntry(s, LogEntry.SeverityLevel.Warning));
+ }
+
+ public static void Error(string s)
+ {
+ Diagnostics.Debug.WriteLine(s);
+ LogContents.Add(new LogEntry(s, LogEntry.SeverityLevel.Error));
+ }
+
+
+ // Exception parameter log functions
+ public static void ImportantInfo(Exception e)
+ {
+ Diagnostics.Debug.WriteLine(e.ToString());
+ LogContents.Add(new LogEntry(e.ToString() , LogEntry.SeverityLevel.Success));
+ }
+
+ public static void Debug(Exception e)
+ {
+ Diagnostics.Debug.WriteLine(e.ToString());
+ LogContents.Add(new LogEntry(e.ToString(), LogEntry.SeverityLevel.Debug));
+ }
+
+ public static void Info(Exception e)
+ {
+ Diagnostics.Debug.WriteLine(e.ToString());
+ LogContents.Add(new LogEntry(e.ToString(), LogEntry.SeverityLevel.Info));
+ }
+
+ public static void Warn(Exception e)
+ {
+ Diagnostics.Debug.WriteLine(e.ToString());
+ LogContents.Add(new LogEntry(e.ToString(), LogEntry.SeverityLevel.Warning));
+ }
+
+ public static void Error(Exception e)
+ {
+ Diagnostics.Debug.WriteLine(e.ToString());
+ LogContents.Add(new LogEntry(e.ToString(), LogEntry.SeverityLevel.Error));
+ }
+
+
+ public static LogEntry[] GetLogs()
+ {
+ return LogContents.ToArray();
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj b/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj
new file mode 100644
index 000000000..1897680a2
--- /dev/null
+++ b/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj
@@ -0,0 +1,9 @@
+
+
+
+
+
+ enable
+
+
+
diff --git a/src/UniGetUI.Core.Logging.Tests/LogEntryTests.cs b/src/UniGetUI.Core.Logging.Tests/LogEntryTests.cs
new file mode 100644
index 000000000..ae29196c7
--- /dev/null
+++ b/src/UniGetUI.Core.Logging.Tests/LogEntryTests.cs
@@ -0,0 +1,37 @@
+namespace UniGetUI.Core.Logging.Tests
+{
+ public class LogEntryTests
+ {
+ [Fact]
+ public async Task TestLogEntry()
+ {
+ var startTime = DateTime.Now;
+
+ await Task.Delay(100);
+
+ var logEntry1 = new LogEntry("Hello World", LogEntry.SeverityLevel.Info);
+ await Task.Delay(50);
+ var logEntry2 = new LogEntry("Hello World 2", LogEntry.SeverityLevel.Debug);
+ await Task.Delay(50);
+ var logEntry3 = new LogEntry("Hello World 3", LogEntry.SeverityLevel.Error);
+
+ await Task.Delay(100);
+
+ var endTime = DateTime.Now;
+
+ Assert.Equal("Hello World", logEntry1.Content);
+ Assert.Equal("Hello World 2", logEntry2.Content);
+ Assert.Equal("Hello World 3", logEntry3.Content);
+
+ Assert.Equal(LogEntry.SeverityLevel.Info, logEntry1.Severity);
+ Assert.Equal(LogEntry.SeverityLevel.Debug, logEntry2.Severity);
+ Assert.Equal(LogEntry.SeverityLevel.Error, logEntry3.Severity);
+
+ Assert.True(logEntry1.Time > startTime && logEntry1.Time < endTime);
+ Assert.True(logEntry2.Time > startTime && logEntry2.Time < endTime);
+ Assert.True(logEntry3.Time > startTime && logEntry3.Time < endTime);
+ Assert.True(logEntry1.Time < logEntry2.Time);
+ Assert.True(logEntry2.Time < logEntry3.Time);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Logging.Tests/LoggerTests.cs b/src/UniGetUI.Core.Logging.Tests/LoggerTests.cs
new file mode 100644
index 000000000..4eb16996c
--- /dev/null
+++ b/src/UniGetUI.Core.Logging.Tests/LoggerTests.cs
@@ -0,0 +1,34 @@
+namespace UniGetUI.Core.Logging.Tests
+{
+ public class LoggerTests
+ {
+ [Fact]
+ public void TestLogger()
+ {
+ var startTime = DateTime.Now;
+ Logger.Info("Hello World");
+ Logger.Debug("Hello World 2");
+ Logger.Error("Hello World 3");
+ Logger.Warn(new Exception("Test exception"));
+
+ var endTime = DateTime.Now;
+
+ var logs = Logger.GetLogs();
+
+ Assert.Equal("Hello World", logs[0].Content);
+ Assert.Equal("Hello World 2", logs[1].Content);
+ Assert.Equal("Hello World 3", logs[2].Content);
+ Assert.Equal("System.Exception: Test exception", logs[3].Content);
+
+ Assert.Equal(LogEntry.SeverityLevel.Info, logs[0].Severity);
+ Assert.Equal(LogEntry.SeverityLevel.Debug, logs[1].Severity);
+ Assert.Equal(LogEntry.SeverityLevel.Error, logs[2].Severity);
+ Assert.Equal(LogEntry.SeverityLevel.Warning, logs[3].Severity);
+
+ Assert.True(logs[0].Time > startTime && logs[0].Time < endTime);
+ Assert.True(logs[1].Time > startTime && logs[1].Time < endTime);
+ Assert.True(logs[2].Time > startTime && logs[2].Time < endTime);
+ Assert.True(logs[3].Time > startTime && logs[3].Time < endTime);
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj
new file mode 100644
index 000000000..95886c86c
--- /dev/null
+++ b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj
@@ -0,0 +1,33 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Settings.Tests/SettingsTest.cs b/src/UniGetUI.Core.Settings.Tests/SettingsTest.cs
new file mode 100644
index 000000000..7bb3884a8
--- /dev/null
+++ b/src/UniGetUI.Core.Settings.Tests/SettingsTest.cs
@@ -0,0 +1,68 @@
+using UniGetUI.Core.Data;
+using UniGetUI.Core.SettingsEngine;
+
+namespace UniGetUI.Core.SettingsEgine.Tests
+{
+ public class SettingsTest
+ {
+ [Theory]
+ [InlineData("TestSetting1", true, false, false, true)]
+ [InlineData("TestSetting2", true, false, false, false)]
+ [InlineData("Test.Settings_with", true, false, true, true)]
+ [InlineData("TestSettingEntry With A Space", false, true, false, false)]
+ [InlineData("ª", false, false, false, false)]
+ [InlineData("VeryVeryLongTestSettingEntrySoTheClassCanReallyBeStressedOut", true, false, true, true)]
+ public void TestBooleanSettings(string SettingName, bool st1, bool st2, bool st3, bool st4)
+ {
+ Settings.Set(SettingName, st1);
+ Assert.Equal(st1, Settings.Get(SettingName));
+ Assert.Equal(st1, File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.Set(SettingName, st2);
+ Assert.Equal(st2, Settings.Get(SettingName));
+ Assert.Equal(st2, File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.Set(SettingName, st3);
+ Assert.Equal(st3, Settings.Get(SettingName));
+ Assert.Equal(st3, File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.Set(SettingName, st4);
+ Assert.Equal(st4, Settings.Get(SettingName));
+ Assert.Equal(st4, File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.Set(SettingName, false); // Cleanup
+ Assert.False(Settings.Get(SettingName));
+ Assert.False(File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+ }
+
+ [Theory]
+ [InlineData("TestSetting1", "RandomFirstValue", "RandomSecondValue", "", "RandomThirdValue")]
+ [InlineData("ktjgshdfsd", "", "", "", "RandomThirdValue")]
+ [InlineData("ª", "RandomFirstValue", " ", "\t", "RandomThirdValue")]
+ [InlineData("TestSettingEntry With A Space", "RandomFirstValue", "", "", "")]
+ [InlineData("VeryVeryLongTestSettingEntrySoTheClassCanReallyBeStressedOut", "\x00\x01\x02\u0003", "", "", "RandomThirdValue")]
+ public void TestValueSettings(string SettingName, string st1, string st2, string st3, string st4)
+ {
+ Settings.SetValue(SettingName, st1);
+ Assert.Equal(st1, Settings.GetValue(SettingName));
+ Assert.Equal((st1 != ""), File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.SetValue(SettingName, st2);
+ Assert.Equal(st2, Settings.GetValue(SettingName));
+ Assert.Equal((st2 != ""), File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.SetValue(SettingName, st3);
+ Assert.Equal(st3, Settings.GetValue(SettingName));
+ Assert.Equal((st3 != ""), File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.SetValue(SettingName, st4);
+ Assert.Equal(st4, Settings.GetValue(SettingName));
+ Assert.Equal((st4 != ""), File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+
+ Settings.Set(SettingName, false); // Cleanup
+ Assert.False(Settings.Get(SettingName));
+ Assert.Equal("", Settings.GetValue(SettingName));
+ Assert.False(File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, SettingName)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj
new file mode 100644
index 000000000..bd8b5a416
--- /dev/null
+++ b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Settings/SettingsEngine.cs b/src/UniGetUI.Core.Settings/SettingsEngine.cs
new file mode 100644
index 000000000..328b6d5fc
--- /dev/null
+++ b/src/UniGetUI.Core.Settings/SettingsEngine.cs
@@ -0,0 +1,58 @@
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+
+namespace UniGetUI.Core.SettingsEngine
+{
+ public static class Settings
+ {
+ public static bool Get(string setting, bool invert = false)
+ {
+ return File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, setting)) ^ invert;
+ }
+
+ public static void Set(string setting, bool value)
+ {
+ try
+ {
+ if (value)
+ {
+ if (!File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, setting)))
+ File.WriteAllText(Path.Join(CoreData.UniGetUIDataDirectory, setting), "");
+ }
+ else
+ {
+ if (File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, setting)))
+ File.Delete(Path.Join(CoreData.UniGetUIDataDirectory, setting));
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Error($"CANNOT SET SETTING FOR setting={setting} enabled={value}");
+ Logger.Error(e);
+ }
+ }
+
+ public static string GetValue(string setting)
+ {
+ if (!File.Exists(Path.Join(CoreData.UniGetUIDataDirectory, setting)))
+ return "";
+ return File.ReadAllText(Path.Join(CoreData.UniGetUIDataDirectory, setting));
+ }
+
+ public static void SetValue(string setting, string value)
+ {
+ try
+ {
+ if (value == "")
+ Set(setting, false);
+ else
+ File.WriteAllText(Path.Join(CoreData.UniGetUIDataDirectory, setting), value);
+ }
+ catch (Exception e)
+ {
+ Logger.Error($"CANNOT SET SETTING VALUE FOR setting={setting} enabled={value}");
+ Logger.Error(e);
+ }
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj b/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj
new file mode 100644
index 000000000..da1d54a30
--- /dev/null
+++ b/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj
@@ -0,0 +1,13 @@
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Structs/Person.cs b/src/UniGetUI.Core.Structs/Person.cs
new file mode 100644
index 000000000..813cc6dac
--- /dev/null
+++ b/src/UniGetUI.Core.Structs/Person.cs
@@ -0,0 +1,24 @@
+using System.Collections.Specialized;
+
+namespace UniGetUI.Core.Structs
+{
+ public readonly struct Person
+ {
+ public readonly string Name;
+ public readonly Uri? ProfilePicture;
+ public readonly Uri? GitHubUrl;
+ public readonly bool HasPicture;
+ public readonly bool HasGitHubProfile;
+ public readonly string Language;
+
+ public Person(string Name, Uri? ProfilePicture = null, Uri? GitHubUrl = null, string Language = "")
+ {
+ this.Name = Name;
+ this.ProfilePicture = ProfilePicture;
+ this.HasPicture = ProfilePicture != null;
+ this.GitHubUrl = GitHubUrl;
+ this.HasPicture = GitHubUrl != null;
+ this.Language = Language;
+ }
+ }
+}
diff --git a/src/UniGetUI.Core.Structs/UniGetUI.Core.Structs.csproj b/src/UniGetUI.Core.Structs/UniGetUI.Core.Structs.csproj
new file mode 100644
index 000000000..fa71b7ae6
--- /dev/null
+++ b/src/UniGetUI.Core.Structs/UniGetUI.Core.Structs.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs b/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs
new file mode 100644
index 000000000..8bf379d41
--- /dev/null
+++ b/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs
@@ -0,0 +1,120 @@
+using System.Diagnostics;
+using UniGetUI.Core.Language;
+
+namespace UniGetUI.Core.Tools.Tests
+{
+ public class ToolsTests
+ {
+ [Theory]
+ [InlineData("NonExistentString", false)]
+ [InlineData(" ", false)]
+ [InlineData("", false)]
+ [InlineData("@@", false)]
+ [InlineData("0 packages found", true)]
+ [InlineData("Add packages or open an existing bundle", true)]
+ public void TranslateFunctionTester(string textEntry, bool TranslationExists)
+ {
+ var langEngine = new LanguageEngine("fr");
+ CoreTools.ReloadLanguageEngineInstance("fr");
+
+ Assert.Equal(CoreTools.Translate(textEntry), langEngine.Translate(textEntry));
+
+ if (TranslationExists)
+ Assert.NotEqual(CoreTools.Translate(textEntry), textEntry);
+ else
+ Assert.Equal(CoreTools.Translate(textEntry), textEntry);
+
+ Assert.Equal(CoreTools.AutoTranslated(textEntry), textEntry);
+ }
+
+ [Fact]
+ public async Task TestWhichFunctionForExistingFile()
+ {
+ var result = await CoreTools.Which("cmd.exe");
+ Assert.True(result.Item1);
+ Assert.True(File.Exists(result.Item2));
+ }
+
+ [Fact]
+ public async Task TestWhichFunctionForNonExistingFile()
+ {
+ var result = await CoreTools.Which("nonexistentfile.exe");
+ Assert.False(result.Item1);
+ Assert.Equal("", result.Item2);
+ }
+
+ [Theory]
+ [InlineData("7zip19.00-helpEr", "7zip19.00 HelpEr")]
+ [InlineData("packagename", "Packagename")]
+ [InlineData("Packagename", "Packagename")]
+ [InlineData("PackageName", "PackageName")]
+ [InlineData("pacKagENaMe", "PacKagENaMe")]
+ [InlineData("PACKAGENAME", "PACKAGENAME")]
+ [InlineData("package-Name", "Package Name")]
+ [InlineData("pub-name/pkg-version_2.00.portable", "Pkg Version 2.00")]
+ [InlineData("!helloWorld", "!helloWorld")]
+ [InlineData("@stylistic/eslint-plugin", "Eslint Plugin")]
+ [InlineData("Flask-RESTful", "Flask RESTful")]
+ public void TestFormatAsName(string id, string name)
+ {
+ Assert.Equal(name, CoreTools.FormatAsName(id));
+ }
+
+ [Theory]
+ [InlineData(89)]
+ [InlineData(33)]
+ [InlineData(558)]
+ [InlineData(12)]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(64)]
+ public void TestRandomStringGenerator(int length)
+ {
+ var string1 = CoreTools.RandomString(length);
+ var string2 = CoreTools.RandomString(length);
+ var string3 = CoreTools.RandomString(length);
+ Assert.Equal(string1.Length, length);
+ Assert.Equal(string2.Length, length);
+ Assert.Equal(string3.Length, length);
+
+ // Zero-lenghted strings are always equal
+ // One-lenghted strings are likely to be equal
+ if (length > 1)
+ {
+ Assert.NotEqual(string1, string2);
+ Assert.NotEqual(string2, string3);
+ Assert.NotEqual(string1, string3);
+ }
+
+ foreach (string s in new string[] { string1, string2, string3})
+ foreach (char c in s)
+ Assert.True("abcdefghijklmnopqrstuvwxyz0123456789".Contains(c));
+ }
+
+ [Theory]
+ [InlineData("", 0)]
+ [InlineData("https://invalid.url.com/this/is/an/invalid.php?file=to_test&if=the&code_returns=zero", 0)]
+ [InlineData("https://www.marticliment.com/wingetui/wingetui_size_test.txt", 460)]
+ public async Task TestFileSizeLoader(string uri, long expectedSize)
+ {
+ var size = await CoreTools.GetFileSizeAsync(uri != ""? new Uri(uri): null);
+ Assert.Equal(expectedSize / 1048576, size);
+ }
+
+ [Theory]
+ [InlineData("1000.0", 1000.0, 0.0)]
+ [InlineData("2.4", 2.4, 0.001)]
+ [InlineData("33a.12-beta", 33.12, 0.0)]
+ [InlineData("0", 0.0, 0.0)]
+ [InlineData("", -1, 0.0)]
+ [InlineData("dfgfdsgdfg", -1, 0.0)]
+ [InlineData("-12", 12.0, 0.0)]
+ [InlineData("4.0.0.1.0", 4.001, 0.01)]
+ [InlineData("2024.30.04.1223", 2024.30041223, 0.0)]
+ [InlineData("0.0", 0.0, 0.0)]
+ public void TestGetVersionStringAsFloat(string version, double expected, double tolerance)
+ {
+ Assert.Equal(expected, CoreTools.GetVersionStringAsFloat(version), tolerance);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj
new file mode 100644
index 000000000..c74d66cc4
--- /dev/null
+++ b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+
+
+
+ enable
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Core.Tools/Tools.cs b/src/UniGetUI.Core.Tools/Tools.cs
new file mode 100644
index 000000000..a45ccabc7
--- /dev/null
+++ b/src/UniGetUI.Core.Tools/Tools.cs
@@ -0,0 +1,299 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Net;
+using System.Security.Principal;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Language;
+using UniGetUI.Core.Logging;
+
+namespace UniGetUI.Core.Tools
+{
+ public static class CoreTools
+ {
+
+ public static readonly HttpClientHandler HttpClientConfig = new HttpClientHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.All
+ };
+
+ private static LanguageEngine? LanguageEngine;
+
+ ///
+ /// Translate a string to the current language
+ ///
+ /// The string to translate
+ /// The translated string if available, the original string otherwise
+ public static string Translate(string text)
+ {
+ if(LanguageEngine == null) LanguageEngine = new LanguageEngine();
+ return LanguageEngine.Translate(text);
+ }
+
+ public static void ReloadLanguageEngineInstance(string ForceLanguage = "")
+ {
+ LanguageEngine = new LanguageEngine(ForceLanguage);
+ }
+
+ ///
+ /// Dummy function to capture the strings that need to be translated but the translation is handled by a custom widget
+ ///
+ ///
+ ///
+ public static string AutoTranslated(string text)
+ {
+ return text;
+ }
+
+ ///
+ /// Launches the self executable on a new process and kills the current process
+ ///
+ public static void RelaunchProcess()
+ {
+ Logger.Debug("Launching process: " + Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe"));
+ Process.Start(Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe"));
+ Logger.Warn("About to kill process");
+ Environment.Exit(0);
+ }
+
+ ///
+ /// Finds an executable in path and returns its location
+ ///
+ /// The executable alias to find
+ /// A tuple containing: a boolean hat represents wether the path was found or not; the path to the file if found.
+ public static async Task> Which(string command)
+ {
+ Process process = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = "cmd.exe",
+ Arguments = "/C where " + command,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true
+ }
+ };
+ process.Start();
+ string? line = await process.StandardOutput.ReadLineAsync();
+ string output;
+ if (line == null)
+ output = "";
+ else
+ output = line.Trim();
+ await process.WaitForExitAsync();
+ if (process.ExitCode != 0 || output == "")
+ return new Tuple(false, "");
+ else
+ return new Tuple(File.Exists(output), output);
+ }
+
+ ///
+ /// Formats a given package id as a name, capitalizing words and replacing separators with spaces
+ ///
+ /// A string containing the Id of a package
+ /// The formatted string
+ public static string FormatAsName(string name)
+ {
+ name = name.Replace(".install", "").Replace(".portable", "").Replace("-", " ").Replace("_", " ").Split("/")[^1];
+ string newName = "";
+ for (int i = 0; i < name.Length; i++)
+ {
+ if (i == 0 || name[i - 1] == ' ')
+ newName += name[i].ToString().ToUpper();
+ else
+ newName += name[i];
+ }
+ return newName;
+ }
+
+ ///
+ /// Generates a random string composed of alphanumeric characters and numbers
+ ///
+ /// The length of the string
+ /// A string
+ public static string RandomString(int length)
+ {
+ Random random = new();
+ const string pool = "abcdefghijklmnopqrstuvwxyz0123456789";
+ IEnumerable chars = Enumerable.Range(0, length)
+ .Select(x => pool[random.Next(0, pool.Length)]);
+ return new string(chars.ToArray());
+ }
+
+ public static void ReportFatalException(Exception e)
+ {
+ string LangName = "Unknown";
+ try
+ {
+ LangName = Translate("langName");
+ }
+ catch { }
+
+ string Error_String = $@"
+ OS: {Environment.OSVersion.Platform}
+ Version: {Environment.OSVersion.VersionString}
+ OS Architecture: {Environment.Is64BitOperatingSystem}
+ APP Architecture: {Environment.Is64BitProcess}
+ Language: {LangName}
+ APP Version: {CoreData.VersionName}
+ Executable: {Environment.ProcessPath}
+
+Crash Message: {e.Message}
+
+Crash Traceback:
+{e.StackTrace}";
+
+ Console.WriteLine(Error_String);
+
+
+ string ErrorBody = "https://www.marticliment.com/error-report/?appName=UniGetUI^&errorBody=" + Uri.EscapeDataString(Error_String.Replace("\n", "{l}"));
+
+ Console.WriteLine(ErrorBody);
+
+ using System.Diagnostics.Process cmd = new();
+ cmd.StartInfo.FileName = "cmd.exe";
+ cmd.StartInfo.RedirectStandardInput = true;
+ cmd.StartInfo.RedirectStandardOutput = false;
+ cmd.StartInfo.CreateNoWindow = true;
+ cmd.StartInfo.UseShellExecute = false;
+ cmd.Start();
+ cmd.StandardInput.WriteLine("start " + ErrorBody);
+ cmd.StandardInput.WriteLine("exit");
+ cmd.WaitForExit();
+ Environment.Exit(1);
+
+ }
+
+ ///
+ /// Launches a .bat or .cmd file for the given filename
+ ///
+ /// The path of the batch file
+ /// The title of the window
+ /// Whether the batch file should be launched elevated or not
+ public static async void LaunchBatchFile(string path, string WindowTitle = "", bool RunAsAdmin = false)
+ {
+ Process p = new();
+ p.StartInfo.FileName = "cmd.exe";
+ p.StartInfo.Arguments = "/C start \"" + WindowTitle + "\" \"" + path + "\"";
+ p.StartInfo.UseShellExecute = true;
+ p.StartInfo.CreateNoWindow = true;
+ p.StartInfo.Verb = RunAsAdmin ? "runas" : "";
+ p.Start();
+ await p.WaitForExitAsync();
+ }
+
+ ///
+ /// Checks whether the current process has administrator privileges
+ ///
+ /// True if the process has administrator privileges
+ public static bool IsAdministrator()
+ {
+ try
+ {
+ return (new WindowsPrincipal(WindowsIdentity.GetCurrent()))
+ .IsInRole(WindowsBuiltInRole.Administrator);
+ }
+ catch (Exception e)
+ {
+ Logger.Warn("Could not check if user is administrator");
+ Logger.Warn(e);
+ return false;
+ }
+ }
+
+ ///
+ /// Returns the size (in MB) of the file at the given URL
+ ///
+ /// a valid Uri object containing a URL to a file
+ /// a double representing the size in MBs, 0 if the process fails
+ public static async Task GetFileSizeAsync(Uri? url)
+ {
+ return await GetFileSizeAsyncAsLong(url) / 1048576;
+ }
+
+ public static async Task GetFileSizeAsyncAsLong(Uri? url)
+ {
+ if(url == null)
+ return 0;
+
+ try
+ {
+#pragma warning disable SYSLIB0014 // Type or member is obsolete
+ WebRequest req = WebRequest.Create(url);
+#pragma warning restore SYSLIB0014 // Type or member is obsolete
+ req.Method = "HEAD";
+ WebResponse resp = await req.GetResponseAsync();
+ long ContentLength;
+ if (long.TryParse(resp.Headers.Get("Content-Length"), out ContentLength))
+ {
+ return ContentLength;
+ }
+
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Could not load file size for url={url}");
+ Logger.Warn(e);
+ }
+ return 0;
+ }
+
+ public static double GetVersionStringAsFloat(string Version)
+ {
+ try
+ {
+ string _ver = "";
+ bool _dotAdded = false;
+ foreach (char _char in Version)
+ {
+ if (char.IsDigit(_char))
+ _ver += _char;
+ else if (_char == '.')
+ {
+ if (!_dotAdded)
+ {
+ _ver += _char;
+ _dotAdded = true;
+ }
+ }
+ }
+ double res = -1;
+ if (_ver != "" && _ver != ".")
+ try
+ {
+ var val = double.Parse(_ver, CultureInfo.InvariantCulture);
+ return val;
+ }
+ catch { }
+ return res;
+ }
+ catch
+ {
+ Logger.Warn($"Failed to parse version {Version} to float");
+ return -1;
+ }
+ }
+
+ ///
+ /// Returns the query that can be safely passed as a command-line parameter
+ ///
+ /// The query to make safe
+ /// The safe version of the query
+ public static string EnsureSafeQueryString(string query)
+ {
+ return query.Replace(";", string.Empty)
+ .Replace("&", string.Empty)
+ .Replace("|", string.Empty)
+ .Replace(">", string.Empty)
+ .Replace("<", string.Empty)
+ .Replace("%", string.Empty)
+ .Replace("\"", string.Empty)
+ .Replace("'", string.Empty)
+ .Replace("\\", string.Empty)
+ .Replace("`", string.Empty);
+ }
+ }
+}
+
diff --git a/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj b/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj
new file mode 100644
index 000000000..13c8e6fab
--- /dev/null
+++ b/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj
@@ -0,0 +1,15 @@
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.Interface.Enums/Enums.cs b/src/UniGetUI.Interface.Enums/Enums.cs
new file mode 100644
index 000000000..b1dfc85c7
--- /dev/null
+++ b/src/UniGetUI.Interface.Enums/Enums.cs
@@ -0,0 +1,16 @@
+namespace UniGetUI.Interface.Enums
+{
+ ///
+ /// Represents the visual status of a package on a list
+ ///
+ public enum PackageTag
+ {
+ Default,
+ AlreadyInstalled,
+ IsUpgradable,
+ Pinned,
+ OnQueue,
+ BeingProcessed,
+ Failed
+ }
+}
diff --git a/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj b/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj
new file mode 100644
index 000000000..293f74341
--- /dev/null
+++ b/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj
@@ -0,0 +1,10 @@
+
+
+
+ net8.0
+ enable
+ enable
+ AnyCPU;x64;ARM64
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Enums/Enums.cs b/src/UniGetUI.PackageEngine.Enums/Enums.cs
new file mode 100644
index 000000000..6c3a40535
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Enums/Enums.cs
@@ -0,0 +1,53 @@
+namespace UniGetUI.PackageEngine.Enums
+{
+ ///
+ /// Represents the installation scope of a package
+ ///
+ public enum PackageScope
+ {
+ Global = 1,
+ Machine = 1,
+ Local = 0,
+ User = 0,
+ }
+
+ public enum DeserializedPackageStatus
+ {
+ ManagerNotFound,
+ ManagerNotEnabled,
+ ManagerNotReady,
+ SourceNotFound,
+ IsAvailable
+ }
+
+ public enum BundleFormatType
+ {
+ JSON,
+ YAML,
+ XML
+ }
+
+
+ public enum OperationVeredict
+ {
+ Succeeded,
+ Failed,
+ AutoRetry,
+ }
+ public enum OperationStatus
+ {
+ Pending,
+ Running,
+ Succeeded,
+ Failed,
+ Cancelled
+ }
+
+ public enum OperationType
+ {
+ Install,
+ Update,
+ Uninstall,
+ None
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Enums.csproj b/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Enums.csproj
new file mode 100644
index 000000000..ba2ecaa37
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Enums.csproj
@@ -0,0 +1,8 @@
+
+
+
+
+ enable
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs
new file mode 100644
index 000000000..dc6ae467c
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs
@@ -0,0 +1,339 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.Managers.PowerShellManager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.ChocolateyManager
+{
+ public class Chocolatey : BaseNuGet
+ {
+ new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_IDS = new string[] { "Directory", "", "Did", "Features?", "Validation", "-", "being", "It", "Error", "L'accs", "Maximum", "This", "Output is package name ", "operable", "Invalid" };
+ new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "", "Did", "Features?", "Validation", "-", "being", "It", "Error", "L'accs", "Maximum", "This", "packages", "current version", "installed version", "is", "program", "validations", "argument", "no" };
+
+ public Chocolatey() : base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ CanSkipIntegrityChecks = true,
+ CanRunInteractively = true,
+ SupportsCustomVersions = true,
+ SupportsCustomArchitectures = true,
+ SupportedCustomArchitectures = new Architecture[] { Architecture.X86 },
+ SupportsPreRelease = true,
+ SupportsCustomSources = true,
+ SupportsCustomPackageIcons = true,
+ Sources = new ManagerSource.Capabilities()
+ {
+ KnowsPackageCount = false,
+ KnowsUpdateDate = false,
+ }
+ };
+
+ Properties = new ManagerProperties()
+ {
+ Name = "Chocolatey",
+ Description = CoreTools.Translate("The classic package manager for windows. You'll find everything there.
Contains: General Software"),
+ IconId = "choco",
+ ColorIconId = "choco_color",
+ ExecutableFriendlyName = "choco.exe",
+ InstallVerb = "install",
+ UninstallVerb = "uninstall",
+ UpdateVerb = "upgrade",
+ ExecutableCallArgs = "",
+ KnownSources = [new ManagerSource(this, "community", new Uri("https://community.chocolatey.org/api/v2/"))],
+ DefaultSource = new ManagerSource(this, "community", new Uri("https://community.chocolatey.org/api/v2/")),
+
+ };
+
+ SourceProvider = new ChocolateySourceProvider(this);
+
+ }
+
+ protected override async Task GetAvailableUpdates_UnSafe()
+ {
+ Process p = new();
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " outdated",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ p.Start();
+ string? line;
+ string output = "";
+ List Packages = new();
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (!line.StartsWith("Chocolatey"))
+ {
+ string[] elements = line.Split('|');
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (elements.Length <= 2)
+ continue;
+
+ if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]) || elements[1] == elements[2])
+ continue;
+
+ Packages.Add(new UpgradablePackage(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], DefaultSource, this));
+ }
+ }
+
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+
+ await p.WaitForExitAsync();
+
+ return Packages.ToArray();
+ }
+
+ protected override async Task GetInstalledPackages_UnSafe()
+ {
+ Process p = new();
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " list",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ p.Start();
+ string? line;
+ string output = "";
+ List Packages = new();
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (!line.StartsWith("Chocolatey"))
+ {
+ string[] elements = line.Split(' ');
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (elements.Length <= 1)
+ continue;
+
+ if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
+ continue;
+
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this));
+ }
+ }
+
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+
+ await p.WaitForExitAsync();
+
+ return Packages.ToArray();
+ }
+ public override OperationVeredict GetInstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ string output_string = string.Join("\n", Output);
+
+ if (ReturnCode == 1641 || ReturnCode == 0)
+ return OperationVeredict.Succeeded;
+ else if (ReturnCode == 3010)
+ return OperationVeredict.Succeeded; // TODO: Restart required
+ else if ((output_string.Contains("Run as administrator") || output_string.Contains("The requested operation requires elevation") || output_string.Contains("ERROR: Exception calling \"CreateDirectory\" with \"1\" argument(s): \"Access to the path")) && !options.RunAsAdministrator)
+ {
+ options.RunAsAdministrator = true;
+ return OperationVeredict.AutoRetry;
+ }
+ return OperationVeredict.Failed;
+ }
+
+ public override OperationVeredict GetUpdateOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ return GetInstallOperationVeredict(package, options, ReturnCode, Output);
+ }
+
+ public override OperationVeredict GetUninstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ string output_string = string.Join("\n", Output);
+
+ if (ReturnCode == 1641 || ReturnCode == 1614 || ReturnCode == 1605 || ReturnCode == 0)
+ return OperationVeredict.Succeeded;
+ else if (ReturnCode == 3010)
+ return OperationVeredict.Succeeded; // TODO: Restart required
+ else if ((output_string.Contains("Run as administrator") || output_string.Contains("The requested operation requires elevation")) && !options.RunAsAdministrator)
+ {
+ options.RunAsAdministrator = true;
+ return OperationVeredict.AutoRetry;
+ }
+ return OperationVeredict.Failed;
+ }
+ public override string[] GetInstallParameters(Package package, InstallationOptions options)
+ {
+ List parameters = GetUninstallParameters(package, options).ToList();
+ parameters[0] = Properties.InstallVerb;
+ parameters.Add("--no-progress");
+
+ if (options.Architecture == System.Runtime.InteropServices.Architecture.X86)
+ parameters.Add("--forcex86");
+
+ if (options.PreRelease)
+ parameters.Add("--prerelease");
+
+ if (options.SkipHashCheck)
+ parameters.AddRange(new string[] { "--ignore-checksums", "--force" });
+
+ if (options.Version != "")
+ parameters.AddRange(new string[] { "--version=" + options.Version, "--allow-downgrade" });
+
+ return parameters.ToArray();
+ }
+ public override string[] GetUpdateParameters(Package package, InstallationOptions options)
+ {
+ string[] parameters = GetInstallParameters(package, options);
+ parameters[0] = Properties.UpdateVerb;
+ return parameters;
+ }
+
+ public override string[] GetUninstallParameters(Package package, InstallationOptions options)
+ {
+ List parameters = new() { Properties.UninstallVerb, package.Id, "-y" };
+
+ if (options.CustomParameters != null)
+ parameters.AddRange(options.CustomParameters);
+
+ if (options.InteractiveInstallation)
+ parameters.Add("--notsilent");
+
+ return parameters.ToArray();
+ }
+
+ protected override async Task LoadManager()
+ {
+ ManagerStatus status = new();
+
+ string old_choco_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs\\WingetUI\\choco-cli");
+ string new_choco_path = Path.Join(CoreData.UniGetUIDataDirectory, "Chocolatey");
+
+ if (Directory.Exists(old_choco_path))
+ try
+ {
+ Logger.Info("Moving Bundled Chocolatey from old path to new path...");
+
+ if (!Directory.Exists(new_choco_path))
+ Directory.CreateDirectory(new_choco_path);
+
+ foreach (string old_subdir in Directory.GetDirectories(old_choco_path, "*", SearchOption.AllDirectories))
+ {
+ string new_subdir = old_subdir.Replace(old_choco_path, new_choco_path);
+ if (!Directory.Exists(new_subdir))
+ {
+ Logger.Debug("New directory: " + new_subdir);
+ await Task.Run(() => Directory.CreateDirectory(new_subdir));
+ }
+ else
+ Logger.Debug("Directory " + new_subdir + " already exists");
+ }
+
+ foreach (string old_file in Directory.GetFiles(old_choco_path, "*", SearchOption.AllDirectories))
+ {
+ string new_file = old_file.Replace(old_choco_path, new_choco_path);
+ if (!File.Exists(new_file))
+ {
+ Logger.Info("Copying " + old_file);
+ await Task.Run(() => File.Move(old_file, new_file));
+ }
+ else
+ {
+ Logger.Debug("File " + new_file + " already exists.");
+ File.Delete(old_file);
+ }
+ }
+
+ foreach (string old_subdir in Directory.GetDirectories(old_choco_path, "*", SearchOption.AllDirectories).Reverse())
+ {
+ if (!Directory.EnumerateFiles(old_subdir).Any() && !Directory.EnumerateDirectories(old_subdir).Any())
+ {
+ Logger.Debug("Deleting old empty subdirectory " + old_subdir);
+ Directory.Delete(old_subdir);
+ }
+ }
+
+ if (!Directory.EnumerateFiles(old_choco_path).Any() && !Directory.EnumerateDirectories(old_choco_path).Any())
+ {
+ Logger.Info("Deleting old Chocolatey directory " + old_choco_path);
+ Directory.Delete(old_choco_path);
+ }
+
+
+ }
+ catch (Exception e)
+ {
+ Logger.Error("An error occurred while migrating chocolatey");
+ Logger.Error(e);
+ }
+
+ if (Settings.Get("UseSystemChocolatey"))
+ status.ExecutablePath = (await CoreTools.Which("choco.exe")).Item2;
+ else if (File.Exists(Path.Join(new_choco_path, "choco.exe")))
+ status.ExecutablePath = Path.Join(new_choco_path, "choco.exe");
+ else
+ status.ExecutablePath = Path.Join(CoreData.UniGetUIExecutableDirectory, "choco-cli\\choco.exe");
+
+ status.Found = File.Exists(status.ExecutablePath);
+
+ if (!status.Found)
+ return status;
+
+ Process process = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = status.ExecutablePath,
+ Arguments = "--version",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+ process.Start();
+ status.Version = (await process.StandardOutput.ReadToEndAsync()).Trim();
+
+ // If the user is running bundled chocolatey and chocolatey is not in path, add chocolatey to path
+ if (/*Settings.Get("ShownWelcomeWizard") && */!Settings.Get("UseSystemChocolatey") && !File.Exists(@"C:\ProgramData\Chocolatey\bin\choco.exe"))
+ {
+ string? path = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User);
+ if (!path?.Contains(status.ExecutablePath.Replace("\\choco.exe", "\\bin")) ?? false)
+ {
+ Logger.Info("Adding chocolatey to path since it was not on path.");
+ Environment.SetEnvironmentVariable("PATH", $"{status.ExecutablePath.Replace("\\choco.exe", "\\bin")};{path}", EnvironmentVariableTarget.User);
+ Environment.SetEnvironmentVariable("chocolateyinstall", Path.GetDirectoryName(status.ExecutablePath), EnvironmentVariableTarget.User);
+ }
+ }
+ Environment.SetEnvironmentVariable("chocolateyinstall", Path.GetDirectoryName(status.ExecutablePath), EnvironmentVariableTarget.Process);
+
+
+ if (status.Found && IsEnabled())
+ await RefreshPackageIndexes();
+
+ return status;
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/ChocolateySourceProvider.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/ChocolateySourceProvider.cs
new file mode 100644
index 000000000..5453c27fe
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/ChocolateySourceProvider.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UniGetUI.Core.Logging;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Classes.Manager.Providers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+
+namespace UniGetUI.PackageEngine.Managers.ChocolateyManager
+{
+ internal class ChocolateySourceProvider : BaseSourceProvider
+ {
+ public ChocolateySourceProvider(Chocolatey manager) : base(manager) { }
+
+ public override string[] GetAddSourceParameters(ManagerSource source)
+ {
+ return new string[] { "source", "add", "--name", source.Name, "--source", source.Url.ToString(), "-y" };
+ }
+
+ public override string[] GetRemoveSourceParameters(ManagerSource source)
+ {
+ return new string[] { "source", "remove", "--name", source.Name, "-y" };
+ }
+
+ public override OperationVeredict GetAddSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ public override OperationVeredict GetRemoveSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ protected override async Task GetSources_UnSafe()
+ {
+ List sources = new();
+
+ Process process = new();
+ ProcessStartInfo startInfo = new()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " source list",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ process.StartInfo = startInfo;
+ process.Start();
+
+
+ string output = "";
+ string? line;
+ while ((line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ try
+ {
+ if (string.IsNullOrEmpty(line))
+ continue;
+
+ if (line.Contains(" - ") && line.Contains(" | "))
+ {
+ string[] parts = line.Trim().Split('|')[0].Trim().Split(" - ");
+ if (parts[1].Trim() == "https://community.chocolatey.org/api/v2/")
+ sources.Add(new ManagerSource(Manager, "community", new Uri("https://community.chocolatey.org/api/v2/")));
+ else
+ sources.Add(new ManagerSource(Manager, parts[0].Trim(), new Uri(parts[1].Trim())));
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Error(e);
+ }
+ }
+
+ output += await process.StandardError.ReadToEndAsync();
+ Manager.LogOperation(process, output);
+
+ await process.WaitForExitAsync();
+ return sources.ToArray();
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj b/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj
new file mode 100644
index 000000000..f9fcd239f
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj
@@ -0,0 +1,253 @@
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
diff --git a/src/UniGetUI/choco-cli/CREDITS.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/CREDITS.txt
similarity index 99%
rename from src/UniGetUI/choco-cli/CREDITS.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/CREDITS.txt
index fb81ac8f1..154f19ee8 100644
--- a/src/UniGetUI/choco-cli/CREDITS.txt
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/CREDITS.txt
@@ -383,9 +383,9 @@ Chocolatey uses [Checksum](https://github.com/chocolatey/checksum) to determine
```
-### log4net @ 2.0.12
+### Logger.Log4net @ 2.0.12
-Chocolatey uses [log4net](http://logging.apache.org/log4net/) for logging.
+Chocolatey uses [log4net](http://logging.apache.org/log4net/) for Logger.Logging.
[License terms](http://logging.apache.org/log4net/license.html):
```txt
diff --git a/src/UniGetUI/choco-cli/LICENSE.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/LICENSE.txt
similarity index 100%
rename from src/UniGetUI/choco-cli/LICENSE.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/LICENSE.txt
diff --git a/src/UniGetUI/choco-cli/bin/RefreshEnv.cmd b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/RefreshEnv.cmd
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/RefreshEnv.cmd
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/RefreshEnv.cmd
diff --git a/src/UniGetUI/choco-cli/bin/_processed.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/_processed.txt
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/_processed.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/_processed.txt
diff --git a/src/UniGetUI/choco-cli/bin/choco.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/choco.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/choco.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/choco.exe
diff --git a/src/UniGetUI/choco-cli/bin/cinst.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cinst.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/cinst.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cinst.exe
diff --git a/src/UniGetUI/choco-cli/bin/clist.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/clist.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/clist.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/clist.exe
diff --git a/src/UniGetUI/choco-cli/bin/cpush.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cpush.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/cpush.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cpush.exe
diff --git a/src/UniGetUI/choco-cli/bin/cuninst.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cuninst.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/cuninst.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cuninst.exe
diff --git a/src/UniGetUI/choco-cli/bin/cup.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cup.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/bin/cup.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/bin/cup.exe
diff --git a/src/UniGetUI/choco-cli/choco.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/choco.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe
diff --git a/src/UniGetUI/choco-cli/choco.exe.ignore b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe.ignore
similarity index 100%
rename from src/UniGetUI/choco-cli/choco.exe.ignore
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe.ignore
diff --git a/src/UniGetUI/choco-cli/choco.exe.manifest b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe.manifest
similarity index 100%
rename from src/UniGetUI/choco-cli/choco.exe.manifest
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/choco.exe.manifest
diff --git a/src/UniGetUI/choco-cli/config/chocolatey.config b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config
similarity index 96%
rename from src/UniGetUI/choco-cli/config/chocolatey.config
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config
index 25f9bc3e7..1518c070c 100644
--- a/src/UniGetUI/choco-cli/config/chocolatey.config
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config
@@ -26,7 +26,7 @@
-
+
@@ -41,8 +41,8 @@
-
-
+
+
diff --git a/src/UniGetUI/choco-cli/config/chocolatey.config.backup b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config.backup
similarity index 96%
rename from src/UniGetUI/choco-cli/config/chocolatey.config.backup
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config.backup
index 13c5a774c..3b7c1eebb 100644
--- a/src/UniGetUI/choco-cli/config/chocolatey.config.backup
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/config/chocolatey.config.backup
@@ -26,7 +26,7 @@
-
+
@@ -41,8 +41,8 @@
-
-
+
+
diff --git a/src/UniGetUI/choco-cli/helpers/ChocolateyTabExpansion.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/ChocolateyTabExpansion.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/ChocolateyTabExpansion.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/ChocolateyTabExpansion.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/chocolateyInstaller.psm1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyInstaller.psm1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/chocolateyInstaller.psm1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyInstaller.psm1
diff --git a/src/UniGetUI/choco-cli/helpers/chocolateyProfile.psm1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyProfile.psm1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/chocolateyProfile.psm1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyProfile.psm1
diff --git a/src/UniGetUI/choco-cli/helpers/chocolateyScriptRunner.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyScriptRunner.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/chocolateyScriptRunner.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/chocolateyScriptRunner.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Format-FileSize.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Format-FileSize.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Format-FileSize.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Format-FileSize.ps1
index 0b604ceed..a4721bce8 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Format-FileSize.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Format-FileSize.ps1
@@ -49,7 +49,7 @@ Get-WebFile
[parameter(ValueFromRemainingArguments = $true)][Object[]] $ignoredArguments
)
- # Do not log function call, it interrupts the single line download progress output.
+ # Do not Logger.Log function call, it interrupts the single line download progress output.
Foreach ($unit in @('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB')) {
If ($size -lt 1024) {
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-CheckSumValid.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-CheckSumValid.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-CheckSumValid.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-CheckSumValid.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyConfigValue.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyConfigValue.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyConfigValue.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyConfigValue.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyPath.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyPath.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyPath.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyPath.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1
index 0d45b52d8..d5f0b3452 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyUnzip.ps1
@@ -70,11 +70,11 @@ OPTIONAL - This is a specific directory within zip file to extract. The
folder and its contents will be extracted to the destination.
.PARAMETER PackageName
-OPTIONAL - This will facilitate logging unzip activity for subsequent
+OPTIONAL - This will facilitate Logger.Logging unzip activity for subsequent
uninstalls
.PARAMETER DisableLogging
-OPTIONAL - This disables logging of the extracted items. It speeds up
+OPTIONAL - This disables Logger.Logging of the extracted items. It speeds up
extraction of archives with many files.
Usage of this parameter will prevent Uninstall-ChocolateyZipPackage
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyWebFile.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyWebFile.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-ChocolateyWebFile.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ChocolateyWebFile.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1
index 697897ec4..2ac4ab498 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariable.ps1
@@ -64,7 +64,7 @@ Set-EnvironmentVariable
[parameter(ValueFromRemainingArguments = $true)][Object[]] $ignoredArguments
)
- # Do not log function call, it may expose variable names
+ # Do not Logger.Log function call, it may expose variable names
## Called from chocolateysetup.psm1 - wrap any Write-Host in try/catch
[string] $MACHINE_ENVIRONMENT_REGISTRY_KEY_NAME = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment\";
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1
index dd5f7fa54..55b51ed7b 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-EnvironmentVariableNames.ps1
@@ -47,7 +47,7 @@ Get-EnvironmentVariable
Set-EnvironmentVariable
#>
- # Do not log function call
+ # Do not Logger.Log function call
# HKCU:\Environment may not exist in all Windows OSes (such as Server Core).
switch ($Scope) {
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-FtpFile.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-FtpFile.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-FtpFile.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-FtpFile.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-OSArchitectureWidth.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-OSArchitectureWidth.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-OSArchitectureWidth.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-OSArchitectureWidth.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-PackageParameters.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-PackageParameters.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-PackageParameters.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-PackageParameters.ps1
index ff6b96f11..157f514f8 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Get-PackageParameters.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-PackageParameters.ps1
@@ -139,7 +139,7 @@ Install-ChocolateyZipPackage
Write-Debug 'Parsing $env:ChocolateyPackageParameters and $env:ChocolateyPackageParametersSensitive for parameters'
$paramStrings = @("$env:ChocolateyPackageParameters", "$env:ChocolateyPackageParametersSensitive")
if ($env:ChocolateyPackageParametersSensitive) {
- Write-Debug "Sensitive parameters detected, no logging of parameters."
+ Write-Debug "Sensitive parameters detected, no Logger.Logging of parameters."
$loggingAllowed = $false
}
}
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-ToolsLocation.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ToolsLocation.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-ToolsLocation.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-ToolsLocation.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-UACEnabled.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-UACEnabled.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-UACEnabled.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-UACEnabled.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-UninstallRegistryKey.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-UninstallRegistryKey.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-UninstallRegistryKey.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-UninstallRegistryKey.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-VirusCheckValid.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-VirusCheckValid.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-VirusCheckValid.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-VirusCheckValid.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-WebFile.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebFile.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-WebFile.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebFile.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-WebFileName.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebFileName.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-WebFileName.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebFileName.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Get-WebHeaders.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebHeaders.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Get-WebHeaders.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Get-WebHeaders.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-BinFile.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-BinFile.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-BinFile.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-BinFile.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyEnvironmentVariable.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyEnvironmentVariable.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyEnvironmentVariable.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyEnvironmentVariable.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyExplorerMenuItem.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyExplorerMenuItem.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyExplorerMenuItem.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyExplorerMenuItem.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyFileAssociation.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyFileAssociation.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyFileAssociation.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyFileAssociation.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1
index 8884e408a..db4865215 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyInstallPackage.ps1
@@ -312,7 +312,7 @@ Pro / Business supports a single, ubiquitous install directory option.
}
try {
- # make sure any logging folder exists
+ # make sure any Logger.Logging folder exists
$pattern = "(?:['`"])([a-zA-Z]\:\\[^'`"]+)(?:[`"'])|([a-zA-Z]\:\\[\S]+)"
$silentArgs, $additionalInstallArgs |
ForEach-Object { Select-String $pattern -input $_ -AllMatches } |
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPackage.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPackage.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPath.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPath.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPath.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPath.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPinnedTaskBarItem.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPinnedTaskBarItem.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPinnedTaskBarItem.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPinnedTaskBarItem.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPowershellCommand.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPowershellCommand.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyPowershellCommand.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyPowershellCommand.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyShortcut.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyShortcut.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyShortcut.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyShortcut.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyVsixPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyVsixPackage.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyVsixPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyVsixPackage.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1
index 19fcfa3c7..9ecddf583 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-ChocolateyZipPackage.ps1
@@ -152,7 +152,7 @@ This parameter provides compatibility, but should not be used directly
and not with the community package repository until January 2018.
.PARAMETER DisableLogging
-OPTIONAL - This disables logging of the extracted items. It speeds up
+OPTIONAL - This disables Logger.Logging of the extracted items. It speeds up
extraction of archives with many files.
Usage of this parameter will prevent Uninstall-ChocolateyZipPackage
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Install-Vsix.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-Vsix.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Install-Vsix.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Install-Vsix.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Set-EnvironmentVariable.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Set-EnvironmentVariable.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Set-EnvironmentVariable.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Set-EnvironmentVariable.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1
index 44276ca15..18e9c28bb 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Set-PowerShellExitCode.ps1
@@ -46,7 +46,7 @@ Set-PowerShellExitCode 3010
[parameter(ValueFromRemainingArguments = $true)][Object[]] $ignoredArguments
)
- # Do not log function call - can mess things up
+ # Do not Logger.Log function call - can mess things up
if ($exitCode -eq $null -or $exitCode -eq '') {
Write-Debug '$exitCode was passed null'
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1
similarity index 97%
rename from src/UniGetUI/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1
index 07a472156..bbaac81f9 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Start-ChocolateyProcessAsAdmin.ps1
@@ -66,7 +66,7 @@ The working directory for the running process. Defaults to
`$env:TEMP` for default.
.PARAMETER SensitiveStatements
-Arguments to pass to `ExeToRun` that are not logged.
+Arguments to pass to `ExeToRun` that are not Logger.Logged.
Note that only licensed versions of Chocolatey provide a way to pass
those values completely through without having them in the install
@@ -326,7 +326,7 @@ $dbMessagePrepend [`"$exeToRun`" $wrappedStatements]. This may take a while, dep
$exitErrorMessage = 'User (you) cancelled the installation.'; break
}
1603 {
- $exitErrorMessage = "Generic MSI Error. This is a local environment error, not an issue with a package or the MSI itself - it could mean a pending reboot is necessary prior to install or something else (like the same version is already installed). Please see MSI log if available. If not, try again adding `'--install-arguments=`"`'/l*v c:\$($env:chocolateyPackageName)_msi_install.log`'`"`'. Then search the MSI Log for `"Return Value 3`" and look above that for the error."; break
+ $exitErrorMessage = "Generic MSI Error. This is a local environment error, not an issue with a package or the MSI itself - it could mean a pending reboot is necessary prior to install or something else (like the same version is already installed). Please see MSI Logger.Log if available. If not, try again adding `'--install-arguments=`"`'/l*v c:\$($env:chocolateyPackageName)_msi_install.log`'`"`'. Then search the MSI Logger.Log for `"Return Value 3`" and look above that for the error."; break
}
1618 {
$exitErrorMessage = 'Another installation currently in progress. Try again later.'; break
@@ -338,7 +338,7 @@ $dbMessagePrepend [`"$exeToRun`" $wrappedStatements]. This may take a while, dep
$exitErrorMessage = 'MSI could not be opened - it is possibly corrupt or not an MSI at all. If it was downloaded and the MSI is less than 30K, try opening it in an editor like Notepad++ as it is likely HTML.' + $errorMessageAddendum; break
}
1622 {
- $exitErrorMessage = 'Something is wrong with the install log location specified. Please fix this in the package silent arguments (or in install arguments you specified). The directory specified as part of the log file path must exist for an MSI to be able to log to that directory.' + $errorMessageAddendum; break
+ $exitErrorMessage = 'Something is wrong with the install Logger.Log location specified. Please fix this in the package silent arguments (or in install arguments you specified). The directory specified as part of the Logger.Log file path must exist for an MSI to be able to Logger.Log to that directory.' + $errorMessageAddendum; break
}
1623 {
$exitErrorMessage = 'This MSI has a language that is not supported by your system. Contact package maintainer(s) if there is an install available in your language and you would like it added to the packaging.'; break
@@ -371,7 +371,7 @@ $dbMessagePrepend [`"$exeToRun`" $wrappedStatements]. This may take a while, dep
Write-Warning $exitErrorMessage
}
else {
- $errorMessageSpecific = 'See log for possible error messages.'
+ $errorMessageSpecific = 'See Logger.Log for possible error messages.'
}
if ($validExitCodes -notcontains $exitCode) {
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1
index fd857c002..1f84655f0 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Test-ProcessAdminRights.ps1
@@ -36,7 +36,7 @@ None
System.Boolean
#>
- # do not log function call
+ # do not Logger.Log function call
## Called from chocolateysetup.psm1 - wrap any Write-Host in try/catch
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent([Security.Principal.TokenAccessLevels]'Query,Duplicate'))
diff --git a/src/UniGetUI/choco-cli/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/UnInstall-ChocolateyZipPackage.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/UnInstall-ChocolateyZipPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/UnInstall-ChocolateyZipPackage.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Uninstall-BinFile.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-BinFile.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Uninstall-BinFile.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-BinFile.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Uninstall-ChocolateyEnvironmentVariable.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-ChocolateyEnvironmentVariable.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Uninstall-ChocolateyEnvironmentVariable.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-ChocolateyEnvironmentVariable.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Uninstall-ChocolateyPackage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-ChocolateyPackage.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Uninstall-ChocolateyPackage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Uninstall-ChocolateyPackage.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Update-SessionEnvironment.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Update-SessionEnvironment.ps1
similarity index 100%
rename from src/UniGetUI/choco-cli/helpers/functions/Update-SessionEnvironment.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Update-SessionEnvironment.ps1
diff --git a/src/UniGetUI/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1 b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1
similarity index 99%
rename from src/UniGetUI/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1
index e03853498..4ed5e011f 100644
--- a/src/UniGetUI/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1
+++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/helpers/functions/Write-FunctionCallLogMessage.ps1
@@ -52,7 +52,7 @@ Write-FunctionCallLogMessage -Invocation $MyInvocation -Parameters $PSBoundParam
[parameter(ValueFromRemainingArguments = $true)][Object[]] $ignoredArguments
)
- # do not log function call - recursion?
+ # do not Logger.Log function call - recursion?
$argumentsPassed = ''
foreach ($param in $parameters.GetEnumerator()) {
diff --git a/src/UniGetUI/choco-cli/redirects/RefreshEnv.cmd b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/RefreshEnv.cmd
similarity index 100%
rename from src/UniGetUI/choco-cli/redirects/RefreshEnv.cmd
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/RefreshEnv.cmd
diff --git a/src/UniGetUI/choco-cli/redirects/choco.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/choco.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/redirects/choco.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/choco.exe
diff --git a/src/UniGetUI/choco-cli/redirects/choco.exe.ignore b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/choco.exe.ignore
similarity index 100%
rename from src/UniGetUI/choco-cli/redirects/choco.exe.ignore
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/redirects/choco.exe.ignore
diff --git a/src/UniGetUI/choco-cli/tools/7z.dll b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.dll
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7z.dll
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.dll
diff --git a/src/UniGetUI/choco-cli/tools/7z.dll.manifest b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.dll.manifest
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7z.dll.manifest
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.dll.manifest
diff --git a/src/UniGetUI/choco-cli/tools/7z.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7z.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe
diff --git a/src/UniGetUI/choco-cli/tools/7z.exe.ignore b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe.ignore
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7z.exe.ignore
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe.ignore
diff --git a/src/UniGetUI/choco-cli/tools/7z.exe.manifest b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe.manifest
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7z.exe.manifest
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7z.exe.manifest
diff --git a/src/UniGetUI/choco-cli/tools/7zip.license.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7zip.license.txt
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/7zip.license.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/7zip.license.txt
diff --git a/src/UniGetUI/choco-cli/tools/checksum.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/checksum.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe
diff --git a/src/UniGetUI/choco-cli/tools/checksum.exe.config b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe.config
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/checksum.exe.config
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe.config
diff --git a/src/UniGetUI/choco-cli/tools/checksum.exe.ignore b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe.ignore
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/checksum.exe.ignore
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.exe.ignore
diff --git a/src/UniGetUI/choco-cli/tools/checksum.license.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.license.txt
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/checksum.license.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/checksum.license.txt
diff --git a/src/UniGetUI/choco-cli/tools/shimgen.exe b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.exe
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/shimgen.exe
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.exe
diff --git a/src/UniGetUI/choco-cli/tools/shimgen.exe.ignore b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.exe.ignore
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/shimgen.exe.ignore
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.exe.ignore
diff --git a/src/UniGetUI/choco-cli/tools/shimgen.license.txt b/src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.license.txt
similarity index 100%
rename from src/UniGetUI/choco-cli/tools/shimgen.license.txt
rename to src/UniGetUI.PackageEngine.Managers.Chocolatey/choco-cli/tools/shimgen.license.txt
diff --git a/src/UniGetUI/PackageEngine/Managers/Dotnet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs
similarity index 56%
rename from src/UniGetUI/PackageEngine/Managers/Dotnet.cs
rename to src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs
index 037cbf1cf..06c1f1091 100644
--- a/src/UniGetUI/PackageEngine/Managers/Dotnet.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs
@@ -1,74 +1,66 @@
-using UniGetUI.PackageEngine.Classes;
-using UniGetUI.PackageEngine.Operations;
-using UniGetUI.Core;
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-
-namespace UniGetUI.PackageEngine.Managers
+using UniGetUI.Core;
+using UniGetUI.PackageEngine.Classes;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Managers;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Managers.PowerShellManager;
+
+namespace UniGetUI.PackageEngine.Managers.DotNetManager
{
- public class Dotnet : PackageManager
+ public class DotNet : BaseNuGet
{
new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
new public static string[] FALSE_PACKAGE_IDS = new string[] { "" };
new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "" };
- protected override async Task FindPackages_UnSafe(string query)
- {
- Process p = new();
- p.StartInfo = new ProcessStartInfo()
+ public DotNet() : base()
+ {
+ Capabilities = new ManagerCapabilities()
{
- FileName = Status.ExecutablePath,
- Arguments = Properties.ExecutableCallArgs + " search \"" + query + "\"",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
+ CanRunAsAdmin = true,
+ SupportsCustomScopes = true,
+ SupportsCustomArchitectures = true,
+ SupportedCustomArchitectures = new Architecture[] { Architecture.X86, Architecture.X64, Architecture.Arm64, Architecture.Arm },
+ SupportsPreRelease = true,
+ SupportsCustomLocations = true,
+ SupportsCustomPackageIcons = true,
+ SupportsCustomVersions = true,
};
- p.Start();
- string line;
- List Packages = new();
- bool DashesPassed = false;
- string output = "";
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ Properties = new ManagerProperties()
{
- output += line + "\n";
- if (!DashesPassed)
- {
- if (line.Contains("-----"))
- DashesPassed = true;
- }
- else
- {
- string[] elements = Regex.Replace(line, " {2,}", " ").Split(' ');
- if (elements.Length >= 2)
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this, PackageScope.Global));
- // Dotnet tool packages are installed globally by default, hence the Global flag
- }
- }
-
- output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
-
- await p.WaitForExitAsync();
-
- return Packages.ToArray();
+ Name = ".NET Tool",
+ Description = CoreTools.Translate("A repository full of tools and executables designed with Microsoft's .NET ecosystem in mind.
Contains: .NET related tools and scripts"),
+ IconId = "dotnet",
+ ColorIconId = "dotnet_color",
+ ExecutableFriendlyName = "dotnet tool",
+ InstallVerb = "install",
+ UninstallVerb = "uninstall",
+ UpdateVerb = "update",
+ ExecutableCallArgs = "tool",
+ DefaultSource = new ManagerSource(this, "nuget.org", new Uri("https://www.nuget.org/api/v2")),
+ KnownSources = [new ManagerSource(this, "nuget.org", new Uri("https://www.nuget.org/api/v2"))],
+ };
}
protected override async Task GetAvailableUpdates_UnSafe()
{
- string path = await Tools.Which("dotnet-tools-outdated.exe");
- if (!File.Exists(path))
+ var which_res = await CoreTools.Which("dotnet-tools-outdated.exe");
+ string path = which_res.Item2;
+ if (!which_res.Item1)
{
Process proc = new()
{
@@ -101,7 +93,7 @@ protected override async Task GetAvailableUpdates_UnSafe()
p.Start();
- string line;
+ string? line;
bool DashesPassed = false;
List Packages = new();
string output = "";
@@ -123,11 +115,11 @@ protected override async Task GetAvailableUpdates_UnSafe()
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new UpgradablePackage(Tools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], MainSource, this, PackageScope.Global));
+ Packages.Add(new UpgradablePackage(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], DefaultSource, this, PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
return Packages.ToArray();
}
@@ -150,7 +142,7 @@ protected override async Task GetInstalledPackages_UnSafe()
p.Start();
- string line;
+ string? line;
bool DashesPassed = false;
List Packages = new();
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
@@ -170,7 +162,7 @@ protected override async Task GetInstalledPackages_UnSafe()
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this, PackageScope.User));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, PackageScope.User));
}
}
@@ -210,11 +202,11 @@ protected override async Task GetInstalledPackages_UnSafe()
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this, PackageScope.Global));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
return Packages.ToArray();
}
@@ -272,131 +264,13 @@ public override string[] GetUninstallParameters(Package package, InstallationOpt
return parameters.ToArray();
}
- public override ManagerSource GetMainSource()
- {
- return new ManagerSource(this, "nuget.org", new Uri("https://www.nuget.org/"));
- }
-
- public override async Task GetPackageDetails_UnSafe(Package package)
- {
- PackageDetails details = new(package);
-
- try
- {
- details.ManifestUrl = new Uri("https://www.nuget.org/packages/" + package.Id);
- string url = $"http://www.nuget.org/api/v2/Packages(Id='{package.Id}',Version='')";
-
- using (HttpClient client = new())
- {
- string apiContents = await client.GetStringAsync(url);
-
- details.InstallerUrl = new Uri($"https://globalcdn.nuget.org/packages/{package.Id}.{package.Version}.nupkg");
- details.InstallerType = Tools.Translate("NuPkg (zipped manifest)");
- details.InstallerSize = await Tools.GetFileSizeAsync(details.InstallerUrl);
-
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/name>"))
- {
- details.Author = match.Value.Replace("", "").Replace("", "");
- details.Publisher = match.Value.Replace("", "").Replace("", "");
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:Description>"))
- {
- details.Description = match.Value.Replace("", "").Replace("", "");
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/updated>"))
- {
- details.UpdateDate = match.Value.Replace("", "").Replace("", "");
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:ProjectUrl>"))
- {
- details.HomepageUrl = new Uri(match.Value.Replace("", "").Replace("", ""));
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:LicenseUrl>"))
- {
- details.LicenseUrl = new Uri(match.Value.Replace("", "").Replace("", ""));
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:PackageHash>"))
- {
- details.InstallerHash = match.Value.Replace("", "").Replace("", "");
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:ReleaseNotes>"))
- {
- details.ReleaseNotes = match.Value.Replace("", "").Replace("", "");
- break;
- }
-
- foreach (Match match in Regex.Matches(apiContents, @"[^<>]+<\/d:LicenseNames>"))
- {
- details.License = match.Value.Replace("", "").Replace("", "");
- break;
- }
- }
- return details;
- }
- catch (Exception e)
- {
- AppTools.Log(e);
- return details;
- }
- }
-
-
-#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
- public override async Task RefreshPackageIndexes()
- {
- // .NET Tool does not support manual source refreshing
- }
-
- protected override ManagerCapabilities GetCapabilities()
- {
- return new ManagerCapabilities()
- {
- CanRunAsAdmin = true,
- SupportsCustomScopes = true,
- SupportsCustomArchitectures = true,
- SupportedCustomArchitectures = new Architecture[] { Architecture.X86, Architecture.X64, Architecture.Arm64, Architecture.Arm },
- SupportsPreRelease = true,
- SupportsCustomLocations = true
- };
- }
-
- protected override ManagerProperties GetProperties()
- {
- ManagerProperties properties = new()
- {
- Name = ".NET Tool",
- Description = Tools.Translate("A repository full of tools and executables designed with Microsoft's .NET ecosystem in mind.
Contains: .NET related tools and scripts"),
- IconId = "dotnet",
- ColorIconId = "dotnet_color",
- ExecutableFriendlyName = "dotnet tool",
- InstallVerb = "install",
- UninstallVerb = "uninstall",
- UpdateVerb = "update",
- ExecutableCallArgs = "tool",
-
- };
- return properties;
- }
-
protected override async Task LoadManager()
{
ManagerStatus status = new();
- status.ExecutablePath = await Tools.Which("dotnet.exe");
- status.Found = File.Exists(status.ExecutablePath);
+ var which_res = await CoreTools.Which("dotnet.exe");
+ status.ExecutablePath = which_res.Item2;
+ status.Found = which_res.Item1;
if (!status.Found)
return status;
@@ -422,12 +296,5 @@ protected override async Task LoadManager()
return status;
}
-
- protected override async Task GetPackageVersions_Unsafe(Package package)
- {
- await Task.Delay(0);
- AppTools.Log("Manager " + Name + " does not support version retrieving, this function should have never been called");
- return new string[0];
- }
}
}
diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj b/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj
new file mode 100644
index 000000000..942b61f2f
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs
new file mode 100644
index 000000000..77bc603c4
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using UniGetUI.Core;
+using UniGetUI.PackageEngine.Classes;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using System.Net;
+using System.Web;
+
+namespace UniGetUI.PackageEngine.Managers.PowerShellManager
+{
+ public abstract class BaseNuGet : PackageManager
+ {
+ new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_IDS = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "" };
+
+ public BaseNuGet() : base()
+ {
+ PackageDetailsProvider = new BaseNuGetDetailsProvider(this);
+ }
+
+ public sealed override async Task InitializeAsync()
+ {
+ if(PackageDetailsProvider is not BaseNuGetDetailsProvider)
+ throw new Exception("NuGet-based package managers must not reassign the PackageDetailsProvider property");
+
+ if (!Capabilities.SupportsCustomVersions)
+ throw new Exception("NuGet-based package managers must support custom versions");
+ if (!Capabilities.SupportsCustomPackageIcons)
+ throw new Exception("NuGet-based package managers must support custom versions");
+
+ await base.InitializeAsync();
+ }
+
+ private struct SearchResult
+ {
+ public string version;
+ public double version_float;
+ public string id;
+ }
+
+ protected sealed override async Task FindPackages_UnSafe(string query)
+ {
+ Logger.Error($"Using new NuGet search engine for manager {Name}");
+ List Packages = new();
+
+ ManagerSource[] sources;
+ if (Capabilities.SupportsCustomSources)
+ sources = await GetSources();
+ else
+ sources = new ManagerSource[] { Properties.DefaultSource };
+
+ foreach(var source in sources)
+ {
+ Uri SearchUrl = new Uri($"{source.Url}/Search()?searchTerm=%27{HttpUtility.UrlEncode(query)}%27&targetFramework=%27%27&includePrerelease=false");
+ Logger.Debug($"Begin package search with url={SearchUrl} on manager {Name}"); ;
+ HttpClientHandler handler = new HttpClientHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.All
+ };
+
+ using (HttpClient client = new HttpClient(handler))
+ {
+ var response = await client.GetAsync(SearchUrl);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ Logger.Warn($"Failed to fetch api at Url={SearchUrl} with status code {response.StatusCode}");
+ continue;
+ }
+
+ string SearchResults = await response.Content.ReadAsStringAsync();
+ MatchCollection matches = Regex.Matches(SearchResults, "([\\s\\S]*?)<\\/entry>");
+
+ Dictionary AlreadyProcessedPackages = new();
+
+ foreach (Match match in matches)
+ {
+ if (!match.Success) continue;
+
+ string id = Regex.Match(match.Value, "Id='([^<>']+)'").Groups[1].Value;
+ string version = Regex.Match(match.Value, "Version='([^<>']+)'").Groups[1].Value;
+ double float_version = CoreTools.GetVersionStringAsFloat(version);
+ Match title = Regex.Match(match.Value, "([^<>]+)<\\/title>");
+
+ if (AlreadyProcessedPackages.ContainsKey(id) && AlreadyProcessedPackages[id].version_float >= float_version)
+ continue;
+
+ AlreadyProcessedPackages[id] = new SearchResult() { id = id, version = version, version_float = float_version };
+ }
+ foreach(var package in AlreadyProcessedPackages.Values)
+ Packages.Add(new Package(CoreTools.FormatAsName(package.id), package.id, package.version, source, this));
+
+ }
+ }
+
+ return Packages.ToArray();
+ }
+
+ }
+
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGetDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGetDetailsProvider.cs
new file mode 100644
index 000000000..543d75c00
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGetDetailsProvider.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+using UniGetUI.Core.IconEngine;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.BaseProviders;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.Managers.Generic.NuGet.Internal;
+using UniGetUI.PackageEngine.PackageClasses;
+using static UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers.ManagerSource;
+
+namespace UniGetUI.PackageEngine.Managers.PowerShellManager
+{
+ internal class BaseNuGetDetailsProvider : BasePackageDetailsProvider
+ {
+ public BaseNuGetDetailsProvider(BaseNuGet manager) : base(manager) { }
+
+ protected override async Task GetPackageDetails_Unsafe(Package package)
+ {
+ PackageDetails details = new(package);
+ try
+ {
+ details.ManifestUrl = PackageManifestLoader.GetPackageManifestUrl(package);
+ string? PackageManifestContents = await PackageManifestLoader.GetPackageManifestContent(package);
+ if (PackageManifestContents == null)
+ {
+ Logger.Warn($"No manifest content could be loaded for package {package.Id} on manager {package.Manager.Name}, returning empty PackageDetails");
+ return details;
+ }
+
+ // details.InstallerUrl = new Uri($"https://globalcdn.nuget.org/packages/{package.Id}.{package.Version}.nupkg");
+ details.InstallerUrl = PackageManifestLoader.GetPackageNuGetPackageUrl(package);
+ details.InstallerType = CoreTools.Translate("NuPkg (zipped manifest)");
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/name>"))
+ {
+ details.Author = match.Value.Replace("", "").Replace("", "");
+ details.Publisher = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:Description>"))
+ {
+ details.Description = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/updated>"))
+ {
+ details.UpdateDate = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:ProjectUrl>"))
+ {
+ details.HomepageUrl = new Uri(match.Value.Replace("", "").Replace("", ""));
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:LicenseUrl>"))
+ {
+ details.LicenseUrl = new Uri(match.Value.Replace("", "").Replace("", ""));
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:PackageHash>"))
+ {
+ details.InstallerHash = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:ReleaseNotes>"))
+ {
+ details.ReleaseNotes = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ foreach (Match match in Regex.Matches(PackageManifestContents, @"[^<>]+<\/d:LicenseNames>"))
+ {
+ details.License = match.Value.Replace("", "").Replace("", "");
+ break;
+ }
+
+ return details;
+ }
+ catch (Exception e)
+ {
+ Logger.Error(e);
+ return details;
+ }
+ }
+
+ protected override async Task GetPackageIcon_Unsafe(Package package)
+ {
+ var PackageManifestContent = await PackageManifestLoader.GetPackageManifestContent(package);
+ if (PackageManifestContent == null)
+ {
+ Logger.Warn($"No manifest content could be loaded for package {package.Id} on manager {package.Manager.Name}");
+ return null;
+ }
+
+ var possibleIconUrl = Regex.Match(PackageManifestContent, "<(?:d\\:)?IconUrl>(.*)<(?:\\/d:)?IconUrl>");
+
+ if (!possibleIconUrl.Success)
+ {
+ Logger.Warn($"No Icon URL could be parsed on the manifest Url={PackageManifestLoader.GetPackageManifestUrl(package).ToString()}");
+ return null;
+ }
+
+ Logger.Debug($"A native icon with Url={possibleIconUrl.Groups[1].Value} was found");
+ return new CacheableIcon(new Uri(possibleIconUrl.Groups[1].Value), package.Version);
+ }
+
+ protected override Task GetPackageScreenshots_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override async Task GetPackageVersions_Unsafe(Package package)
+ {
+ Uri SearchUrl = new Uri($"{package.Source.Url}/FindPackagesById()?id='{package.Id}'");
+ Logger.Debug($"Begin package version search with url={SearchUrl} on manager {Manager.Name}"); ;
+ HttpClientHandler handler = new HttpClientHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.All
+ };
+
+ using (HttpClient client = new HttpClient(handler))
+ {
+ var response = await client.GetAsync(SearchUrl);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ Logger.Warn($"Failed to fetch api at Url={SearchUrl} with status code {response.StatusCode} to load versions");
+ return [];
+ }
+
+ string SearchResults = await response.Content.ReadAsStringAsync();
+ MatchCollection matches = Regex.Matches(SearchResults, "Version='([^<>']+)'");
+
+ List results = new List();
+ HashSet alreadyProcessed = new HashSet();
+
+ foreach (Match match in matches)
+ if(!alreadyProcessed.Contains(match.Groups[1].Value) && match.Success)
+ {
+ results.Add(match.Groups[1].Value);
+ alreadyProcessed.Add(match.Groups[1].Value);
+ }
+
+ results.Reverse();
+ return results.ToArray();
+
+ }
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/Internal/PackageManifestLoader.cs b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/Internal/PackageManifestLoader.cs
new file mode 100644
index 000000000..62d2d329f
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/Internal/PackageManifestLoader.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using UniGetUI.Core.Logging;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.Generic.NuGet.Internal
+{
+ internal static class PackageManifestLoader
+ {
+ private static Dictionary __manifest_cache = new();
+
+ ///
+ /// Returns the URL to the manifest of a NuGet-based package
+ ///
+ /// A valid Package object
+ /// A Uri object
+ public static Uri GetPackageManifestUrl(Package package)
+ {
+ return new Uri($"{package.Source.Url}/Packages(Id='{package.Id}',Version='{package.Version}')");
+ }
+
+ ///
+ /// Returns the URL to the NuPk file
+ ///
+ /// A valid Package object
+ /// A Uri object
+ public static Uri GetPackageNuGetPackageUrl(Package package)
+ {
+ return new Uri($"{package.Source.Url}/Packages/{package.Id}.{package.Version}.nupkg");
+ }
+
+ ///
+ /// Returns the contents of the manifest of a NuGet-based package
+ ///
+ /// The package for which to obtain the manifest
+ /// A string containing the contents of the manifest
+ public static async Task GetPackageManifestContent(Package package)
+ {
+ string? PackageManifestContent = "";
+ string PackageManifestUrl = GetPackageManifestUrl(package).ToString();
+ if (__manifest_cache.ContainsKey(PackageManifestUrl))
+ {
+ Logger.Debug($"Loading cached NuGet manifest for package {package.Id} on manager {package.Manager.Name}");
+ return __manifest_cache[PackageManifestUrl];
+ }
+
+ try
+ {
+ HttpClientHandler handler = new HttpClientHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.All
+ };
+
+ using (HttpClient client = new HttpClient(handler))
+ {
+ var response = await client.GetAsync(PackageManifestUrl);
+ if (!response.IsSuccessStatusCode && package.Version.EndsWith(".0"))
+ response = await client.GetAsync(new Uri(PackageManifestUrl.ToString().Replace(".0')", "')")));
+
+ if (!response.IsSuccessStatusCode)
+ {
+ Logger.Warn($"Failed to download the {package.Manager.Name} manifest at Url={PackageManifestUrl.ToString()} with status code {response.StatusCode}");
+ return null;
+ }
+
+ PackageManifestContent = await response.Content.ReadAsStringAsync();
+ }
+ __manifest_cache[PackageManifestUrl] = PackageManifestContent;
+ return PackageManifestContent;
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Failed to download the {package.Manager.Name} manifest at Url={PackageManifestUrl.ToString()}");
+ Logger.Warn(e);
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj
new file mode 100644
index 000000000..981d1e543
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/PackageEngine/Managers/Npm.cs b/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs
similarity index 57%
rename from src/UniGetUI/PackageEngine/Managers/Npm.cs
rename to src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs
index 1a03ed637..69e183b75 100644
--- a/src/UniGetUI/PackageEngine/Managers/Npm.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs
@@ -1,21 +1,47 @@
-using UniGetUI.PackageEngine.Classes;
-using UniGetUI.PackageEngine.Operations;
-using UniGetUI.Core;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Threading.Tasks;
-
-namespace UniGetUI.PackageEngine.Managers
+using System.Diagnostics;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.NpmManager
{
public class Npm : PackageManager
{
new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
new public static string[] FALSE_PACKAGE_IDS = new string[] { "" };
new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "" };
+
+ public Npm() : base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ SupportsCustomVersions = true,
+ SupportsCustomScopes = true,
+ };
+
+ Properties = new ManagerProperties()
+ {
+ Name = "Npm",
+ Description = CoreTools.Translate("Node JS's package manager. Full of libraries and other utilities that orbit the javascript world
Contains: Node javascript libraries and other related utilities"),
+ IconId = "node",
+ ColorIconId = "node_color",
+ ExecutableFriendlyName = "npm",
+ InstallVerb = "install",
+ UninstallVerb = "uninstall",
+ UpdateVerb = "install",
+ ExecutableCallArgs = " -NoProfile -ExecutionPolicy Bypass -Command npm",
+ DefaultSource = new ManagerSource(this, "npm", new Uri("https://www.npmjs.com/")),
+ KnownSources = [new ManagerSource(this, "npm", new Uri("https://www.npmjs.com/"))],
+
+ };
+
+ PackageDetailsProvider = new NpmPackageDetailsProvider(this);
+ }
+
protected override async Task FindPackages_UnSafe(string query)
{
Process p = new();
@@ -33,7 +59,7 @@ protected override async Task FindPackages_UnSafe(string query)
};
p.Start();
- string line;
+ string? line;
List Packages = new();
bool HeaderPassed = false;
string output = "";
@@ -47,7 +73,7 @@ protected override async Task FindPackages_UnSafe(string query)
{
string[] elements = line.Split('\t');
if (elements.Length >= 5)
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[4], MainSource, this));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[4], DefaultSource, this));
}
}
@@ -73,7 +99,7 @@ protected override async Task GetAvailableUpdates_UnSafe()
};
p.Start();
- string line;
+ string? line;
List Packages = new();
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
@@ -82,7 +108,7 @@ protected override async Task GetAvailableUpdates_UnSafe()
string[] elements = line.Split(':');
if (elements.Length >= 4)
{
- Packages.Add(new UpgradablePackage(Tools.FormatAsName(elements[2].Split('@')[0]), elements[2].Split('@')[0], elements[3].Split('@')[^1], elements[2].Split('@')[^1], MainSource, this));
+ Packages.Add(new UpgradablePackage(CoreTools.FormatAsName(elements[2].Split('@')[0]), elements[2].Split('@')[0], elements[3].Split('@')[^1], elements[2].Split('@')[^1], DefaultSource, this));
}
}
@@ -114,12 +140,12 @@ protected override async Task GetAvailableUpdates_UnSafe()
if (elements[3][0] == '@')
elements[3] = "%" + elements[3][1..];
- Packages.Add(new UpgradablePackage(Tools.FormatAsName(elements[2].Split('@')[0]).Replace('%', '@'), elements[2].Split('@')[0].Replace('%', '@'), elements[3].Split('@')[^1].Replace('%', '@'), elements[2].Split('@')[^1].Replace('%', '@'), MainSource, this, PackageScope.Global));
+ Packages.Add(new UpgradablePackage(CoreTools.FormatAsName(elements[2].Split('@')[0]).Replace('%', '@'), elements[2].Split('@')[0].Replace('%', '@'), elements[3].Split('@')[^1].Replace('%', '@'), elements[2].Split('@')[^1].Replace('%', '@'), DefaultSource, this, PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
await p.WaitForExitAsync();
@@ -143,7 +169,7 @@ protected override async Task GetInstalledPackages_UnSafe()
};
p.Start();
- string line;
+ string? line;
List Packages = new();
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
@@ -152,7 +178,7 @@ protected override async Task GetInstalledPackages_UnSafe()
if (line.Contains("--") || line.Contains("├─") || line.Contains("└─"))
{
string[] elements = line[4..].Split('@');
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this));
}
}
@@ -178,12 +204,12 @@ protected override async Task GetInstalledPackages_UnSafe()
{
line = line.Replace("- @", "- %");
string[] elements = line[4..].Split('@');
- Packages.Add(new Package(Tools.FormatAsName(elements[0].Replace('%', '@')), elements[0].Replace('%', '@'), elements[1], MainSource, this, PackageScope.Global));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0].Replace('%', '@')), elements[0].Replace('%', '@'), elements[1], DefaultSource, this, PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
await p.WaitForExitAsync();
return Packages.ToArray();
@@ -235,142 +261,13 @@ public override string[] GetUninstallParameters(Package package, InstallationOpt
return parameters.ToArray();
}
- public override ManagerSource GetMainSource()
- {
- return new ManagerSource(this, "npm", new Uri("https://www.npmjs.com/"));
- }
-
- public override async Task GetPackageDetails_UnSafe(Package package)
- {
- PackageDetails details = new(package);
- try
- {
- details.InstallerType = "Tarball";
- details.ManifestUrl = new Uri($"https://www.npmjs.com/package/{package.Id}");
- details.ReleaseNotesUrl = new Uri($"https://www.npmjs.com/package/{package.Id}?activeTab=versions");
-
- using (Process p = new())
- {
- p.StartInfo = new ProcessStartInfo()
- {
- FileName = Status.ExecutablePath,
- Arguments = Properties.ExecutableCallArgs + " info " + package.Id,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
- StandardOutputEncoding = System.Text.Encoding.UTF8
- };
-
- p.Start();
-
- List output = new();
- string line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- output.Add(line);
- }
-
- int lineNo = 0;
- bool ReadingMaintainer = false;
- foreach (string outLine in output)
- {
- try
- {
- lineNo++;
- if (lineNo == 2)
- {
- details.License = outLine.Split("|")[1];
- }
- else if (lineNo == 3)
- {
- details.Description = outLine.Trim();
- }
- else if (lineNo == 4)
- {
- details.HomepageUrl = new Uri(outLine.Trim());
- }
- else if (outLine.StartsWith(".tarball"))
- {
- details.InstallerUrl = new Uri(outLine.Replace(".tarball: ", "").Trim());
- details.InstallerSize = await Tools.GetFileSizeAsync(details.InstallerUrl);
- }
- else if (outLine.StartsWith(".integrity"))
- {
- details.InstallerHash = outLine.Replace(".integrity: sha512-", "").Replace("==", "").Trim();
- }
- else if (outLine.StartsWith("maintainers:"))
- {
- ReadingMaintainer = true;
- }
- else if (ReadingMaintainer)
- {
- ReadingMaintainer = false;
- details.Author = outLine.Replace("-", "").Split('<')[0].Trim();
- }
- else if (outLine.StartsWith("published"))
- {
- details.Publisher = outLine.Split("by").Last().Split('<')[0].Trim();
- details.UpdateDate = outLine.Replace("published", "").Split("by")[0].Trim();
- }
- }
- catch (Exception e)
- {
- AppTools.Log(e);
- }
- }
- }
- }
- catch (Exception e)
- {
- AppTools.Log(e);
- }
-
- return details;
- }
-
-#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
- public override async Task RefreshPackageIndexes()
- {
- // Npm does not support manual source refreshing
- }
-
- protected override ManagerCapabilities GetCapabilities()
- {
- return new ManagerCapabilities()
- {
- CanRunAsAdmin = true,
- SupportsCustomVersions = true,
- SupportsCustomScopes = true,
- };
- }
-
- protected override ManagerProperties GetProperties()
- {
- ManagerProperties properties = new()
- {
- Name = "Npm",
- Description = Tools.Translate("Node JS's package manager. Full of libraries and other utilities that orbit the javascript world
Contains: Node javascript libraries and other related utilities"),
- IconId = "node",
- ColorIconId = "node_color",
- ExecutableFriendlyName = "npm",
- InstallVerb = "install",
- UninstallVerb = "uninstall",
- UpdateVerb = "install",
- ExecutableCallArgs = " -NoProfile -ExecutionPolicy Bypass -Command npm",
-
- };
- return properties;
- }
protected override async Task LoadManager()
{
ManagerStatus status = new();
status.ExecutablePath = Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe");
- status.Found = File.Exists(await Tools.Which("npm"));
+ status.Found = (await CoreTools.Which("npm")).Item1;
if (!status.Found)
return status;
@@ -400,36 +297,6 @@ protected override async Task LoadManager()
return status;
}
- protected override async Task GetPackageVersions_Unsafe(Package package)
- {
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = Status.ExecutablePath,
- Arguments = Properties.ExecutableCallArgs + " show " + package.Id + " versions --json",
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
- StandardOutputEncoding = System.Text.Encoding.UTF8
- }
- };
-
- string line;
- List versions = new();
-
- p.Start();
-
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- if (line.Contains("\""))
- versions.Add(line.Trim().TrimStart('"').TrimEnd(',').TrimEnd('"'));
- }
-
- return versions.ToArray();
- }
+
}
}
diff --git a/src/UniGetUI.PackageEngine.Managers.Npm/NpmPackageDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.Npm/NpmPackageDetailsProvider.cs
new file mode 100644
index 000000000..38ef9f807
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Npm/NpmPackageDetailsProvider.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UniGetUI.Core.IconEngine;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.BaseProviders;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.NpmManager
+{
+ internal class NpmPackageDetailsProvider : BasePackageDetailsProvider
+ {
+ public NpmPackageDetailsProvider(Npm manager) : base(manager) { }
+
+ protected override async Task GetPackageDetails_Unsafe(Package package)
+ {
+ PackageDetails details = new(package);
+ try
+ {
+ details.InstallerType = "Tarball";
+ details.ManifestUrl = new Uri($"https://www.npmjs.com/package/{package.Id}");
+ details.ReleaseNotesUrl = new Uri($"https://www.npmjs.com/package/{package.Id}?activeTab=versions");
+
+ using (Process p = new())
+ {
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " info " + package.Id,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ p.Start();
+
+ List output = new();
+ string? line;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output.Add(line);
+ }
+
+ int lineNo = 0;
+ bool ReadingMaintainer = false;
+ foreach (string outLine in output)
+ {
+ try
+ {
+ lineNo++;
+ if (lineNo == 2)
+ {
+ details.License = outLine.Split("|")[1];
+ }
+ else if (lineNo == 3)
+ {
+ details.Description = outLine.Trim();
+ }
+ else if (lineNo == 4)
+ {
+ details.HomepageUrl = new Uri(outLine.Trim());
+ }
+ else if (outLine.StartsWith(".tarball"))
+ {
+ details.InstallerUrl = new Uri(outLine.Replace(".tarball: ", "").Trim());
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+ }
+ else if (outLine.StartsWith(".integrity"))
+ {
+ details.InstallerHash = outLine.Replace(".integrity: sha512-", "").Replace("==", "").Trim();
+ }
+ else if (outLine.StartsWith("maintainers:"))
+ {
+ ReadingMaintainer = true;
+ }
+ else if (ReadingMaintainer)
+ {
+ ReadingMaintainer = false;
+ details.Author = outLine.Replace("-", "").Split('<')[0].Trim();
+ }
+ else if (outLine.StartsWith("published"))
+ {
+ details.Publisher = outLine.Split("by").Last().Split('<')[0].Trim();
+ details.UpdateDate = outLine.Replace("published", "").Split("by")[0].Trim();
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn(e);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Error(e);
+ }
+
+ return details;
+ }
+
+ protected override Task GetPackageIcon_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override Task GetPackageScreenshots_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override async Task GetPackageVersions_Unsafe(Package package)
+ {
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show " + package.Id + " versions --json",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ string? line;
+ List versions = new();
+
+ p.Start();
+
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ if (line.Contains("\""))
+ versions.Add(line.Trim().TrimStart('"').TrimEnd(',').TrimEnd('"'));
+ }
+
+ return versions.ToArray();
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj b/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj
new file mode 100644
index 000000000..cfc05a17d
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI/PackageEngine/Managers/Pip.cs b/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs
similarity index 56%
rename from src/UniGetUI/PackageEngine/Managers/Pip.cs
rename to src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs
index f33cc34e9..28f27684f 100644
--- a/src/UniGetUI/PackageEngine/Managers/Pip.cs
+++ b/src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs
@@ -1,30 +1,57 @@
-using UniGetUI.PackageEngine.Classes;
-using UniGetUI.PackageEngine.Operations;
-using UniGetUI.Core;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
+using System.Diagnostics;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-
-namespace UniGetUI.PackageEngine.Managers
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.PipManager
{
public class Pip : PackageManager
{
new public static string[] FALSE_PACKAGE_NAMES = new string[] { "", "WARNING:", "[notice]", "Package", "DEPRECATION:" };
new public static string[] FALSE_PACKAGE_IDS = new string[] { "", "WARNING:", "[notice]", "Package", "DEPRECATION:" };
new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "", "Ignoring", "invalid" };
+
+ public Pip() : base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ SupportsCustomVersions = true,
+ SupportsCustomScopes = true,
+ SupportsPreRelease = true,
+ };
+
+ Properties= new ManagerProperties()
+ {
+ Name = "Pip",
+ Description = CoreTools.Translate("Python's library manager. Full of python libraries and other python-related utilities
Contains: Python libraries and related utilities"),
+ IconId = "python",
+ ColorIconId = "pip_color",
+ ExecutableFriendlyName = "pip",
+ InstallVerb = "install",
+ UninstallVerb = "uninstall",
+ UpdateVerb = "install --upgrade",
+ ExecutableCallArgs = " -m pip",
+ DefaultSource = new ManagerSource(this, "pip", new Uri("https://pypi.org/")),
+ KnownSources = [new ManagerSource(this, "pip", new Uri("https://pypi.org/"))],
+
+ };
+
+ PackageDetailsProvider = new PipPackageDetailsProvider(this);
+ }
+
protected override async Task FindPackages_UnSafe(string query)
{
List Packages = new();
- string path = await Tools.Which("parse_pip_search");
- if (!File.Exists(path))
+ var which_res = await CoreTools.Which("parse_pip_search");
+ string path = which_res.Item2;
+ if (!which_res.Item1)
{
Process proc = new()
{
@@ -57,7 +84,7 @@ protected override async Task FindPackages_UnSafe(string query)
p.Start();
- string line;
+ string? line;
bool DashesPassed = false;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
@@ -78,11 +105,11 @@ protected override async Task FindPackages_UnSafe(string query)
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this, scope: PackageScope.Global));
+ Packages.Add(new Package(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, scope: PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
return Packages.ToArray();
}
@@ -104,7 +131,7 @@ protected override async Task GetAvailableUpdates_UnSafe()
p.Start();
- string line;
+ string? line;
bool DashesPassed = false;
List Packages = new();
string output = "";
@@ -126,11 +153,11 @@ protected override async Task GetAvailableUpdates_UnSafe()
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new UpgradablePackage(Tools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], MainSource, this, scope: PackageScope.Global));
+ Packages.Add(new UpgradablePackage(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], DefaultSource, this, scope: PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
return Packages.ToArray();
}
@@ -153,7 +180,7 @@ protected override async Task GetInstalledPackages_UnSafe()
p.Start();
- string line;
+ string? line;
bool DashesPassed = false;
List Packages = new();
string output = "";
@@ -175,11 +202,11 @@ protected override async Task GetInstalledPackages_UnSafe()
if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
continue;
- Packages.Add(new Package(Tools.FormatAsName(elements[0]), elements[0], elements[1], MainSource, this, scope: PackageScope.Global));
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[0]), elements[0], elements[1], DefaultSource, this, scope: PackageScope.Global));
}
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
return Packages.ToArray();
}
@@ -241,145 +268,14 @@ public override string[] GetUninstallParameters(Package package, InstallationOpt
return parameters.ToArray();
}
- public override ManagerSource GetMainSource()
- {
- return new ManagerSource(this, "pip", new Uri("https://pypi.org/"));
- }
-
- public override async Task GetPackageDetails_UnSafe(Package package)
- {
- PackageDetails details = new(package);
-
- AppTools.Log("Getting package details for " + package.Id);
-
- string JsonString;
- HttpClient client = new();
- JsonString = await client.GetStringAsync($"https://pypi.org/pypi/{package.Id}/json");
-
- JsonObject RawInfo = JsonObject.Parse(JsonString) as JsonObject;
-
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("author"))
- details.Author = (RawInfo["info"] as JsonObject)["author"].ToString();
- }
- catch (Exception ex) { AppTools.Log("Can't load author: " + ex); }
-
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("home_page"))
- details.HomepageUrl = new Uri((RawInfo["info"] as JsonObject)["home_page"].ToString());
- }
- catch (Exception ex) { AppTools.Log("Can't load home_page: " + ex); }
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("package_url"))
- details.ManifestUrl = new Uri((RawInfo["info"] as JsonObject)["package_url"].ToString());
- }
- catch (Exception ex) { AppTools.Log("Can't load package_url: " + ex); }
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("summary"))
- details.Description = (RawInfo["info"] as JsonObject)["summary"].ToString();
- }
- catch (Exception ex) { AppTools.Log("Can't load summary: " + ex); }
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("license"))
- details.License = (RawInfo["info"] as JsonObject)["license"].ToString();
- }
- catch (Exception ex) { AppTools.Log("Can't load license: " + ex); }
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("maintainer"))
- details.Publisher = (RawInfo["info"] as JsonObject)["maintainer"].ToString();
- }
- catch (Exception ex) { AppTools.Log("Can't load maintainer: " + ex); }
- try
- {
- if ((RawInfo["info"] as JsonObject).ContainsKey("classifiers") && (RawInfo["info"] as JsonObject)["classifiers"] is JsonArray)
- {
- List Tags = new();
- foreach (string line in (RawInfo["info"] as JsonObject)["classifiers"] as JsonArray)
- if (line.Contains("License ::"))
- details.License = line.Split("::")[^1].Trim();
- else if (line.Contains("Topic ::"))
- if (!Tags.Contains(line.Split("::")[^1].Trim()))
- Tags.Add(line.Split("::")[^1].Trim());
- details.Tags = Tags.ToArray();
- }
- }
- catch (Exception ex) { AppTools.Log("Can't load classifiers: " + ex); }
-
- try
- {
- JsonObject? url = null;
- if (RawInfo.ContainsKey("url"))
-
- url = RawInfo["url"] as JsonObject;
- else if (RawInfo.ContainsKey("urls"))
- url = (RawInfo["urls"] as JsonArray)[0] as JsonObject;
-
- if (url != null)
- {
- if (url.ContainsKey("digests") && (url["digests"] as JsonObject).ContainsKey("sha256"))
- {
- details.InstallerHash = url["digests"]["sha256"].ToString();
- }
- if (url.ContainsKey("url"))
- {
- details.InstallerType = url["url"].ToString().Split('.')[^1].Replace("whl", "Wheel");
- details.InstallerUrl = new Uri(url["url"].ToString());
- details.InstallerSize = await Tools.GetFileSizeAsync(details.InstallerUrl);
- }
- }
- }
- catch (Exception ex) { AppTools.Log("Can't load installer data: " + ex); }
-
- return details;
- }
-
-#pragma warning disable CS1998
- public override async Task RefreshPackageIndexes()
- {
- // Pip does not support manual source refreshing
- }
-
- protected override ManagerCapabilities GetCapabilities()
- {
- return new ManagerCapabilities()
- {
- CanRunAsAdmin = true,
- SupportsCustomVersions = true,
- SupportsCustomScopes = true,
- SupportsPreRelease = true,
- };
- }
-
- protected override ManagerProperties GetProperties()
- {
- ManagerProperties properties = new()
- {
- Name = "Pip",
- Description = Tools.Translate("Python's library manager. Full of python libraries and other python-related utilities
Contains: Python libraries and related utilities"),
- IconId = "python",
- ColorIconId = "pip_color",
- ExecutableFriendlyName = "pip",
- InstallVerb = "install",
- UninstallVerb = "uninstall",
- UpdateVerb = "install --upgrade",
- ExecutableCallArgs = " -m pip",
-
- };
- return properties;
- }
protected override async Task LoadManager()
{
ManagerStatus status = new();
- status.ExecutablePath = await Tools.Which("python.exe");
- status.Found = File.Exists(status.ExecutablePath);
+ var which_res = await CoreTools.Which("python.exe");
+ status.ExecutablePath = which_res.Item2;
+ status.Found = which_res.Item1;
if (!status.Found)
return status;
@@ -405,39 +301,6 @@ protected override async Task LoadManager()
return status;
}
-
- protected override async Task GetPackageVersions_Unsafe(Package package)
- {
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = Status.ExecutablePath,
- Arguments = Properties.ExecutableCallArgs + " index versions " + package.Id,
- RedirectStandardOutput = true,
- RedirectStandardInput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- }
- };
-
- p.Start();
-
- string line;
- string[] result = new string[0];
- string output = "";
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- output += line + "\n";
- if (line.Contains("Available versions:"))
- result = line.Replace("Available versions:", "").Trim().Split(", ");
- }
-
- output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
- return result;
- }
}
}
+
diff --git a/src/UniGetUI.PackageEngine.Managers.Pip/PipPackageDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.Pip/PipPackageDetailsProvider.cs
new file mode 100644
index 000000000..5868f40f9
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Pip/PipPackageDetailsProvider.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using UniGetUI.Core.IconEngine;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.BaseProviders;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.PipManager
+{
+ internal class PipPackageDetailsProvider : BasePackageDetailsProvider
+ {
+ public PipPackageDetailsProvider(Pip manager) : base(manager) { }
+
+ protected override async Task GetPackageDetails_Unsafe(Package package)
+ {
+ PackageDetails details = new(package);
+
+
+ string JsonString;
+ HttpClient client = new();
+ JsonString = await client.GetStringAsync($"https://pypi.org/pypi/{package.Id}/json");
+
+ JsonObject? RawInfo = JsonObject.Parse(JsonString) as JsonObject;
+
+ if(RawInfo == null)
+ {
+ Logger.Error($"Can't load package info on manager {Manager.Name}, JsonObject? RawInfo was null");
+ return details;
+ }
+
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("author") ?? false)
+ details.Author = (RawInfo["info"] as JsonObject)?["author"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load author: " + ex); }
+
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("home_page") ?? false)
+ details.HomepageUrl = new Uri((RawInfo["info"] as JsonObject)?["home_page"]?.ToString() ?? "");
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load home_page: " + ex); }
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("package_url") ?? false)
+ details.ManifestUrl = new Uri((RawInfo["info"] as JsonObject)?["package_url"]?.ToString() ?? "");
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load package_url: " + ex); }
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("summary") ?? false)
+ details.Description = (RawInfo["info"] as JsonObject)?["summary"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load summary: " + ex); }
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("license") ?? false)
+ details.License = (RawInfo["info"] as JsonObject)?["license"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load license: " + ex); }
+ try
+ {
+ if ((RawInfo["info"] as JsonObject)?.ContainsKey("maintainer") ?? false)
+ details.Publisher = (RawInfo["info"] as JsonObject)?["maintainer"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load maintainer: " + ex); }
+ try
+ {
+ if (((RawInfo["info"] as JsonObject)?.ContainsKey("classifiers") ?? false)
+ && ((RawInfo["info"] as JsonObject)?["classifiers"] is JsonArray))
+ {
+ List Tags = new();
+ foreach (string? line in (RawInfo["info"] as JsonObject)?["classifiers"] as JsonArray ?? new())
+ if (line?.Contains("License ::") ?? false)
+ details.License = line.Split("::")[^1].Trim();
+ else if (line?.Contains("Topic ::") ?? false)
+ if (!Tags.Contains(line.Split("::")[^1].Trim()))
+ Tags.Add(line.Split("::")[^1].Trim());
+ details.Tags = Tags.ToArray();
+ }
+ }
+ catch (Exception ex) { Logger.Debug("[Pip] Can't load classifiers: " + ex); }
+
+ try
+ {
+ JsonObject? url = null;
+ if (RawInfo.ContainsKey("url"))
+
+ url = RawInfo["url"] as JsonObject;
+ else if (RawInfo.ContainsKey("urls"))
+ url = (RawInfo["urls"] as JsonArray)?[0] as JsonObject;
+
+ if (url != null)
+ {
+ if (url.ContainsKey("digests") && ((url["digests"] as JsonObject)?.ContainsKey("sha256") ?? false))
+ {
+ details.InstallerHash = url["digests"]?["sha256"]?.ToString() ?? "";
+ }
+ if (url.ContainsKey("url"))
+ {
+ details.InstallerType = url["url"]?.ToString().Split('.')[^1].Replace("whl", "Wheel") ?? "";
+ details.InstallerUrl = url["url"] != null? new Uri(url["url"]?.ToString() ?? ""): null;
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+ }
+ }
+ }
+ catch (Exception ex) { Logger.Debug("Can't load installer data: " + ex); }
+
+ return details;
+ }
+
+ protected override Task GetPackageIcon_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override Task GetPackageScreenshots_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override async Task GetPackageVersions_Unsafe(Package package)
+ {
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " index versions " + package.Id,
+ RedirectStandardOutput = true,
+ RedirectStandardInput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ p.Start();
+
+ string? line;
+ string[] result = new string[0];
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (line.Contains("Available versions:"))
+ result = line.Replace("Available versions:", "").Trim().Split(", ");
+ }
+
+ output += await p.StandardError.ReadToEndAsync();
+ Manager.LogOperation(p, output);
+ return result;
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj b/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj
new file mode 100644
index 000000000..0d96aa278
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs
new file mode 100644
index 000000000..81b22f395
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs
@@ -0,0 +1,274 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using UniGetUI.Core;
+using UniGetUI.PackageEngine.Classes;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+
+namespace UniGetUI.PackageEngine.Managers.PowerShellManager
+{
+ public class PowerShell : BaseNuGet
+ {
+ new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_IDS = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "" };
+
+ public PowerShell() : base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ CanSkipIntegrityChecks = true,
+ SupportsCustomVersions = true,
+ SupportsCustomScopes = true,
+ SupportsCustomSources = true,
+ SupportsPreRelease = true,
+ SupportsCustomPackageIcons = true,
+ Sources = new ManagerSource.Capabilities()
+ {
+ KnowsPackageCount = false,
+ KnowsUpdateDate = false,
+ }
+ };
+
+ Properties = new ManagerProperties()
+ {
+ Name = "PowerShell",
+ Description = CoreTools.Translate("PowerShell's package manager. Find libraries and scripts to expand PowerShell capabilities
Contains: Modules, Scripts, Cmdlets"),
+ IconId = "powershell",
+ ColorIconId = "powershell_color",
+ ExecutableFriendlyName = "powershell.exe",
+ InstallVerb = "Install-Module",
+ UninstallVerb = "Uninstall-Module",
+ UpdateVerb = "Update-Module",
+ ExecutableCallArgs = " -NoProfile -Command",
+ KnownSources = [new(this, "PSGallery", new Uri("https://www.powershellgallery.com/api/v2")),
+ new(this, "PoshTestGallery", new Uri("https://www.poshtestgallery.com/api/v2"))],
+ DefaultSource = new ManagerSource(this, "PSGallery", new Uri("https://www.powershellgallery.com/api/v2")),
+ };
+
+ SourceProvider = new PowerShellSourceProvider(this);
+ }
+ protected override async Task GetAvailableUpdates_UnSafe()
+ {
+ Process p = new();
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = "",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ p.Start();
+
+ await p.StandardInput.WriteLineAsync(@"
+ function Test-GalleryModuleUpdate {
+ param (
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [version] $Version,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Repository,
+ [switch] $NeedUpdateOnly
+ )
+ process {
+ $URLs = @{}
+ @(Get-PSRepository).ForEach({$URLs[$_.Name] = $_.SourceLocation})
+ $page = Invoke-WebRequest -Uri ($URLs[$Repository] + ""/package/$Name"") -UseBasicParsing -Maximum 0 -ea Ignore
+ [version]$latest = Split-Path -Path ($page.Headers.Location -replace ""$Name."" -replace "".nupkg"") -Leaf
+ $needsupdate = $Latest -gt $Version
+ if ($needsupdate) {
+ Write-Output($Name + ""|"" + $Version.ToString() + ""|"" + $Latest.ToString() + ""|"" + $Repository)
+ }
+ }
+ }
+ Get-InstalledModule | Test-GalleryModuleUpdate
+
+ exit
+ "); // do NOT remove the trailing endline
+ string? line;
+ List Packages = new();
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (line.StartsWith(">>"))
+ continue;
+
+ string[] elements = line.Split('|');
+ if (elements.Length < 4)
+ continue;
+
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (elements[1] + ".0" == elements[2] || elements[1] + ".0.0" == elements[2])
+ continue;
+
+ Packages.Add(new UpgradablePackage(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], GetSourceOrDefault(elements[3]), this));
+ }
+
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+ await p.WaitForExitAsync();
+
+ return Packages.ToArray();
+ }
+
+ protected override async Task GetInstalledPackages_UnSafe()
+ {
+ Process p = new();
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " Get-InstalledModule",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ p.Start();
+ string? line;
+ List Packages = new();
+ bool DashesPassed = false;
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (!DashesPassed)
+ {
+ if (line.Contains("-----"))
+ DashesPassed = true;
+ }
+ else
+ {
+ string[] elements = Regex.Replace(line, " {2,}", " ").Split(' ');
+ if (elements.Length < 3)
+ continue;
+
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ Packages.Add(new Package(CoreTools.FormatAsName(elements[1]), elements[1], elements[0], GetSourceOrDefault(elements[2]), this));
+ }
+ }
+
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+ await p.WaitForExitAsync();
+
+ return Packages.ToArray();
+ }
+
+ public override OperationVeredict GetInstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ return GetUninstallOperationVeredict(package, options, ReturnCode, Output);
+ }
+
+ public override OperationVeredict GetUpdateOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ return GetUninstallOperationVeredict(package, options, ReturnCode, Output);
+ }
+
+ public override OperationVeredict GetUninstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ string output_string = string.Join("\n", Output);
+
+ if (output_string.Contains("AdminPrivilegesAreRequired") && !options.RunAsAdministrator)
+ {
+ options.RunAsAdministrator = true;
+ return OperationVeredict.AutoRetry;
+ }
+
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+ public override string[] GetInstallParameters(Package package, InstallationOptions options)
+ {
+ List parameters = GetUpdateParameters(package, options).ToList();
+ parameters[0] = Properties.InstallVerb;
+
+ parameters.AddRange(new string[] { "-AllowClobber" });
+ if (package.Scope == PackageScope.Global)
+ parameters.AddRange(new string[] { "-Scope", "AllUsers" });
+ else
+ parameters.AddRange(new string[] { "-Scope", "CurrentUser" });
+
+ if (options.Version != "")
+ parameters.AddRange(new string[] { "-RequiredVersion", options.Version });
+
+ return parameters.ToArray();
+
+ }
+ public override string[] GetUpdateParameters(Package package, InstallationOptions options)
+ {
+ List parameters = GetUninstallParameters(package, options).ToList();
+ parameters[0] = Properties.UpdateVerb;
+
+ if (options.PreRelease)
+ parameters.Add("-AllowPrerelease");
+
+ if (options.SkipHashCheck)
+ parameters.Add("-SkipPublisherCheck");
+
+ return parameters.ToArray();
+ }
+
+ public override string[] GetUninstallParameters(Package package, InstallationOptions options)
+ {
+ List parameters = new() { Properties.UninstallVerb, "-Name", package.Id, "-Confirm:$false", "-Force" };
+
+ if (options.CustomParameters != null)
+ parameters.AddRange(options.CustomParameters);
+
+ return parameters.ToArray();
+ }
+
+ protected override async Task LoadManager()
+ {
+ ManagerStatus status = new()
+ {
+ ExecutablePath = Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe")
+ };
+ status.Found = File.Exists(status.ExecutablePath);
+
+ if (!status.Found)
+ return status;
+
+ Process process = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " \"echo $PSVersionTable\"",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+ process.Start();
+ status.Version = (await process.StandardOutput.ReadToEndAsync()).Trim();
+
+ if (status.Found && IsEnabled())
+ await RefreshPackageIndexes();
+
+ return status;
+ }
+
+ }
+
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShellSourceProvider.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShellSourceProvider.cs
new file mode 100644
index 000000000..a501d9de4
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShellSourceProvider.cs
@@ -0,0 +1,91 @@
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using UniGetUI.Core.Logging;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Classes.Manager.Providers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+
+namespace UniGetUI.PackageEngine.Managers.PowerShellManager
+{
+ internal class PowerShellSourceProvider : BaseSourceProvider
+ {
+ public PowerShellSourceProvider(PowerShell manager) : base(manager) { }
+
+ public override string[] GetAddSourceParameters(ManagerSource source)
+ {
+ if (source.Url.ToString() == "https://www.powershellgallery.com/api/v2")
+ return new string[] { "Register-PSRepository", "-Default" };
+ return new string[] { "Register-PSRepository", "-Name", source.Name, "-SourceLocation", source.Url.ToString() };
+ }
+
+ public override string[] GetRemoveSourceParameters(ManagerSource source)
+ {
+ return new string[] { "Unregister-PSRepository", "-Name", source.Name };
+ }
+
+ public override OperationVeredict GetAddSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ public override OperationVeredict GetRemoveSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ protected override async Task GetSources_UnSafe()
+ {
+ List sources = new();
+
+ Process process = new();
+ ProcessStartInfo startInfo = new()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " Get-PSRepository",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+
+ process.StartInfo = startInfo;
+ process.Start();
+
+ bool dashesPassed = false;
+ string? line;
+ string output = "";
+ while ((line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ try
+ {
+ if (string.IsNullOrEmpty(line))
+ continue;
+
+ if (!dashesPassed)
+ {
+ if (line.Contains("---"))
+ dashesPassed = true;
+ }
+ else
+ {
+ string[] parts = Regex.Replace(line.Trim(), " {2,}", " ").Split(' ');
+ if (parts.Length >= 3)
+ sources.Add(new ManagerSource(Manager, parts[0].Trim(), new Uri(parts[2].Trim())));
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn(e);
+ }
+ }
+ output += await process.StandardError.ReadToEndAsync();
+ Manager.LogOperation(process, output);
+ await process.WaitForExitAsync();
+ return sources.ToArray();
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj b/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj
new file mode 100644
index 000000000..942b61f2f
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs
new file mode 100644
index 000000000..1ebac5931
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs
@@ -0,0 +1,431 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text.Json.Nodes;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using UniGetUI.Core;
+using UniGetUI.PackageEngine.Classes;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+
+namespace UniGetUI.PackageEngine.Managers.ScoopManager
+{
+
+ public class Scoop : PackageManager
+ {
+ new public static string[] FALSE_PACKAGE_NAMES = new string[] { "" };
+ new public static string[] FALSE_PACKAGE_IDS = new string[] { "No" };
+ new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "Matches" };
+
+ public Scoop(): base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ CanSkipIntegrityChecks = true,
+ CanRemoveDataOnUninstall = true,
+ SupportsCustomArchitectures = true,
+ SupportedCustomArchitectures = new Architecture[] { Architecture.X86, Architecture.X64, Architecture.Arm64 },
+ SupportsCustomScopes = true,
+ SupportsCustomSources = true,
+ Sources = new ManagerSource.Capabilities()
+ {
+ KnowsPackageCount = true,
+ KnowsUpdateDate = true
+ }
+ };
+
+ Properties = new ManagerProperties()
+ {
+ Name = "Scoop",
+ Description = CoreTools.Translate("Great repository of unknown but useful utilities and other interesting packages.
Contains: Utilities, Command-line programs, General Software (extras bucket required)"),
+ IconId = "scoop",
+ ColorIconId = "scoop_color",
+ ExecutableCallArgs = " -NoProfile -ExecutionPolicy Bypass -Command scoop",
+ ExecutableFriendlyName = "scoop",
+ InstallVerb = "install",
+ UpdateVerb = "update",
+ UninstallVerb = "uninstall",
+ KnownSources = [new(this, "main", new Uri("https://github.com/ScoopInstaller/Main")),
+ new(this, "extras", new Uri("https://github.com/ScoopInstaller/Extras")),
+ new(this, "versions", new Uri("https://github.com/ScoopInstaller/Versions")),
+ new(this, "nirsoft", new Uri("https://github.com/kodybrown/scoop-nirsoft")),
+ new(this, "sysinternals", new Uri("https://github.com/niheaven/scoop-sysinternals")),
+ new(this, "php", new Uri("https://github.com/ScoopInstaller/PHP")),
+ new(this, "nerd-fonts", new Uri("https://github.com/matthewjberger/scoop-nerd-fonts")),
+ new(this, "nonportable", new Uri("https://github.com/ScoopInstaller/Nonportable")),
+ new(this, "java", new Uri("https://github.com/ScoopInstaller/Java")),
+ new(this, "games", new Uri("https://github.com/Calinou/scoop-games"))],
+ DefaultSource = new(this, "main", new Uri("https://github.com/ScoopInstaller/Main")),
+ };
+
+ SourceProvider = new ScoopSourceProvider(this);
+ PackageDetailsProvider = new ScoopPackageDetailsProvider(this);
+ }
+
+ protected override async Task FindPackages_UnSafe(string query)
+ {
+ List Packages = new();
+
+ var which_res = await CoreTools.Which("scoop-search.exe");
+ string path = which_res.Item2;
+ if (!which_res.Item1)
+ {
+ Process proc = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " install main/scoop-search",
+ UseShellExecute = true,
+ CreateNoWindow = true
+ }
+ };
+ proc.Start();
+ await proc.WaitForExitAsync();
+ path = "scoop-search.exe";
+ }
+
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = path,
+ Arguments = query,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ p.Start();
+
+ string? line;
+ ManagerSource source = Properties.DefaultSource;
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (line.StartsWith("'"))
+ {
+ string sourceName = line.Split(" ")[0].Replace("'", "");
+ source = GetSourceOrDefault(sourceName);
+ }
+ else if (line.Trim() != "")
+ {
+ string[] elements = line.Trim().Split(" ");
+ if (elements.Length < 2)
+ continue;
+
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
+ continue;
+
+ Packages.Add(new Package(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1].Replace("(", "").Replace(")", ""), source, this));
+ }
+ }
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+ return Packages.ToArray();
+ }
+
+ protected override async Task GetAvailableUpdates_UnSafe()
+ {
+ Dictionary InstalledPackages = new();
+ foreach (Package InstalledPackage in await GetInstalledPackages())
+ {
+ if (!InstalledPackages.ContainsKey(InstalledPackage.Id + "." + InstalledPackage.Version))
+ InstalledPackages.Add(InstalledPackage.Id + "." + InstalledPackage.Version, InstalledPackage);
+ }
+
+ List Packages = new();
+
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " status",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ p.Start();
+
+ string? line;
+ bool DashesPassed = false;
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (!DashesPassed)
+ {
+ if (line.Contains("---"))
+ DashesPassed = true;
+ }
+ else if (line.Trim() != "")
+ {
+ string[] elements = Regex.Replace(line, " {2,}", " ").Trim().Split(" ");
+ if (elements.Length < 3)
+ continue;
+
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
+ continue;
+
+ if (!InstalledPackages.ContainsKey(elements[0] + "." + elements[1]))
+ {
+ Logger.Warn("Upgradable scoop package not listed on installed packages - id=" + elements[0]);
+ continue;
+ }
+
+ Packages.Add(new UpgradablePackage(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1], elements[2], InstalledPackages[elements[0] + "." + elements[1]].Source, this, InstalledPackages[elements[0] + "." + elements[1]].Scope));
+ }
+ }
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+ return Packages.ToArray();
+ }
+
+ protected override async Task GetInstalledPackages_UnSafe()
+ {
+ List Packages = new();
+
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " list",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ p.Start();
+
+ string? line;
+ bool DashesPassed = false;
+ string output = "";
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ output += line + "\n";
+ if (!DashesPassed)
+ {
+ if (line.Contains("---"))
+ DashesPassed = true;
+ }
+ else if (line.Trim() != "")
+ {
+ string[] elements = Regex.Replace(line, " {2,}", " ").Trim().Split(" ");
+ if (elements.Length < 3)
+ continue;
+
+ for (int i = 0; i < elements.Length; i++) elements[i] = elements[i].Trim();
+
+ if (FALSE_PACKAGE_IDS.Contains(elements[0]) || FALSE_PACKAGE_VERSIONS.Contains(elements[1]))
+ continue;
+
+ PackageScope scope = PackageScope.User;
+ if (line.Contains("Global install"))
+ scope = PackageScope.Global;
+
+ Packages.Add(new Package(Core.Tools.CoreTools.FormatAsName(elements[0]), elements[0], elements[1], GetSourceOrDefault(elements[2]), this, scope));
+ }
+ }
+ output += await p.StandardError.ReadToEndAsync();
+ LogOperation(p, output);
+ return Packages.ToArray();
+ }
+
+
+ public override OperationVeredict GetUninstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ string output_string = string.Join("\n", Output);
+ if ((output_string.Contains("Try again with the --global (or -g) flag instead") && package.Scope == PackageScope.Local))
+ {
+ package.Scope = PackageScope.Global;
+ return OperationVeredict.AutoRetry;
+ }
+ if (output_string.Contains("requires admin rights") || output_string.Contains("requires administrator rights") || output_string.Contains("you need admin rights to install global apps"))
+ {
+ options.RunAsAdministrator = true;
+ return OperationVeredict.AutoRetry;
+ }
+ if (output_string.Contains("was uninstalled"))
+ return OperationVeredict.Succeeded;
+ return OperationVeredict.Failed;
+ }
+ public override OperationVeredict GetInstallOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ string output_string = string.Join("\n", Output);
+ if ((output_string.Contains("Try again with the --global (or -g) flag instead") && package.Scope == PackageScope.Local))
+ {
+ package.Scope = PackageScope.Global;
+ return OperationVeredict.AutoRetry;
+ }
+ if (output_string.Contains("requires admin rights") || output_string.Contains("requires administrator rights") || output_string.Contains("you need admin rights to install global apps"))
+ {
+ options.RunAsAdministrator = true;
+ return OperationVeredict.AutoRetry;
+ }
+ if (output_string.Contains("ERROR"))
+ return OperationVeredict.Failed;
+ return OperationVeredict.Succeeded;
+ }
+ public override OperationVeredict GetUpdateOperationVeredict(Package package, InstallationOptions options, int ReturnCode, string[] Output)
+ {
+ return GetInstallOperationVeredict(package, options, ReturnCode, Output);
+ }
+
+ public override string[] GetUninstallParameters(Package package, InstallationOptions options)
+ {
+ List parameters = new();
+
+ parameters.Add(Properties.UninstallVerb);
+ parameters.Add(package.Source.Name + "/" + package.Id);
+
+ if (package.Scope == PackageScope.Global)
+ parameters.Add("--global");
+
+ if (options.CustomParameters != null)
+ parameters.AddRange(options.CustomParameters);
+
+ if (options.RemoveDataOnUninstall)
+ parameters.Add("--purge");
+
+ return parameters.ToArray();
+ }
+ public override string[] GetInstallParameters(Package package, InstallationOptions options)
+ {
+ string[] parameters = GetUpdateParameters(package, options);
+ parameters[0] = Properties.InstallVerb;
+ return parameters;
+ }
+ public override string[] GetUpdateParameters(Package package, InstallationOptions options)
+ {
+ List parameters = GetUninstallParameters(package, options).ToList();
+ parameters[0] = Properties.UpdateVerb;
+
+ parameters.Remove("--purge");
+
+ switch (options.Architecture)
+ {
+ case null:
+ break;
+ case Architecture.X64:
+ parameters.Add("--arch");
+ parameters.Add("64bit");
+ break;
+ case Architecture.X86:
+ parameters.Add("--arch");
+ parameters.Add("32bit");
+ break;
+ case Architecture.Arm64:
+ parameters.Add("--arch");
+ parameters.Add("arm64");
+ break;
+ }
+
+ if (options.SkipHashCheck)
+ {
+ parameters.Add("--skip");
+ }
+
+ return parameters.ToArray();
+ }
+
+ public override async Task RefreshPackageIndexes()
+ {
+ Process process = new();
+ ProcessStartInfo StartInfo = new()
+ {
+ FileName = Properties.ExecutableFriendlyName,
+ Arguments = Properties.ExecutableCallArgs + " update"
+ };
+ process.StartInfo = StartInfo;
+ process.Start();
+ await process.WaitForExitAsync();
+ }
+
+ protected override async Task LoadManager()
+ {
+ ManagerStatus status = new()
+ {
+ ExecutablePath = Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe")
+ };
+
+ Process process = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " --version",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+ process.Start();
+ status.Version = (await process.StandardOutput.ReadToEndAsync()).Trim();
+ status.Found = process.ExitCode == 0;
+
+
+ if (status.Found && IsEnabled())
+ _ = RefreshPackageIndexes();
+
+
+ Status = status; // Wee need this for the RunCleanup method to get the executable path
+ if (status.Found && IsEnabled() && Settings.Get("EnableScoopCleanup"))
+ RunCleanup();
+
+ return status;
+ }
+
+ private async void RunCleanup()
+ {
+ Logger.Info("Starting scoop cleanup...");
+ foreach (string command in new string[] { " cache rm *", " cleanup --all --cache", " cleanup --all --global --cache" })
+ {
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Status.ExecutablePath,
+ Arguments = Properties.ExecutableCallArgs + " " + command,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+ p.Start();
+ await p.WaitForExitAsync();
+ }
+ Logger.Info("Scoop cleanup finished!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopPackageDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopPackageDetailsProvider.cs
new file mode 100644
index 000000000..9c098a181
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopPackageDetailsProvider.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+using UniGetUI.Core.IconEngine;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.BaseProviders;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.ScoopManager
+{
+ internal class ScoopPackageDetailsProvider : BasePackageDetailsProvider
+ {
+ public ScoopPackageDetailsProvider(Scoop manager) : base(manager) { }
+
+ protected override async Task GetPackageDetails_Unsafe(Package package)
+ {
+ PackageDetails details = new(package);
+
+ if (package.Source.Url != null)
+ try
+ {
+ details.ManifestUrl = new Uri(package.Source.Url.ToString() + "/blob/master/bucket/" + package.Id + ".json");
+ }
+ catch (Exception ex)
+ {
+ Logger.Error("Cannot load package manifest URL");
+ Logger.Error(ex);
+ }
+
+ Process p = new();
+ p.StartInfo = new ProcessStartInfo()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " cat " + package.Source.Name + "/" + package.Id,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8,
+ };
+
+ p.Start();
+ string JsonString = await p.StandardOutput.ReadToEndAsync();
+
+ JsonObject? RawInfo = JsonObject.Parse(JsonString) as JsonObject;
+
+ if(RawInfo == null)
+ {
+ throw new Exception("Deserialized RawInfo was null");
+ }
+
+ try
+ {
+ if (RawInfo.ContainsKey("description") && (RawInfo["description"] is JsonArray))
+ {
+ details.Description = "";
+ foreach (JsonNode? note in RawInfo["description"] as JsonArray ?? new())
+ details.Description += note?.ToString() + "\n";
+ details.Description = details.Description.Replace("\n\n", "\n").Trim();
+ }
+ else if (RawInfo.ContainsKey("description"))
+ details.Description = RawInfo["description"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load description: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("innosetup"))
+ details.InstallerType = "Inno Setup (" + CoreTools.Translate("extracted") + ")";
+ else
+ details.InstallerType = CoreTools.Translate("Scoop package");
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load installer type: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("homepage"))
+ {
+ details.HomepageUrl = RawInfo["homepage"] != null? new Uri(RawInfo["homepage"]?.ToString() ?? ""): null;
+ if (details.HomepageUrl?.ToString().Contains("https://github.com/") ?? false)
+ details.Author = details.HomepageUrl.ToString().Replace("https://github.com/", "").Split("/")[0];
+ else
+ details.Author = details.HomepageUrl?.Host.Split(".")[^2] ?? "";
+ }
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load homepage: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("notes") && (RawInfo["notes"] is JsonArray))
+ {
+ details.ReleaseNotes = "";
+ foreach (JsonNode? note in RawInfo["notes"] as JsonArray ?? new())
+ details.ReleaseNotes += note?.ToString() + "\n";
+ details.ReleaseNotes = details.ReleaseNotes.Replace("\n\n", "\n").Trim();
+ }
+ else if (RawInfo.ContainsKey("notes"))
+ details.ReleaseNotes = RawInfo["notes"]?.ToString() ?? "";
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load notes: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("license"))
+ {
+ if (RawInfo["license"] is not JsonValue)
+ {
+ details.License = RawInfo["license"]?["identifier"]?.ToString() ?? "";
+ details.LicenseUrl = RawInfo["license"]?["url"] != null? new Uri(RawInfo["license"]?["url"]?.ToString() ?? ""): null;
+ }
+ else
+ details.License = RawInfo["license"]?.ToString() ?? "";
+ }
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load license: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("url") && RawInfo.ContainsKey("hash"))
+ {
+ if (RawInfo["url"] is JsonArray)
+ details.InstallerUrl = RawInfo["url"] != null? new Uri(RawInfo["url"]?[0]?.ToString() ?? ""): null;
+ else
+ details.InstallerUrl = RawInfo["url"] != null? new Uri(RawInfo["url"]?.ToString() ?? ""): null;
+
+ if (RawInfo["hash"] is JsonArray)
+ details.InstallerHash = RawInfo["hash"]?[0]?.ToString() ?? "";
+ else
+ details.InstallerHash = RawInfo["hash"]?.ToString() ?? "";
+ }
+ else if (RawInfo.ContainsKey("architecture"))
+ {
+ string FirstArch = (RawInfo["architecture"] as JsonObject)?.ElementAt(0).Key ?? "";
+ details.InstallerHash = RawInfo["architecture"]?[FirstArch]?["hash"]?.ToString() ?? "";
+ details.InstallerUrl = RawInfo["architecture"]?[FirstArch]?["url"] != null?
+ new Uri(RawInfo["architecture"]?[FirstArch]?["url"]?.ToString() ?? ""): null;
+ }
+
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load installer URL: " + ex); }
+
+ try
+ {
+ if (RawInfo.ContainsKey("checkver") && RawInfo["checkver"] is JsonObject && ((RawInfo["checkver"] as JsonObject)?.ContainsKey("url") ?? false))
+ details.ReleaseNotesUrl = RawInfo["checkver"]?["url"] != null? new Uri(RawInfo["checkver"]?["url"]?.ToString() ?? ""): null;
+ }
+ catch (Exception ex) { Logger.Debug("[Scoop] Can't load notes URL: " + ex); }
+
+ return details;
+
+ }
+
+ protected override Task GetPackageIcon_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override Task GetPackageScreenshots_Unsafe(Package package)
+ {
+ throw new NotImplementedException();
+ }
+
+#pragma warning disable
+ protected override async Task GetPackageVersions_Unsafe(Package package)
+ {
+ throw new Exception("Scoop does not support custom package versions");
+ }
+ }
+#pragma warning enable
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopSourceProvider.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopSourceProvider.cs
new file mode 100644
index 000000000..fa17cb335
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Scoop/ScoopSourceProvider.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using UniGetUI.Core.Logging;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Classes.Manager.Providers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+
+namespace UniGetUI.PackageEngine.Managers.ScoopManager
+{
+ internal class ScoopSourceProvider : BaseSourceProvider
+ {
+ public ScoopSourceProvider(Scoop manager) : base(manager) { }
+
+ public override OperationVeredict GetAddSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ public override string[] GetAddSourceParameters(ManagerSource source)
+ {
+ return new string[] { "bucket", "add", source.Name, source.Url.ToString() };
+ }
+
+ public override OperationVeredict GetRemoveSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
+ {
+ return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
+ }
+
+ public override string[] GetRemoveSourceParameters(ManagerSource source)
+ {
+ return new string[] { "bucket", "rm", source.Name };
+ }
+
+ protected override async Task GetSources_UnSafe()
+ {
+ using (Process process = new())
+ {
+ process.StartInfo.FileName = Manager.Status.ExecutablePath;
+ process.StartInfo.Arguments = Manager.Properties.ExecutableCallArgs + " bucket list";
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.RedirectStandardError = true;
+ process.StartInfo.RedirectStandardInput = true;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.StandardInputEncoding = System.Text.Encoding.UTF8;
+ process.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
+
+ List sources = new();
+
+ process.Start();
+
+ string _output = "";
+ bool DashesPassed = false;
+
+ string? line;
+ while ((line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ _output += line + "\n";
+ try
+ {
+ if (!DashesPassed)
+ {
+ if (line.Contains("---"))
+ DashesPassed = true;
+ }
+ else if (line.Trim() != "")
+ {
+ string[] elements = Regex.Replace(line.Replace("AM", "").Replace("PM", "").Trim(), " {2,}", " ").Split(' ');
+ if (elements.Length >= 5)
+ {
+ if (!elements[1].Contains("https://"))
+ elements[1] = "https://scoop.sh/"; // If the URI is invalid, we'll use the main website
+ sources.Add(new ManagerSource(Manager, elements[0].Trim(), new Uri(elements[1].Trim()), int.Parse(elements[4].Trim()), elements[2].Trim() + " " + elements[3].Trim()));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn(e);
+ }
+ }
+ _output += await process.StandardError.ReadToEndAsync();
+ Manager.LogOperation(process, _output);
+
+ await process.WaitForExitAsync();
+
+
+ return sources.ToArray();
+ }
+ }
+ }
+}
diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj b/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj
new file mode 100644
index 000000000..1446938aa
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj
new file mode 100644
index 000000000..24f61f4f4
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
diff --git a/src/UniGetUI/PackageEngine/Managers/Winget.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
similarity index 69%
rename from src/UniGetUI/PackageEngine/Managers/Winget.cs
rename to src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
index 6ea4f067d..2a408544c 100644
--- a/src/UniGetUI/PackageEngine/Managers/Winget.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
@@ -1,46 +1,96 @@
-using UniGetUI.Core.Data;
-using UniGetUI.PackageEngine.Classes;
-using UniGetUI.PackageEngine.Operations;
-using UniGetUI.Core;
using System;
using System.Collections.Generic;
-using System.ComponentModel.Design;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Net;
using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using Windows.Services.TargetedContent;
+using UniGetUI.Core;
+using UniGetUI.Core.Data;
+using UniGetUI.PackageEngine.Classes;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.ManagerClasses.Manager;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using Windows.Graphics.Display;
-namespace UniGetUI.PackageEngine.Managers
+namespace UniGetUI.PackageEngine.Managers.WingetManager
{
- public class Winget : PackageManagerWithSources
+ public class WinGet : PackageManager
{
new public static string[] FALSE_PACKAGE_NAMES = new string[] { "", "e(s)", "have", "the", "Id" };
new public static string[] FALSE_PACKAGE_IDS = new string[] { "", "e(s)", "have", "an", "'winget", "pin'", "have", "an", "Version" };
new public static string[] FALSE_PACKAGE_VERSIONS = new string[] { "", "have", "an", "'winget", "pin'", "have", "an", "Version" };
- private static LocalPcSource LocalPcSource { get; } = new LocalPcSource();
- private static AndroidSubsystemSource AndroidSubsystemSource { get; } = new AndroidSubsystemSource();
- private static SteamSource SteamSource { get; } = new SteamSource();
- private static UbisoftConnectSource UbisoftConnectSource { get; } = new UbisoftConnectSource();
- private static GOGSource GOGSource { get; } = new GOGSource();
- private static MicrosoftStoreSource MicrosoftStoreSource { get; } = new MicrosoftStoreSource();
-
- private IWinGetPackageHelper WinGetHelper;
-
+ private LocalWingetSource LocalPcSource { get; set; }
+ private LocalWingetSource AndroidSubsystemSource { get; set; }
+ private LocalWingetSource SteamSource { get; set; }
+ private LocalWingetSource UbisoftConnectSource { get; set; }
+ private LocalWingetSource GOGSource { get; set; }
+ private LocalWingetSource MicrosoftStoreSource { get; set; }
+
+ public WinGet(): base()
+ {
+ Capabilities = new ManagerCapabilities()
+ {
+ CanRunAsAdmin = true,
+ CanSkipIntegrityChecks = true,
+ CanRunInteractively = true,
+ SupportsCustomVersions = true,
+ SupportsCustomArchitectures = true,
+ SupportedCustomArchitectures = new Architecture[] { Architecture.X86, Architecture.X64, Architecture.Arm64 },
+ SupportsCustomScopes = true,
+ SupportsCustomLocations = true,
+ SupportsCustomSources = true,
+ SupportsCustomPackageIcons = true,
+ SupportsCustomPackageScreenshots = true,
+ Sources = new ManagerSource.Capabilities()
+ {
+ KnowsPackageCount = false,
+ KnowsUpdateDate = true,
+ MustBeInstalledAsAdmin = true,
+ }
+ };
+
+ Properties = new ManagerProperties()
+ {
+ Name = "Winget",
+ Description = CoreTools.Translate("Microsoft's official package manager. Full of well-known and verified packages
Contains: General Software, Microsoft Store apps"),
+ IconId = "winget",
+ ColorIconId = "winget_color",
+ ExecutableFriendlyName = "winget.exe",
+ InstallVerb = "install",
+ UninstallVerb = "uninstall",
+ UpdateVerb = "update",
+ ExecutableCallArgs = "",
+ KnownSources = [ new(this, "winget", new Uri("https://cdn.winget.microsoft.com/cache")),
+ new(this, "msstore", new Uri("https://storeedgefd.dsx.mp.microsoft.com/v9.0")) ],
+ DefaultSource = new(this, "winget", new Uri("https://cdn.winget.microsoft.com/cache"))
+ };
+
+ SourceProvider = new WinGetSourceProvider(this);
+ PackageDetailsProvider = new WinGetPackageDetailsProvider(this);
+
+ LocalPcSource = new LocalWingetSource(this, CoreTools.Translate("Local PC"), "localpc");
+ AndroidSubsystemSource = new(this, CoreTools.Translate("Android Subsystem"), "android");
+ SteamSource = new(this, "Steam", "steam");
+ UbisoftConnectSource = new(this, "Ubisoft Connect", "uplay");
+ GOGSource = new(this, "GOG", "gog");
+ MicrosoftStoreSource = new(this, "Microsoft Store", "msstore");
+ }
+
protected override async Task FindPackages_UnSafe(string query)
{
- return await WinGetHelper.FindPackages_UnSafe(this, query);
+ return await WinGetHelper.Instance.FindPackages_UnSafe(this, query);
}
protected override async Task GetAvailableUpdates_UnSafe()
{
- var Packages = new List();
+ List Packages = new();
- Process p = new Process();
+ Process p = new();
p.StartInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
@@ -85,7 +135,7 @@ function Print-WinGetPackage {
");
- string line;
+ string? line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
@@ -97,13 +147,13 @@ function Print-WinGetPackage {
if (elements.Length < 5)
continue;
- ManagerSource source = SourceFactory.GetSourceOrDefault(elements[4]);
+ ManagerSource source = GetSourceOrDefault(elements[4]);
Packages.Add(new UpgradablePackage(elements[0][1..], elements[1], elements[2], elements[3], source, this));
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
await p.WaitForExitAsync();
return Packages.ToArray();
@@ -111,9 +161,9 @@ function Print-WinGetPackage {
protected override async Task GetInstalledPackages_UnSafe()
{
- var Packages = new List();
+ List Packages = new();
- Process p = new Process();
+ Process p = new();
p.StartInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
@@ -153,7 +203,7 @@ function Print-WinGetPackage {
exit
");
- string line;
+ string? line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
@@ -167,7 +217,7 @@ function Print-WinGetPackage {
ManagerSource source;
if (elements[3] != "")
- source = SourceFactory.GetSourceOrDefault(elements[3]);
+ source = GetSourceOrDefault(elements[3]);
else
source = GetLocalSource(elements[1]);
@@ -175,7 +225,7 @@ function Print-WinGetPackage {
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(this, p, output);
+ LogOperation(p, output);
await p.WaitForExitAsync();
return Packages.ToArray();
@@ -217,7 +267,8 @@ private ManagerSource GetLocalSource(string id)
}
catch (Exception ex)
{
- AppTools.Log(ex);
+ Logger.Warn($"Could not parse local source for package {id}");
+ Logger.Warn(ex);
return LocalPcSource;
}
}
@@ -272,7 +323,9 @@ public override string[] GetUpdateParameters(Package package, InstallationOption
public override string[] GetUninstallParameters(Package package, InstallationOptions options)
{
List parameters = new() { Properties.UninstallVerb };
- parameters.AddRange(new string[] { "--id", package.Id, "--exact", "--source", package.Source.Name });
+ parameters.AddRange(new string[] { "--id", package.Id, "--exact" });
+ if(!package.Source.IsVirtualManager)
+ parameters.AddRange(new string[] { "--source", package.Source.Name });
parameters.Add("--accept-source-agreements");
@@ -309,14 +362,14 @@ public override OperationVeredict GetInstallOperationVeredict(Package package, I
if (output_string.Contains("No applicable upgrade found") || output_string.Contains("No newer package versions are available from the configured sources"))
return OperationVeredict.Succeeded;
- if(output_string.Contains("winget settings --enable InstallerHashOverride"))
+ if (output_string.Contains("winget settings --enable InstallerHashOverride"))
{
- AppTools.Log("Enabling skip hash ckeck for winget...");
- Process p = new Process()
+ Logger.Info("Enabling skip hash ckeck for winget...");
+ Process p = new()
{
StartInfo = new ProcessStartInfo()
{
- FileName = CoreData.GSudoPath,
+ // FileName = AppTools.GSudoPath,
Arguments = Status.ExecutablePath + " " + Properties.ExecutableCallArgs + " settings --enable InstallerHashOverride",
UseShellExecute = false,
RedirectStandardOutput = true,
@@ -351,84 +404,18 @@ public override OperationVeredict GetUninstallOperationVeredict(Package package,
return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
}
-
- public override ManagerSource GetMainSource()
- {
- return new ManagerSource(this, "winget", new Uri("https://cdn.winget.microsoft.com/cache"));
- }
-
- protected override async Task GetPackageVersions_Unsafe(Package package)
- {
- return await WinGetHelper.GetPackageVersions_Unsafe(this, package);
- }
-
- public override async Task GetPackageDetails_UnSafe(Package package)
- {
- return await WinGetHelper.GetPackageDetails_UnSafe(this, package);
- }
-
- protected override async Task GetSources_UnSafe()
- {
- return await WinGetHelper.GetSources_UnSafe(this);
- }
-
- public override async Task RefreshPackageIndexes()
- {
- await Task.Delay(0);
- // As of WinGet 1.6, WinGet does handle updating package indexes automatically
- }
-
- protected override ManagerCapabilities GetCapabilities()
- {
- return new ManagerCapabilities()
- {
- CanRunAsAdmin = true,
- CanSkipIntegrityChecks = true,
- CanRunInteractively = true,
- SupportsCustomVersions = true,
- SupportsCustomArchitectures = true,
- SupportedCustomArchitectures = new Architecture[] { Architecture.X86, Architecture.X64, Architecture.Arm64 },
- SupportsCustomScopes = true,
- SupportsCustomLocations = true,
- SupportsCustomSources = true,
- Sources = new ManagerSource.Capabilities()
- {
- KnowsPackageCount = false,
- KnowsUpdateDate = true,
- MustBeInstalledAsAdmin = true,
- }
- };
- }
-
- protected override ManagerProperties GetProperties()
- {
- ManagerProperties properties = new()
- {
- Name = "Winget",
- Description = Tools.Translate("Microsoft's official package manager. Full of well-known and verified packages
Contains: General Software, Microsoft Store apps"),
- IconId = "winget",
- ColorIconId = "winget_color",
- ExecutableFriendlyName = "winget.exe",
- InstallVerb = "install",
- UninstallVerb = "uninstall",
- UpdateVerb = "update",
- ExecutableCallArgs = "",
- };
- return properties;
- }
-
protected override async Task LoadManager()
{
ManagerStatus status = new();
-
- status.ExecutablePath = await Tools.Which("winget.exe");
- status.Found = File.Exists(status.ExecutablePath);
+ var which_res = await CoreTools.Which("winget.exe");
+ status.ExecutablePath = which_res.Item2;
+ status.Found = which_res.Item1;
if (!status.Found)
return status;
- var process = new Process()
+ Process process = new()
{
StartInfo = new ProcessStartInfo()
{
@@ -444,16 +431,15 @@ protected override async Task LoadManager()
process.Start();
status.Version = "Naive WinGet CLI Version: " + (await process.StandardOutput.ReadToEndAsync()).Trim();
-
try
{
- await Task.Run(() => WinGetHelper = new NativeWinGetHelper());
+ await Task.Run(() => WinGetHelper.Instance = new NativeWinGetHelper());
status.Version += "\nUsing Native WinGet helper (COM Api)";
}
catch (Exception ex)
{
- AppTools.Log("Cannot create native WinGet instance due to error: " + ex.ToString());
- WinGetHelper = new BundledWinGetHelper();
+ Logger.Error("Cannot create native WinGet instance due to error: " + ex.ToString());
+ WinGetHelper.Instance = new BundledWinGetHelper();
status.Version += "\nUsing bundled WinGet helper (CLI parsing)";
}
@@ -463,100 +449,28 @@ protected override async Task LoadManager()
return status;
}
-
- public override ManagerSource[] GetKnownSources()
- {
- return new ManagerSource[]
- {
- new(this, "winget", new Uri("https://cdn.winget.microsoft.com/cache")),
- new(this, "msstore", new Uri("https://storeedgefd.dsx.mp.microsoft.com/v9.0")),
- };
- }
-
- public override string[] GetAddSourceParameters(ManagerSource source)
- {
- return new string[] { "source", "add", "--name", source.Name, "--arg", source.Url.ToString(), "--accept-source-agreements", "--disable-interactivity" };
- }
-
- public override string[] GetRemoveSourceParameters(ManagerSource source)
- {
- return new string[] { "source", "remove", "--name", source.Name, "--disable-interactivity" };
- }
-
- public override OperationVeredict GetAddSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
- {
- return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
- }
-
- public override OperationVeredict GetRemoveSourceOperationVeredict(ManagerSource source, int ReturnCode, string[] Output)
- {
- return ReturnCode == 0 ? OperationVeredict.Succeeded : OperationVeredict.Failed;
- }
}
- public class LocalPcSource : ManagerSource
+ internal class LocalWingetSource: ManagerSource
{
- public override string IconId { get { return "localpc"; } }
- public LocalPcSource() : base(Winget.Tools.App.Winget, Winget.Tools.Translate("Local PC"), new Uri("https://microsoft.com/local-pc-source"))
- { IsVirtualManager = true; }
- public override string ToString()
- {
- return Winget.Tools.Translate("Local PC");
- }
- }
+ private string name;
+ private string __icon_id;
+ public override string IconId { get { return __icon_id; } }
- public class AndroidSubsystemSource : ManagerSource
- {
- public override string IconId { get { return "android"; } }
- public AndroidSubsystemSource() : base(Winget.Tools.App.Winget, Winget.Tools.Translate("Android Subsystem"), new Uri("https://microsoft.com/local-pc-source"))
- { IsVirtualManager = true; }
- public override string ToString()
+ public LocalWingetSource(WinGet manager, string name, string iconId)
+ : base(manager, name, new Uri("https://microsoft.com/local-pc-source"), isVirtualManager: true)
{
- return Winget.Tools.Translate("Android Subsystem");
+ this.name = name;
+ __icon_id = iconId;
}
- }
- public class SteamSource : ManagerSource
- {
- public override string IconId { get { return "steam"; } }
- public SteamSource() : base(Winget.Tools.App.Winget, "Steam", new Uri("https://microsoft.com/local-pc-source"))
- { IsVirtualManager = true; }
public override string ToString()
{
- return "Steam";
+ return name;
}
}
+}
+
- public class UbisoftConnectSource : ManagerSource
- {
- public override string IconId { get { return "uplay"; } }
- public UbisoftConnectSource() : base(Winget.Tools.App.Winget, "Ubisoft Connect", new Uri("https://microsoft.com/local-pc-source"))
- { IsVirtualManager = true; }
- public override string ToString()
- {
- return "Ubisoft Connect";
- }
- }
- public class GOGSource : ManagerSource
- {
- public override string IconId { get { return "gog"; } }
- public GOGSource() : base(Winget.Tools.App.Winget, "GOG", new Uri("https://microsoft.com/gog-source"))
- { IsVirtualManager = true; }
- public override string ToString()
- {
- return "GOG";
- }
- }
- public class MicrosoftStoreSource : ManagerSource
- {
- public override string IconId { get { return "msstore"; } }
- public MicrosoftStoreSource() : base(Winget.Tools.App.Winget, "Microsoft Store", new Uri("https://microsoft.com/microsoft-store-source"))
- { IsVirtualManager = true; }
- public override string ToString()
- {
- return "Microsoft Store";
- }
- }
-}
diff --git a/src/UniGetUI/PackageEngine/Managers/WinGetHelpers.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs
similarity index 78%
rename from src/UniGetUI/PackageEngine/Managers/WinGetHelpers.cs
rename to src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs
index 668150357..ec0b85e1d 100644
--- a/src/UniGetUI/PackageEngine/Managers/WinGetHelpers.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs
@@ -1,80 +1,103 @@
-using System;
+using Microsoft.Management.Deployment;
+using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
-using System.Text;
+using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UniGetUI.Core;
+using UniGetUI.Core.Data;
using UniGetUI.PackageEngine.Classes;
using WindowsPackageManager.Interop;
+using UniGetUI.Core.Logging;
using Deployment = Microsoft.Management.Deployment;
-using Microsoft.Management.Deployment;
-using System.Diagnostics;
-using UniGetUI.Core.Data;
-using System.IO;
-using System.ComponentModel;
-using YamlDotNet.Core.Tokens;
-using System.Text.RegularExpressions;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.PackageClasses;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
-namespace UniGetUI.PackageEngine.Managers
+namespace UniGetUI.PackageEngine.Managers.WingetManager
{
+ internal static class WinGetHelper
+ {
+ private static IWinGetPackageHelper? __helper;
+ public static IWinGetPackageHelper Instance
+ {
+ get
+ {
+ if (__helper == null)
+ {
+ __helper = new BundledWinGetHelper();
+ }
+ return __helper;
+ }
+
+ set
+ {
+ __helper = value;
+ }
+ }
+ }
+
internal interface IWinGetPackageHelper
{
- public Task FindPackages_UnSafe(Winget ManagerInstance, string query);
- public Task GetSources_UnSafe(Winget ManagerInstance);
- public Task GetPackageVersions_Unsafe(Winget ManagerInstance, Package package);
- public Task GetPackageDetails_UnSafe(Winget ManagerInstance, Package package);
+ public Task FindPackages_UnSafe(WinGet ManagerInstance, string query);
+ public Task GetSources_UnSafe(WinGet ManagerInstance);
+ public Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package);
+ public Task GetPackageDetails_UnSafe(WinGet ManagerInstance, Package package);
}
- internal class NativeWinGetHelper: IWinGetPackageHelper
+ internal class NativeWinGetHelper : IWinGetPackageHelper
{
- WindowsPackageManagerStandardFactory Factory;
- Deployment.PackageManager WinGetManager;
+ public WindowsPackageManagerStandardFactory Factory;
+ public Deployment.PackageManager WinGetManager;
- public NativeWinGetHelper() {
- if (Winget.Tools.IsAdministrator())
- AppTools.Log("[WARNING] Running elevated, WinGet class registration is likely to fail");
+ public NativeWinGetHelper()
+ {
+ if (CoreTools.IsAdministrator())
+ Logger.Info("Running elevated, WinGet class registration is likely to fail");
Factory = new WindowsPackageManagerStandardFactory();
WinGetManager = Factory.CreatePackageManager();
}
- public async Task FindPackages_UnSafe(Winget ManagerInstance, string query)
+ public async Task FindPackages_UnSafe(WinGet ManagerInstance, string query)
{
List Packages = new();
- var PackageFilters = Factory.CreateFindPackagesOptions();
+ FindPackagesOptions PackageFilters = Factory.CreateFindPackagesOptions();
// Name filter
- var FilterName = Factory.CreatePackageMatchFilter();
+ PackageMatchFilter FilterName = Factory.CreatePackageMatchFilter();
FilterName.Field = Deployment.PackageMatchField.Name;
FilterName.Value = query;
FilterName.Option = Deployment.PackageFieldMatchOption.ContainsCaseInsensitive;
PackageFilters.Filters.Add(FilterName);
// Id filter
- var FilterId = Factory.CreatePackageMatchFilter();
+ PackageMatchFilter FilterId = Factory.CreatePackageMatchFilter();
FilterId.Field = Deployment.PackageMatchField.Name;
FilterId.Value = query;
FilterId.Option = Deployment.PackageFieldMatchOption.ContainsCaseInsensitive;
PackageFilters.Filters.Add(FilterId);
// Load catalogs
- var AvailableCatalogs = WinGetManager.GetPackageCatalogs();
+ IReadOnlyList AvailableCatalogs = WinGetManager.GetPackageCatalogs();
Dictionary> FindPackageTasks = new();
// Spawn Tasks to find packages on catalogs
- foreach (var CatalogReference in AvailableCatalogs.ToArray())
+ foreach (PackageCatalogReference CatalogReference in AvailableCatalogs.ToArray())
{
// Connect to catalog
CatalogReference.AcceptSourceAgreements = true;
- var result = await CatalogReference.ConnectAsync();
+ ConnectResult result = await CatalogReference.ConnectAsync();
if (result.Status == Deployment.ConnectResultStatus.Ok)
{
try
{
// Create task and spawn it
- var task = new Task(() => result.PackageCatalog.FindPackages(PackageFilters));
+ Task task = new(() => result.PackageCatalog.FindPackages(PackageFilters));
task.Start();
// Add task to list
@@ -85,28 +108,28 @@ public async Task FindPackages_UnSafe(Winget ManagerInstance, string
}
catch (Exception e)
{
- AppTools.Log("WinGet: Catalog " + CatalogReference.Info.Name + " failed to spawn FindPackages task.");
- AppTools.Log(e);
+ Logger.Error("WinGet: Catalog " + CatalogReference.Info.Name + " failed to spawn FindPackages task.");
+ Logger.Error(e);
}
}
else
{
- AppTools.Log("WinGet: Catalog " + CatalogReference.Info.Name + " failed to connect.");
+ Logger.Error("WinGet: Catalog " + CatalogReference.Info.Name + " failed to connect.");
}
}
// Wait for tasks completion
await Task.WhenAll(FindPackageTasks.Values.ToArray());
- foreach (var CatalogTaskPair in FindPackageTasks)
+ foreach (KeyValuePair> CatalogTaskPair in FindPackageTasks)
{
try
{
// Get the source for the catalog
- ManagerSource source = ManagerInstance.SourceFactory.GetSourceOrDefault(CatalogTaskPair.Key.Info.Name);
+ ManagerSource source = ManagerInstance.GetSourceOrDefault(CatalogTaskPair.Key.Info.Name);
- var FoundPackages = CatalogTaskPair.Value.Result;
- foreach (var package in FoundPackages.Matches.ToArray())
+ FindPackagesResult FoundPackages = CatalogTaskPair.Value.Result;
+ foreach (MatchResult package in FoundPackages.Matches.ToArray())
{
// Create the Package item and add it to the list
Packages.Add(new Package(
@@ -120,72 +143,72 @@ public async Task FindPackages_UnSafe(Winget ManagerInstance, string
}
catch (Exception e)
{
- AppTools.Log("WinGet: Catalog " + CatalogTaskPair.Key.Info.Name + " failed to get available packages.");
- AppTools.Log(e);
+ Logger.Error("WinGet: Catalog " + CatalogTaskPair.Key.Info.Name + " failed to get available packages.");
+ Logger.Error(e);
}
}
return Packages.ToArray();
}
- public async Task GetSources_UnSafe(Winget ManagerInstance)
+ public async Task GetSources_UnSafe(WinGet ManagerInstance)
{
List sources = new();
- foreach (var catalog in await Task.Run(() => WinGetManager.GetPackageCatalogs().ToArray()))
+ foreach (PackageCatalogReference catalog in await Task.Run(() => WinGetManager.GetPackageCatalogs().ToArray()))
try
{
sources.Add(new ManagerSource(ManagerInstance, catalog.Info.Name, new Uri(catalog.Info.Argument), updateDate: catalog.Info.LastUpdateTime.ToString()));
}
catch (Exception e)
{
- AppTools.Log(e);
+ Logger.Error(e);
}
return sources.ToArray();
}
- public async Task GetPackageVersions_Unsafe(Winget ManagerInstance, Package package)
+ public async Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package)
{
// Find the native package for the given Package object
- var Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
+ PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
if (Catalog == null)
{
- AppTools.Log("Failed to get catalog " + package.Source.Name + ". Is the package local?");
+ Logger.Error("Failed to get catalog " + package.Source.Name + ". Is the package local?");
return [];
}
// Connect to catalog
Catalog.AcceptSourceAgreements = true;
- var ConnectResult = await Task.Run(() => Catalog.Connect());
+ ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
if (ConnectResult.Status != Deployment.ConnectResultStatus.Ok)
{
- AppTools.Log("Failed to connect to catalog " + package.Source.Name);
+ Logger.Error("Failed to connect to catalog " + package.Source.Name);
return [];
}
// Match only the exact same Id
- var packageMatchFilter = Factory.CreateFindPackagesOptions();
- var filters = Factory.CreatePackageMatchFilter();
+ FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
+ PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
filters.Field = Deployment.PackageMatchField.Id;
filters.Value = package.Id;
filters.Option = Deployment.PackageFieldMatchOption.Equals;
packageMatchFilter.Filters.Add(filters);
packageMatchFilter.ResultLimit = 1;
- var SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
+ Task SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
if (SearchResult.Result == null || SearchResult.Result.Matches == null || SearchResult.Result.Matches.Count() == 0)
{
- AppTools.Log("WinGet: Failed to find package " + package.Id + " in catalog " + package.Source.Name);
+ Logger.Error("WinGet: Failed to find package " + package.Id + " in catalog " + package.Source.Name);
return [];
}
// Get the Native Package
- var NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
+ CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
return NativePackage.AvailableVersions.Select(x => x.Version).ToArray();
}
- public async Task GetPackageDetails_UnSafe(Winget ManagerInstance, Package package)
+ public async Task GetPackageDetails_UnSafe(WinGet ManagerInstance, Package package)
{
PackageDetails details = new(package);
@@ -199,43 +222,43 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
details.ManifestUrl = new Uri("https://apps.microsoft.com/detail/" + package.Id);
// Find the native package for the given Package object
- var Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
+ PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
if (Catalog == null)
{
- AppTools.Log("Failed to get catalog " + package.Source.Name + ". Is the package local?");
+ Logger.Error("Failed to get catalog " + package.Source.Name + ". Is the package local?");
return details;
}
// Connect to catalog
Catalog.AcceptSourceAgreements = true;
- var ConnectResult = await Task.Run(() => Catalog.Connect());
+ ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
if (ConnectResult.Status != Deployment.ConnectResultStatus.Ok)
{
- AppTools.Log("Failed to connect to catalog " + package.Source.Name);
+ Logger.Error("Failed to connect to catalog " + package.Source.Name);
return details;
}
// Match only the exact same Id
- var packageMatchFilter = Factory.CreateFindPackagesOptions();
- var filters = Factory.CreatePackageMatchFilter();
+ FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
+ PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
filters.Field = Deployment.PackageMatchField.Id;
filters.Value = package.Id;
filters.Option = Deployment.PackageFieldMatchOption.Equals;
packageMatchFilter.Filters.Add(filters);
packageMatchFilter.ResultLimit = 1;
- var SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
+ Task SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
if (SearchResult.Result == null || SearchResult.Result.Matches == null || SearchResult.Result.Matches.Count() == 0)
{
- AppTools.Log("WinGet: Failed to find package " + package.Id + " in catalog " + package.Source.Name);
+ Logger.Error("WinGet: Failed to find package " + package.Id + " in catalog " + package.Source.Name);
return details;
}
// Get the Native Package
- var NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
+ CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
// Extract data from NativeDetails
- var NativeDetails = NativePackage.DefaultInstallVersion.GetCatalogPackageMetadata(Windows.System.UserProfile.GlobalizationPreferences.Languages[0]);
+ CatalogPackageMetadata NativeDetails = NativePackage.DefaultInstallVersion.GetCatalogPackageMetadata(Windows.System.UserProfile.GlobalizationPreferences.Languages[0]);
if (NativeDetails.Author != "")
details.Author = NativeDetails.Author;
@@ -264,7 +287,6 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
if (NativeDetails.Tags != null)
details.Tags = NativeDetails.Tags.ToArray();
- Debug.WriteLine("Starting manual fetch");
// There is no way yet to retrieve installer URLs right now so this part will be console-parsed.
// TODO: Replace this code with native code when available on the COM api
@@ -272,7 +294,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
List output = new();
ProcessStartInfo startInfo = new()
{
- FileName = Path.Join(CoreData.UniGetUIExecutableDirectory, "PackageEngine", "Managers", "winget-cli_x64", "winget.exe"),
+ FileName = Path.Join(CoreData.UniGetUIExecutableDirectory, "winget-cli_x64", "winget.exe"),
Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show --id " + package.Id + " --exact --disable-interactivity --accept-source-agreements --source " + package.Source.Name,
RedirectStandardOutput = true,
RedirectStandardError = true,
@@ -285,7 +307,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
process.Start();
// Retrieve the output
- string _line;
+ string? _line;
while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
if (_line.Trim() != "")
output.Add(_line);
@@ -295,7 +317,6 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
{
try
{
- AppTools.Log(__line);
string line = __line.Trim();
if (line.Contains("Installer SHA256:"))
details.InstallerHash = line.Split(":")[1].Trim();
@@ -303,7 +324,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
else if (line.Contains("Installer Url:"))
{
details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
- details.InstallerSize = await Winget.Tools.GetFileSizeAsync(details.InstallerUrl);
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
}
else if (line.Contains("Release Date:"))
details.UpdateDate = line.Split(":")[1].Trim();
@@ -313,8 +334,8 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
}
catch (Exception e)
{
- AppTools.Log("Error occurred while parsing line value=\"" + __line + "\"");
- AppTools.Log(e.Message);
+ Logger.Warn("Error occurred while parsing line value=\"" + __line + "\"");
+ Logger.Warn(e.Message);
}
}
@@ -327,15 +348,16 @@ internal class BundledWinGetHelper : IWinGetPackageHelper
{
private string WinGetBundledPath;
- public BundledWinGetHelper() {
+ public BundledWinGetHelper()
+ {
WinGetBundledPath = Path.Join(CoreData.UniGetUIExecutableDirectory, "PackageEngine", "Managers", "winget-cli_x64", "winget.exe");
}
- public async Task FindPackages_UnSafe(Winget ManagerInstance, string query)
+ public async Task FindPackages_UnSafe(WinGet ManagerInstance, string query)
{
- var Packages = new List();
+ List Packages = new();
- Process p = new Process();
+ Process p = new();
p.StartInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
@@ -377,11 +399,10 @@ function Print-WinGetPackage {
");
- string line;
+ string? line;
string output = "";
while ((line = await p.StandardOutput.ReadLineAsync()) != null)
{
- Debug.WriteLine(line);
output += line + "\n";
if (!line.StartsWith("#"))
continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
@@ -390,20 +411,20 @@ function Print-WinGetPackage {
if (elements.Length < 4)
continue;
- ManagerSource source = ManagerInstance.SourceFactory.GetSourceOrDefault(elements[3]);
+ ManagerSource source = ManagerInstance.GetSourceOrDefault(elements[3]);
Packages.Add(new Package(elements[0][1..], elements[1], elements[2], source, ManagerInstance));
}
output += await p.StandardError.ReadToEndAsync();
- AppTools.LogManagerOperation(ManagerInstance, p, output);
+ // AppTools.LogManagerOperation(ManagerInstance, p, output);
await p.WaitForExitAsync();
return Packages.ToArray();
}
- public async Task GetPackageDetails_UnSafe(Winget ManagerInstance, Package package)
+ public async Task GetPackageDetails_UnSafe(WinGet ManagerInstance, Package package)
{
PackageDetails details = new(package);
@@ -442,13 +463,12 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
process.StartInfo = startInfo;
process.Start();
- string _line;
+ string? _line;
while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
if (_line.Trim() != "")
{
output.Add(_line);
- AppTools.Log(_line);
- if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see logs for more details."))
+ if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see Logger.Logs for more details."))
{
LocaleFound = false;
break;
@@ -459,7 +479,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
if (!LocaleFound)
{
output.Clear();
- AppTools.Log("Winget could not found culture data for package Id=" + package.Id + " and Culture=" + System.Globalization.CultureInfo.CurrentCulture.ToString() + ". Trying to get data for en-US");
+ Logger.Info("Winget could not found culture data for package Id=" + package.Id + " and Culture=" + System.Globalization.CultureInfo.CurrentCulture.ToString() + ". Trying to get data for en-US");
process = new Process();
LocaleFound = true;
startInfo = new()
@@ -480,8 +500,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
if (_line.Trim() != "")
{
output.Add(_line);
- AppTools.Log(_line);
- if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see logs for more details."))
+ if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see Logger.Logs for more details."))
{
LocaleFound = false;
break;
@@ -493,7 +512,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
if (!LocaleFound)
{
output.Clear();
- AppTools.Log("Winget could not found culture data for package Id=" + package.Id + " and Culture=en-US. Loading default");
+ Logger.Info("Winget could not found culture data for package Id=" + package.Id + " and Culture=en-US. Loading default");
LocaleFound = true;
process = new Process();
startInfo = new()
@@ -514,7 +533,6 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
if (_line.Trim() != "")
{
output.Add(_line);
- AppTools.Log(_line);
}
}
@@ -568,7 +586,7 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
else if (line.Contains("Installer Url:"))
{
details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
- details.InstallerSize = await Winget.Tools.GetFileSizeAsync(details.InstallerUrl);
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
}
else if (line.Contains("Release Date:"))
details.UpdateDate = line.Split(":")[1].Trim();
@@ -597,16 +615,16 @@ public async Task GetPackageDetails_UnSafe(Winget ManagerInstanc
}
catch (Exception e)
{
- AppTools.Log("Error occurred while parsing line value=\"" + _line + "\"");
- AppTools.Log(e.Message);
+ Logger.Warn("Error occurred while parsing line value=\"" + _line + "\"");
+ Logger.Warn(e.Message);
}
}
return details;
}
- public async Task GetPackageVersions_Unsafe(Winget ManagerInstance, Package package)
- {
+ public async Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package)
+ {
Process p = new()
{
StartInfo = new ProcessStartInfo()
@@ -624,7 +642,7 @@ public async Task GetPackageVersions_Unsafe(Winget ManagerInstance, Pa
p.Start();
- string line;
+ string? line;
List