Compare commits

...

86 Commits

Author SHA1 Message Date
JFronny
2fe4fa4592 Implement queue management UI and app upload for eto 2021-02-14 16:29:09 +01:00
JFronny
531a1c1e34 Implement app controls and filters in UpToolEto 2021-02-13 14:36:12 +01:00
JFronny
5814336814 Fix download dialog, fix threaded invokes of Eto UTLibFunctions, use UTLibFunctions instead of console logging and direct msgbox calls 2021-02-13 13:05:38 +01:00
JFronny
6af8eba6c6 Split UpToolLib into v1 (basically an interface over XElements with rudementary parsing) and v2 (more object-oriented, less hacky API, will allow easier migration to a more suited information backend) and start work on a new eto-based UI (not functional currently) 2021-02-08 19:00:52 +01:00
J. Fronny
ba106c1783 Path 2021-02-04 14:41:34 +00:00
J. Fronny
3d710854b3 CI: no longer try to add /runtimes 2021-02-03 21:55:05 +00:00
JFronny
f9b56c91af Upgrade System.Commandline 2021-02-03 22:47:53 +01:00
JFronny
3ddc958e0b Switch to CC-Functions.Core 2021-02-03 22:42:22 +01:00
J. Fronny
536b549114 Specify dotnet path to dotnet-install output 2021-02-03 21:31:56 +00:00
J. Fronny
94c0273304 Readd dotnet download because maybe that fixes it 2021-02-03 21:19:07 +00:00
JFronny
e92a074544 net5.0 attempt 2 2021-02-03 22:14:47 +01:00
J. Fronny
9b1935e7a7 Hopefully fix 2021-02-03 20:55:22 +00:00
J. Fronny
3bd245b277 [attempt] install .net using dotnet-install 2020-12-13 19:29:59 +00:00
JFronny
9d42aefe24 .Net 5 - This is to test if gitlab CI has this available now 2020-12-13 21:21:46 +01:00
JFronny
ef5947f54c Remove #if (compile-time) conditions. This should make testing scenarios slightly more accurate. This does NOT mean that things like self-updating will suddenly work, just that it won't be ignored when compiling for debug 2020-09-10 20:16:19 +02:00
JFronny
f38a0e054d Remove repo link unshortening, noticably reducing load time (way less requests have to be made) 2020-09-10 20:05:48 +02:00
J. Fronny
5e31ff3b45 Merge branch 'renovate/system.commandline-2.x' into 'master'
Update dependency System.CommandLine to v2.0.0-beta1.20427.1

See merge request JFronny/UpTool2!20
2020-09-07 09:44:44 +00:00
Renovate Bot
c602b59f21
Update dependency System.CommandLine to v2.0.0-beta1.20427.1 2020-09-07 06:52:50 +00:00
JFronny
042b126634 Add support for starting apps with arguments and custom file names to UpToolLib and UpToolCLI (the UpToolCLI impl is limited due to System.Commandline: values starting with dashes need to share a string with the option switch) 2020-08-31 22:11:40 +02:00
JFronny
0976297348 Fix CLI Installer 2020-08-31 21:14:27 +02:00
JFronny
ddbfb39e87 Correct the type for --waitForExit in Start (UpToolCLI) 2020-08-31 21:12:00 +02:00
JFronny
14b2643cbf Fix bug where Basic was used before being set
- Set Basic before FixXml (was accesed before being set)
- Move Basic to Program.cs
2020-08-31 20:40:58 +02:00
JFronny
0eccafa9ea Various CLI improvements
- Show dialog before adding default repo
- Prevent edge-case where --basic is used later in a CLI command
- Fix RemoveRepo in basic mode
- Use default instead of true in basic YesNoDialog
2020-08-31 20:22:37 +02:00
JFronny
b2d353b0bb --basic option to disable advanced output (UpToolCLI) 2020-08-31 19:56:10 +02:00
JFronny
c5de2e6886 Better logging for debugging, partially reworked interface for UpToolCLI 2020-08-31 18:58:15 +02:00
J. Fronny
73669e16ea Merge branch 'renovate/sixlabors.imagesharp-1.x' into 'master'
Update dependency SixLabors.ImageSharp to v1.0.1

See merge request JFronny/UpTool2!19
2020-08-22 16:31:57 +00:00
Renovate Bot
ffa645c991
Update dependency SixLabors.ImageSharp to v1.0.1 2020-08-21 16:17:53 +00:00
J. Fronny
e642161206 Merge branch 'renovate/sixlabors.imagesharp-1.x' into 'master'
Update dependency SixLabors.ImageSharp to v1.0.0

See merge request JFronny/UpTool2!18
2020-08-05 08:07:27 +00:00
Renovate Bot
568d17e3fa
Update dependency SixLabors.ImageSharp to v1.0.0 2020-08-04 22:42:51 +00:00
J. Fronny
08dfef1498 Merge branch 'renovate/system.commandline-2.x' into 'master'
Update dependency System.CommandLine to v2.0.0-beta1.20371.2

See merge request JFronny/UpTool2!17
2020-07-23 04:49:24 +00:00
Renovate Bot
2670a04542
Update dependency System.CommandLine to v2.0.0-beta1.20371.2 2020-07-23 02:40:03 +00:00
JFronny
e36005558d Prevent a bug with mainBin being a global path instead of local 2020-07-16 17:12:31 +02:00
J. Fronny
da1dbca8f6 Add LICENSE 2020-06-27 16:22:04 +00:00
J. Fronny
2fd34f5576 Merge branch 'renovate/system.commandline-2.x' into 'master'
Update dependency System.CommandLine to v2.0.0-beta1.20303.1

See merge request JFronny/UpTool2!16
2020-06-23 12:14:53 +00:00
J. Fronny
bc7875c512 Update renovate.json 2020-06-23 12:13:46 +00:00
Renovate Bot
2dea7f8138
Update dependency System.CommandLine to v2.0.0-beta1.20303.1 2020-06-23 12:07:00 +00:00
J. Fronny
07ef29d807 Merge branch 'renovate/configure' into 'master'
Configure Renovate

See merge request JFronny/UpTool2!15
2020-06-23 12:06:41 +00:00
Renovate Bot
c59bb90032
Add renovate.json 2020-06-23 09:19:30 +00:00
JFronny
b3bf4f7026 Kleen 2020-06-21 16:46:34 +02:00
J. Fronny
0f48d64121 Generate Installer-gui Zip for usage in website 2020-06-21 13:22:06 +00:00
J. Fronny
984044f1b0 GitHub to GitLab in Installer 2020-06-21 06:51:16 +00:00
J. Fronny
a8479cd577 Update .gitlab-ci.yml 2020-06-21 06:21:12 +00:00
J. Fronny
12b946fdf0 Update README.md, UpToolLib/Tool/XmlTool.cs, UpTool2/Program.cs files 2020-06-21 06:05:35 +00:00
J. Fronny
651992285c Update .gitlab-ci.yml 2020-06-20 11:16:00 +00:00
J. Fronny
4afa77abca Update .gitlab-ci.yml 2020-06-20 11:09:59 +00:00
J. Fronny
bc418aaef6 Update .gitlab-ci.yml 2020-06-20 11:07:38 +00:00
J. Fronny
3291f7c460 Update .gitlab-ci.yml 2020-06-20 10:47:35 +00:00
J. Fronny
50c422b701 Add .gitlab-ci.yml 2020-06-20 10:01:52 +00:00
J. Fronny
24529a59e7 Update README.md 2020-06-20 09:45:38 +00:00
dependabot-preview[bot]
c8eaeebbde Bump CC-Functions.Misc from 1.1.7450.31626 to 1.1.7468.32091
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7450.31626 to 1.1.7468.32091.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7450.31626...1.1.7468.32091)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 06:53:52 +02:00
dependabot-preview[bot]
df8099e3d0 Bump SixLabors.ImageSharp from 1.0.0-rc0001 to 1.0.0-rc0002
Bumps [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 1.0.0-rc0001 to 1.0.0-rc0002.
- [Release notes](https://github.com/SixLabors/ImageSharp/releases)
- [Commits](https://github.com/SixLabors/ImageSharp/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-09 11:38:55 +02:00
J. Fronny
5364fa250c
Only add needed files to Release.zip 2020-06-08 12:07:50 +02:00
dependabot-preview[bot]
90a3aacce0 Bump CC-Functions.Misc from 1.1.7448.24408 to 1.1.7450.31626
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7448.24408 to 1.1.7450.31626.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7448.24408...1.1.7450.31626)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-26 08:41:54 +02:00
dependabot-preview[bot]
55cf52df26 Bump CC-Functions.Misc from 1.1.7409.23118 to 1.1.7448.24408
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7409.23118 to 1.1.7448.24408.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7409.23118...1.1.7448.24408)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-24 14:18:39 +02:00
JFronny
802340e418 Hide CLI in GUI-Installer (no longer used) 2020-05-16 18:29:50 +02:00
JFronny
a42b9b624d Fix release builds, clean 2020-05-16 18:19:43 +02:00
JFronny
0ac90790b8 Bugfix, better CLI 2020-05-16 18:04:24 +02:00
dependabot-preview[bot]
8d3bc22af7 Bump SixLabors.ImageSharp from 1.0.0-beta0007 to 1.0.0-rc0001
Bumps [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 1.0.0-beta0007 to 1.0.0-rc0001.
- [Release notes](https://github.com/SixLabors/ImageSharp/releases)
- [Commits](https://github.com/SixLabors/ImageSharp/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-01 14:46:29 +02:00
dependabot-preview[bot]
f58334c8a4 Bump CC-Functions.Misc from 1.1.7399.26972 to 1.1.7409.23118
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7399.26972 to 1.1.7409.23118.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7399.26972...1.1.7409.23118)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-17 10:27:48 +02:00
CreepyCrafter24
eca073fab3 Separate installer CLI 2020-04-09 13:58:06 +02:00
CreepyCrafter24
c186afa8b4 Stage changes 2020-04-08 20:57:50 +02:00
CreepyCrafter24
daca8d5b9a Add install option for app-updates 2020-04-08 19:22:38 +02:00
CreepyCrafter24
a76a09051b Add installer-option for PATH and self-updating on logon 2020-04-08 19:16:14 +02:00
CreepyCrafter24
0fc0b9eead Class containing some duplicate code for Update Checks 2020-04-08 18:41:57 +02:00
CreepyCrafter24
a64d3ab4bc Sleep before install 2020-04-08 18:15:21 +02:00
CreepyCrafter24
b395ab2d81 Fix Version 2020-04-08 18:11:30 +02:00
CreepyCrafter24
2ca1bd5408 Self-update using installer 2020-04-08 18:03:50 +02:00
CreepyCrafter24
29e35dbec0 CLI-Output for Installer 2020-04-08 17:56:54 +02:00
CreepyCrafter24
1ad1d0f8f8 Main.yml: reference installer in main.yml 2020-04-08 17:14:51 +02:00
CreepyCrafter24
5619de376a Init repos from installer 2020-04-08 17:08:51 +02:00
CreepyCrafter24
21dc22965d Create "Platform"-Property for Repos 2020-04-08 16:32:16 +02:00
CreepyCrafter24
5cae428440 Partially untested code for Linux support without Wine 2020-04-08 16:05:09 +02:00
J. Fronny
f931169ebe
fix typo 2020-04-07 21:37:08 +02:00
CreepyCrafter24
1d690c738d Add update count to UpTool2-update 2020-04-07 21:26:25 +02:00
dependabot-preview[bot]
ca89e1c94d Bump CC-Functions.Misc from 1.1.7397.24614 to 1.1.7399.26972
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7397.24614 to 1.1.7399.26972.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7397.24614...1.1.7399.26972)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-06 18:46:40 +02:00
dependabot-preview[bot]
ac5fc1cd5e Bump CC-Functions.Misc from 1.1.7396.23808 to 1.1.7397.24614
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7396.23808 to 1.1.7397.24614.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7396.23808...1.1.7397.24614)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-04 15:46:20 +02:00
J. Fronny
ff2e7e63de Attempt in GitHub online, will prob. not work 2020-04-02 22:36:11 +02:00
dependabot-preview[bot]
f6acde934e Bump CC-Functions.Misc from 1.1.7388.28729 to 1.1.7396.23808
Bumps [CC-Functions.Misc](https://github.com/JFronny/CC-Functions) from 1.1.7388.28729 to 1.1.7396.23808.
- [Release notes](https://github.com/JFronny/CC-Functions/releases)
- [Commits](https://github.com/JFronny/CC-Functions/compare/1.1.7388.28729...1.1.7396.23808)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-02 15:44:11 +02:00
J. Fronny
b6d2c18b31
Maybe fix 2020-04-02 15:38:51 +02:00
CreepyCrafter24
86009c2d88 Fix major issue 2020-03-24 23:14:40 +01:00
CreepyCrafter24
18c8419495 Random stuff 2020-03-24 22:43:57 +01:00
J. Fronny
4b7980d138
Also add UpToolCLI artifacts to release.zip 2020-03-24 22:03:59 +01:00
CreepyCrafter24
3210028469 Fix a strange edge-case 2020-03-24 21:57:52 +01:00
CreepyCrafter24
101ea5843a Fix some stuff 2020-03-24 21:27:41 +01:00
CreepyCrafter24
d7306150e8 Fix Usings 2020-03-24 20:54:52 +01:00
CreepyCrafter24
023f452b26 Add CLI Tool 2020-03-24 20:53:23 +01:00
97 changed files with 4140 additions and 1037 deletions

View File

@ -1,129 +0,0 @@
name: CD
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Build
id: base_init
run: |
cd $Env:GITHUB_WORKSPACE
dotnet build --verbosity:m -p:Configuration=Release
cp ".\UpTool build tool\bin\Release\netcoreapp3.1\package.zip" $Env:GITHUB_WORKSPACE\Tools.zip
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpTool2\bin\Release\netcoreapp3.1\*
$asmver = $([Reflection.Assembly]::Loadfile($(pwd).Path + "\\UpTool2\\bin\\Release\\netcoreapp3.1\\UpTool2.dll").GetName().version.ToString())
$pkgtoolver = $([Reflection.Assembly]::Loadfile($(pwd).Path + "\\UpTool build tool\\bin\\Release\\netcoreapp3.1\\pkgtool.dll").GetName().version.ToString())
echo "::set-output name=vers::$asmver"
echo "::set-output name=pkgvers::$pkgtoolver"
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.base_init.outputs.vers }}
release_name: Release ${{ steps.base_init.outputs.vers }}
draft: false
prerelease: false
- name: Upload Release Asset
id: upload_release_asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Release.zip
asset_name: Release.zip
asset_content_type: application/zip
- name: Upload Tool Asset
id: upload_tool_asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Tools.zip
asset_name: Tools.zip
asset_content_type: application/zip
- name: Create XML
run: |
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = "UpTool2 package tools"
$app.appendChild($xml.CreateElement("Description")).InnerText = "Tools for automating package creation"
$app.appendChild($xml.CreateElement("Version")).InnerText = "${{ steps.base_init.outputs.pkgvers }}"
$app.appendChild($xml.CreateElement("ID")).InnerText = "0e35d154-d0d3-45e0-b080-62f521263a44"
$app.appendChild($xml.CreateElement("File")).InnerText = "${{ steps.upload_tool_asset.outputs.browser_download_url }}"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash $Env:GITHUB_WORKSPACE\Tools.zip).Hash
echo NULL > tools.xml
$xml.save($(gi .\tools.xml).Fullname)
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("meta")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Version")).InnerText = "${{ steps.base_init.outputs.vers }}"
$app.appendChild($xml.CreateElement("File")).InnerText = "${{ steps.upload_release_asset.outputs.browser_download_url }}"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash $Env:GITHUB_WORKSPACE\Release.zip).Hash
echo NULL > meta.xml
$xml.save($(gi .\meta.xml).Fullname)
- name: Upload Meta XML
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./meta.xml
asset_name: meta.xml
asset_content_type: text/xml
- name: Upload Tool XML
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./tools.xml
asset_name: tools.xml
asset_content_type: text/xml
- name: Build non-generic installers
run: |
cd $Env:GITHUB_WORKSPACE\Installer
& "C:\Program Files\7-Zip\7z" a ..\Installer-generic.zip .\bin\Release\netcoreapp3.1\Installer.exe
& "C:\Program Files\7-Zip\7z" a ..\Installer-generic.zip .\bin\Release\netcoreapp3.1\Installer.dll
& "C:\Program Files\7-Zip\7z" a ..\Installer-generic.zip .\bin\Release\netcoreapp3.1\Installer.runtimeconfig.json
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
dotnet publish -r win-x86 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
cp .\bin\Release\netcoreapp3.1\win-x64\publish\Installer.exe ..\Installer-x64.exe
cp .\bin\Release\netcoreapp3.1\win-x86\publish\Installer.exe ..\Installer-x86.exe
cd $Env:GITHUB_WORKSPACE
- name: Upload x86 Installer
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Installer-x86.exe
asset_name: Installer-x86.exe
asset_content_type: application/vnd.microsoft.portable-executable
- name: Upload x64 Installer
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Installer-x64.exe
asset_name: Installer-x64.exe
asset_content_type: application/vnd.microsoft.portable-executable
- name: Upload generic Installer
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Installer-generic.zip
asset_name: Installer-generic.zip
asset_content_type: application/zip

72
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,72 @@
.shared_windows_runners:
tags:
- windows
uptool:
extends:
- .shared_windows_runners
stage: deploy
script: |
Invoke-WebRequest -Uri https://dotnet.microsoft.com/download/dotnet-core/scripts/v1/dotnet-install.ps1 -OutFile dotnet-install.ps1
Set-ExecutionPolicy Unrestricted -Scope Process
.\dotnet-install.ps1 -Channel 5.0
$env:Path = "C:\Users\gitlab_runner\AppData\Local\Microsoft\dotnet;" + $env:Path + ";C:\Users\gitlab_runner\AppData\Local\Microsoft\dotnet"
dotnet build --verbosity:m -p:Configuration=Release
cp ".\UpTool build tool\bin\Release\net5.0\package.zip" .\Tools.zip
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpTool2\bin\Release\net5.0-windows\UpTool2.exe
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpTool2\bin\Release\net5.0-windows\*.dll
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpTool2\bin\Release\net5.0-windows\UpTool2.runtimeconfig.json
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpToolCLI\bin\Release\net5.0\uptool.exe
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpToolCLI\bin\Release\net5.0\*.dll
& "C:\Program Files\7-Zip\7z" a .\Release.zip .\UpToolCLI\bin\Release\net5.0\uptool.runtimeconfig.json
$asmver = $([Reflection.Assembly]::Loadfile($(pwd).Path + "\\UpTool2\\bin\\Release\\net5.0-windows\\UpTool2.dll").GetName().version.ToString())
$pkgtoolver = $([Reflection.Assembly]::Loadfile($(pwd).Path + "\\UpTool build tool\\bin\\Release\\net5.0\\pkgtool.dll").GetName().version.ToString())
& "C:\Program Files\7-Zip\7z" a .\Installer-generic.zip .\InstallerCLI\bin\Release\net5.0\Installer.exe
& "C:\Program Files\7-Zip\7z" a .\Installer-generic.zip .\InstallerCLI\bin\Release\net5.0\*.dll
& "C:\Program Files\7-Zip\7z" a .\Installer-generic.zip .\InstallerCLI\bin\Release\net5.0\Installer.runtimeconfig.json
& "C:\Program Files\7-Zip\7z" a .\Installer-generic.zip .\InstallerCLI\Info.txt
& "C:\Program Files\7-Zip\7z" a .\Installer-gui.zip .\Installer\bin\Release\net5.0-windows\Installer.exe
& "C:\Program Files\7-Zip\7z" a .\Installer-gui.zip .\Installer\bin\Release\net5.0-windows\*.dll
& "C:\Program Files\7-Zip\7z" a .\Installer-gui.zip .\Installer\bin\Release\net5.0-windows\Installer.runtimeconfig.json
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = "UpTool2 package tools"
$app.appendChild($xml.CreateElement("Description")).InnerText = "Tools for automating package creation"
$app.appendChild($xml.CreateElement("Version")).InnerText = $pkgtoolver
$app.appendChild($xml.CreateElement("ID")).InnerText = "0e35d154-d0d3-45e0-b080-62f521263a44"
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/Tools.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\Tools.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = "pkgtool.exe"
$app.appendChild($xml.CreateElement("Icon")).InnerText = "https://gitlab.com/JFronny/UpTool2/-/raw/master/UpTool2.ico"
echo NULL > tools.xml
$xml.save($(gi .\tools.xml).Fullname)
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("meta")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Version")).InnerText = $asmver
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/Release.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\Release.zip).Hash
$app.appendChild($xml.CreateElement("Installer")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/Installer-generic.zip"
$app.appendChild($xml.CreateElement("InstallerHash")).InnerText = $(Get-FileHash .\Installer-generic.zip).Hash
$app.appendChild($xml.CreateElement("InstallerGui")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/Installer-gui.zip"
$app.appendChild($xml.CreateElement("InstallerGuiHash")).InnerText = $(Get-FileHash .\Installer-gui.zip).Hash
echo NULL > meta.xml
$xml.save($(gi .\meta.xml).Fullname)
#cd Installer
#dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
#dotnet publish -r win-x86 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
#cp .\bin\Release\net5.0-windows\win-x64\publish\Installer.exe ..\Installer-x64.exe
#cp .\bin\Release\net5.0-windows\win-x86\publish\Installer.exe ..\Installer-x86.exe
#cd ..
#Installer-x64 and Installer-x86 were also originally artifacts but there doesn't seem to be a x86-64 windows runner
artifacts:
paths:
- Release.zip
- Tools.zip
- Installer-generic.zip
- Installer-gui.zip
- meta.xml
- tools.xml
only:
- master

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="true" />
<option name="show" value="PROJECT_FILES" />
</component>
<component name="ProjectNotificationSettings">
<option name="askShowProject" value="false" />

View File

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.UpTool2/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.UpTool2/riderModule.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.UpTool2/.idea/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.UpTool2/.idea/riderModule.iml" />
</modules>
</component>
</project>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="1" />
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

39
CLI.md Normal file
View File

@ -0,0 +1,39 @@
# CLI
### Package Management
Installing a package (set \<package> to a file for local): uptool install \<package>
Upgrading a package: uptool upgrade \<package>
Reinstalling a package: uptool reinstall \<package>
Removing a package: uptool remove \<package>
Removing a package and all its configuration and data files: uptool purge \<package>
Upgrade all packages: uptool dist-upgrade
### Cache Management
List installed packages: uptool list
Search for a package: uptool search \<text>
Show package info: uptool show \<package>
Updating the cache: uptool update
### Repos Management
Add a repository: uptool add-repo \<name> \<link>
Remove a repository: uptool remove-repo \<name>
List repositories: uptool list-repo
### Other
Upgrading UpToolCLI: uptool upgrade-self
Start an app: uptool start \<package>

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>..\UpTool2.ico</ApplicationIcon>
</PropertyGroup>
@ -11,4 +11,8 @@
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

View File

@ -17,69 +17,56 @@
{
components.Dispose();
}
_lib.Dispose();
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallerForm));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Installer.InstallerForm));
this.install = new System.Windows.Forms.Button();
this.installLabel = new System.Windows.Forms.Label();
this.progress = new System.Windows.Forms.ProgressBar();
this.processLabel = new System.Windows.Forms.Label();
this.log = new System.Windows.Forms.Button();
this.startupBox = new System.Windows.Forms.CheckBox();
this.pathBox = new System.Windows.Forms.CheckBox();
this.updateAppsBox = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// install
//
this.install.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.install.Location = new System.Drawing.Point(12, 92);
this.install.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.install.Location = new System.Drawing.Point(12, 116);
this.install.Name = "install";
this.install.Size = new System.Drawing.Size(539, 27);
this.install.TabIndex = 0;
this.install.Text = "Install";
this.install.UseVisualStyleBackColor = true;
this.install.Click += new System.EventHandler(this.install_Click);
//
// installLabel
//
this.installLabel.AutoSize = true;
this.installLabel.Location = new System.Drawing.Point(12, 9);
this.installLabel.Name = "installLabel";
this.installLabel.Size = new System.Drawing.Size(550, 75);
this.installLabel.TabIndex = 1;
this.installLabel.Text = resources.GetString("installLabel.Text");
//
// progress
//
this.progress.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.progress.Location = new System.Drawing.Point(12, 92);
this.progress.Maximum = 6;
this.progress.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.progress.Location = new System.Drawing.Point(12, 116);
this.progress.Maximum = 8;
this.progress.Name = "progress";
this.progress.Size = new System.Drawing.Size(539, 27);
this.progress.TabIndex = 2;
this.progress.Visible = false;
//
// processLabel
//
this.processLabel.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.processLabel.ForeColor = System.Drawing.SystemColors.ControlText;
this.processLabel.Location = new System.Drawing.Point(422, 70);
this.processLabel.Location = new System.Drawing.Point(386, 91);
this.processLabel.Name = "processLabel";
this.processLabel.Size = new System.Drawing.Size(129, 19);
this.processLabel.Size = new System.Drawing.Size(165, 22);
this.processLabel.TabIndex = 3;
this.processLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// log
//
this.log.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.log.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.log.Location = new System.Drawing.Point(524, 3);
this.log.Name = "log";
this.log.Size = new System.Drawing.Size(36, 23);
@ -88,34 +75,60 @@
this.log.UseVisualStyleBackColor = true;
this.log.Visible = false;
this.log.Click += new System.EventHandler(this.log_Click);
//
// InstallerForm
//
this.startupBox.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.startupBox.AutoSize = true;
this.startupBox.Enabled = false;
this.startupBox.Location = new System.Drawing.Point(130, 91);
this.startupBox.Name = "startupBox";
this.startupBox.Size = new System.Drawing.Size(122, 19);
this.startupBox.TabIndex = 5;
this.startupBox.Text = "Update on Startup";
this.startupBox.CheckedChanged += new System.EventHandler(this.startupBox_CheckedChanged);
this.pathBox.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.pathBox.AutoSize = true;
this.pathBox.Location = new System.Drawing.Point(12, 91);
this.pathBox.Name = "pathBox";
this.pathBox.Size = new System.Drawing.Size(112, 19);
this.pathBox.TabIndex = 6;
this.pathBox.Text = "Register in PATH";
this.pathBox.CheckedChanged += new System.EventHandler(this.pathBox_CheckedChanged);
this.updateAppsBox.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.updateAppsBox.AutoSize = true;
this.updateAppsBox.Enabled = false;
this.updateAppsBox.Location = new System.Drawing.Point(258, 91);
this.updateAppsBox.Name = "updateAppsBox";
this.updateAppsBox.Size = new System.Drawing.Size(94, 19);
this.updateAppsBox.TabIndex = 5;
this.updateAppsBox.Text = "Update Apps";
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(563, 132);
this.ClientSize = new System.Drawing.Size(563, 156);
this.Controls.Add(this.updateAppsBox);
this.Controls.Add(this.log);
this.Controls.Add(this.processLabel);
this.Controls.Add(this.progress);
this.Controls.Add(this.installLabel);
this.Controls.Add(this.install);
this.Controls.Add(this.startupBox);
this.Controls.Add(this.pathBox);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
this.Name = "InstallerForm";
this.ShowIcon = false;
this.Text = "UpTool2 Installer";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button install;
private System.Windows.Forms.Label installLabel;
private System.Windows.Forms.ProgressBar progress;
private System.Windows.Forms.Label processLabel;
private System.Windows.Forms.Button log;
private System.Windows.Forms.CheckBox pathBox;
private System.Windows.Forms.Label processLabel;
private System.Windows.Forms.ProgressBar progress;
private System.Windows.Forms.CheckBox startupBox;
private System.Windows.Forms.CheckBox updateAppsBox;
#endregion
}
}

View File

@ -1,25 +1,40 @@
using System;
using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Win32;
using UpToolLib;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace Installer
{
public partial class InstallerForm : Form
{
private string Log = "";
private const string AppName = "UpTool2";
private readonly RegistryKey _rkApp;
private string _log = "";
private UpToolLibMain _lib;
public InstallerForm()
{
_lib = new UpToolLibMain(new UtLibFunctionsGui(Log));
InitializeComponent();
Step(0, "Initialized");
Log.TrimStart(Environment.NewLine.ToCharArray());
_log = _log.TrimStart(Environment.NewLine.ToCharArray());
_rkApp = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
pathBox.Checked = !File.Exists(_lib.V1.PathTool.InfoXml) ||
Path.Content.Contains(Path.GetName(_lib.V1.PathTool.GetRelative("Install")));
startupBox.Checked = pathBox.Checked && _rkApp.GetValue(AppName) != null;
updateAppsBox.Checked = pathBox.Checked && startupBox.Checked &&
(string) _rkApp.GetValue(AppName) == "uptool dist-upgrade";
}
private void install_Click(object sender, EventArgs e)
@ -28,33 +43,50 @@ namespace Installer
try
{
progress.Visible = true;
WebClient client = new WebClient();
WebClient client = new();
Step(1, "Downloading metadata");
XElement meta = XDocument.Load("https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml")
XElement meta = XDocument
.Load("https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/meta.xml?job=uptool")
.Element("meta");
Step(2, "Downloading binary");
byte[] dl = client.DownloadData(meta.Element("File").Value);
Step(3, "Verifying integrity");
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
using (SHA256CryptoServiceProvider sha256 = new())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty).ToUpper();
if (pkgHash != meta.Element("Hash").Value.ToUpper())
throw new Exception(
$"The hash is not equal to the one stored in the repo:\r\nPackage: {pkgHash}\r\nOnline: {meta.Element("Hash").Value.ToUpper()}");
$@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {meta.Element("Hash").Value.ToUpper()}");
}
Step(4, "Extracting");
if (Directory.Exists(PathTool.GetRelative("Install")))
Directory.Delete(PathTool.GetRelative("Install"), true);
Directory.CreateDirectory(PathTool.GetRelative("Install"));
using (MemoryStream ms = new MemoryStream(dl))
if (Directory.Exists(_lib.V1.PathTool.GetRelative("Install")))
Directory.Delete(_lib.V1.PathTool.GetRelative("Install"), true);
Directory.CreateDirectory(_lib.V1.PathTool.GetRelative("Install"));
using (MemoryStream ms = new(dl))
{
using ZipArchive ar = new ZipArchive(ms);
ar.ExtractToDirectory(PathTool.GetRelative("Install"), true);
using ZipArchive ar = new(ms);
ar.ExtractToDirectory(_lib.V1.PathTool.GetRelative("Install"), true);
}
Step(5, "Creating shortcut");
Shortcut.Make(PathTool.GetRelative("Install", "UpTool2.exe"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "UpTool2.lnk"));
Step(6, "Done!");
Shortcut.Make(_lib.V1.PathTool.GetRelative("Install", "UpTool2.exe"),
System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs),
"UpTool2.lnk"));
Step(6, "Preparing Repos");
_lib.V1.XmlTool.FixXml();
_lib.V2.RepoManagement.FetchRepos();
if (pathBox.Checked)
{
Step(7, startupBox.Checked ? "Creating PATH & Autostart entry" : "Creating PATH entry");
if (!Path.Content.Contains(Path.GetName(_lib.V1.PathTool.GetRelative("Install"))))
Path.Append(_lib.V1.PathTool.GetRelative("Install"));
if (startupBox.Checked)
_rkApp.SetValue(AppName, updateAppsBox.Checked ? "uptool dist-upgrade" : "uptool upgrade-self");
else if (_rkApp.GetValue(AppName) != null)
_rkApp.DeleteValue(AppName, false);
}
Step(8, "Done!");
}
catch (Exception ex)
{
@ -81,9 +113,30 @@ namespace Installer
{
progress.Value = p;
processLabel.Text = text;
Log += $"{Environment.NewLine}[{DateTime.Now.ToString(CultureInfo.InvariantCulture).Split(' ')[1]}] {text}";
Log(text);
}
private void log_Click(object sender, EventArgs e) => new Thread(() => MessageBox.Show(Log)).Start();
private void Log(string text) => _log +=
$"{Environment.NewLine}[{DateTime.Now.ToString(CultureInfo.InvariantCulture).Split(' ')[1]}] {text}";
private void log_Click(object sender, EventArgs e) => new Thread(() => MessageBox.Show(_log)).Start();
private void pathBox_CheckedChanged(object sender, EventArgs e)
{
startupBox.Enabled = pathBox.Checked;
if (!pathBox.Checked)
{
startupBox.Checked = false;
updateAppsBox.Checked = false;
updateAppsBox.Enabled = false;
}
}
private void startupBox_CheckedChanged(object sender, EventArgs e)
{
updateAppsBox.Enabled = startupBox.Checked;
if (!startupBox.Checked)
updateAppsBox.Checked = false;
}
}
}

View File

@ -61,7 +61,7 @@
<value>Thank you for downloading UpTool2.
To prevent inconsistent behavior you will need to install this before running.
Files will be placed in %appdata%\UpTool2 and %appdata%\Microsoft\Windows\Start Menu\Programs
There will also be a new PATH Entry for your user.
Do you want to continue?</value>
</data>
<assembly alias="System.Drawing.Common" name="System.Drawing.Common, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />

19
Installer/PATH.cs Normal file
View File

@ -0,0 +1,19 @@
using System;
using System.Linq;
namespace Installer
{
public static class Path
{
public static string[] Content
{
get => Environment.GetEnvironmentVariable("path", EnvironmentVariableTarget.User).Split(';');
set => Environment.SetEnvironmentVariable("path", string.Join(';', value), EnvironmentVariableTarget.User);
}
public static void Append(string path, bool escape = true) =>
Content = Content.Append(escape ? GetName(path) : path).ToArray();
public static string GetName(string path) => System.IO.Path.GetFullPath(path);
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace Installer
{
internal static class PathTool
{
public static string dir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UpTool2");
public static string tempPath => GetRelative("tmp");
public static string appsPath => GetRelative("Apps");
public static string InfoXml => GetRelative("info.xml");
public static string GetRelative(params string[] segments) =>
Path.Combine(new[] {dir}.Concat(segments).ToArray());
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Windows.Forms;
using UpToolLib;
namespace Installer
{

View File

@ -0,0 +1,65 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Windows.Forms;
using UpToolLib.DataStructures;
namespace Installer
{
internal class UtLibFunctionsGui : IExternalFunctionality
{
private readonly Action<string> _log;
public UtLibFunctionsGui(Action<string> log) => _log = log;
public Tuple<bool, byte[]> Download(Uri link)
{
using WebClient cli = new();
try
{
return new Tuple<bool, byte[]>(true, cli.DownloadData(link));
}
catch
{
return new Tuple<bool, byte[]>(false, new byte[0]);
}
}
public string FetchImageB64(Uri link)
{
using WebClient client = new();
Image src = Image.FromStream(
client.OpenRead(link));
Bitmap dest = new(70, 70);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
using (Graphics g = Graphics.FromImage(dest))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using ImageAttributes wrapMode = new();
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
GraphicsUnit.Pixel, wrapMode);
}
using MemoryStream ms = new();
dest.Save(ms, ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool _) =>
MessageBox.Show(text, "", MessageBoxButtons.YesNo) == DialogResult.Yes;
public void OkDialog(string text) => MessageBox.Show(text);
public object GetDefaultIcon() => 0;
public object ImageFromB64(string b64) =>
(Bitmap) new ImageConverter().ConvertFrom(Convert.FromBase64String(b64));
public void Log(string text) => _log(text);
}
}

2
InstallerCLI/Info.txt Normal file
View File

@ -0,0 +1,2 @@
Use "Installer --help" for info
(on non-windows platforms, use the dotnet CLI to run Installer.dll)

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Installer</AssemblyName>
<RootNamespace>Installer</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.2" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
</ItemGroup>
</Project>

90
InstallerCLI/Program.cs Normal file
View File

@ -0,0 +1,90 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Security.Cryptography;
using System.Threading;
using UpToolLib;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace Installer
{
public static class Program
{
public static bool Basic;
private static UpToolLibMain _lib;
public static int Main(string[] args)
{
Thread.Sleep(2000);
try
{
Basic = args.Length > 0 && args[0].ToLower() == "--basic";
_lib = new UpToolLibMain(new UtLibFunctions());
RootCommand rootCommand = new();
rootCommand.AddGlobalOption(new Option<bool>("--basic",
"Use only basic console functionality. Must be the first parameter in the call"));
Command install = new("install", "Install UpTool")
{
new Option<bool>(new[] {"--noPrep", "-p"}, "Doesn't initialize repos. Use with caution!")
};
install.AddAlias("-i");
install.AddAlias("i");
install.Handler = CommandHandler.Create<bool>(Install);
rootCommand.AddCommand(install);
return rootCommand.InvokeAsync(args).Result;
}
catch (Exception e)
{
Console.WriteLine($"FAILED: {e}");
return 1;
}
finally
{
_lib?.Dispose();
}
}
private static void Install(bool noPrep)
{
WebClient client = new();
Console.WriteLine("Downloading metadata");
UpdateCheck check =
_lib.V2.UpdateChecker.Check(
"https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/meta.xml?job=uptool");
PathTool pathTool = _lib.V1.PathTool;
Console.WriteLine("Downloading binary");
byte[] dl = client.DownloadData(check.App);
Console.WriteLine("Verifying integrity");
using (SHA256CryptoServiceProvider sha256 = new())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty)
.ToUpper();
if (pkgHash != check.AppHash)
throw new Exception($@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {check.AppHash}");
}
Console.WriteLine("Extracting");
if (Directory.Exists(pathTool.GetRelative("Install")))
{
foreach (string file in Directory.GetFiles(pathTool.GetRelative("Install"))) File.Delete(file);
foreach (string dir in Directory.GetDirectories(pathTool.GetRelative("Install")))
if (Path.GetFileName(dir) != "tmp")
Directory.Delete(dir, true);
}
Directory.CreateDirectory(pathTool.GetRelative("Install"));
using (MemoryStream ms = new(dl))
{
using ZipArchive ar = new(ms);
ar.ExtractToDirectory(pathTool.GetRelative("Install"), true);
}
if (noPrep) return;
Console.WriteLine("Preparing Repos");
_lib.V1.XmlTool.FixXml();
_lib.V2.RepoManagement.FetchRepos();
}
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.IO;
using System.Net;
using System.Threading;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using UpToolLib.DataStructures;
using static Installer.Program;
namespace Installer
{
public class UtLibFunctions : IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link)
{
using WebClient client = new();
byte[] result = new byte[0];
bool finished = false;
bool success = true;
client.DownloadDataCompleted += (sender, e) =>
{
success = !e.Cancelled;
if (success)
result = e.Result;
finished = true;
};
client.DownloadProgressChanged += (sender, e) =>
{
if (!Basic)
{
Console.Write(
$"{new string('=', e.ProgressPercentage / 10)}[{e.ProgressPercentage}]{new string('-', 10 - e.ProgressPercentage / 10)}");
Console.CursorLeft = 0;
}
};
client.DownloadDataAsync(link);
while (!finished)
Thread.Sleep(100);
return new Tuple<bool, byte[]>(success, result);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new();
using Image image = Image.Load(client.OpenRead(link));
using MemoryStream ms = new();
image.SaveAsPng(ms);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool defaultVal)
{
if (Basic)
{
Console.WriteLine(text);
Console.WriteLine($"Selecting: {defaultVal}");
return defaultVal;
}
else
{
bool choosing = true;
bool current = defaultVal;
Console.WriteLine(text);
while (choosing)
{
Console.CursorLeft = 0;
Console.BackgroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.Write("Yes");
Console.ResetColor();
Console.Write(" ");
Console.BackgroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.ForegroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.Write("No");
Console.ResetColor();
switch (Console.ReadKey().Key)
{
case ConsoleKey.LeftArrow:
case ConsoleKey.RightArrow:
current = !current;
break;
case ConsoleKey.Enter:
choosing = false;
break;
case ConsoleKey.Escape:
current = defaultVal;
choosing = false;
break;
}
}
Console.ResetColor();
Console.WriteLine($" Selecting: {current}");
return current;
}
}
public void OkDialog(string text)
{
if (Basic)
Console.WriteLine(text);
else
{
Console.WriteLine(text);
Console.BackgroundColor = ConsoleColor.White;
Console.Write("OK");
Console.ResetColor();
Console.ReadKey();
}
}
public object GetDefaultIcon() => 0;
public object ImageFromB64(string b64) => 0;
public void Log(string text) => Console.WriteLine(text);
}
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 J. Fronny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,11 +1,8 @@
# UpTool2
Downloading software from online repos since 2019\
[![CodeFactor](https://www.codefactor.io/repository/github/jfronny/uptool2/badge)](https://www.codefactor.io/repository/github/jfronny/uptool2)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JFronny/UpTool2)](https://github.com/JFronny/UpTool2/releases/latest)
[![GitHub repo size](https://img.shields.io/github/repo-size/JFronny/UpTool2)](https://github.com/JFronny/UpTool2/archive/master.zip)
[![GitHub All Releases](https://img.shields.io/github/downloads/JFronny/UpTool2/total)](https://github.com/JFronny/UpTool2/releases)
[![GitLab pipeline](https://img.shields.io/gitlab/pipeline/JFronny/UpTool2)](https://gitlab.com/JFronny/UpTool2/builds)
[![Discord](https://img.shields.io/discord/466965965658128384)](https://discordapp.com/invite/UjhHBqt)
[![Default Repo](https://img.shields.io/badge/Default-Repo-informational)](https://gist.github.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4)
[![Default Repo](https://img.shields.io/badge/Default-Repo-informational)](https://gitlab.com/JFronny/UpTool2/snippets/1988600)
## How to automate UpTool2 deployments
You will want the assembly version to automatically increment.
To achieve this you have to add this:\
@ -15,15 +12,15 @@ Now you can add this\
```if exist "$(SolutionDir)Data\pkgtool.exe" ($(SolutionDir)Data\pkgtool.exe build --noLogo --binDir .) else if exist "%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" ("%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" build --noLogo --binDir .) else echo Cound not find Package build tools, skipping```\
as a PostBuild event to automatically run pkgtool. Customize this if you need to.\
For GitHub actions I wrote [this](https://github.com/JFronny/CC-Clicker/blob/master/.github/workflows/main.yml).\
If you copy it, make sure to replace the descriptions and ID under the `Fenerate XML` step\
You can also add something like this to your Readme: [![UpTool2](https://img.shields.io/badge/dynamic/xml?color=informational&label=UpTool2&query=%2F%2Fapp%2FVersion&url=https%3A%2F%2Fgithub.com%2FJFronny%2FCC-Clicker%2Freleases%2Fdownload%2F1.0.7380.28108%2Fapp.xml&style=flat)](https://jfronny.github.io/home/uptool)\
If you copy it, make sure to replace the descriptions and ID under the `Generate XML` step\
You can also add something like this to your Readme: [![UpTool2](https://img.shields.io/badge/Get%20it-on%20UpTool2-blue)](https://jfronny.gitlab.io/home/uptool)\
(Look at the source for the MD Code)
## Folder layout
- %APPDATA%\UpTool2
- Apps
- __APPGUID
- `info.xml` Local copy of some app information, like [this](https://github.com/JFronny/UpTool2#app-layout) but missing ID, File, Hash and Icon
- [`package.zip`](https://github.com/JFronny/UpTool2#package-layout) The package that was downloaded on install
- `info.xml` Local copy of some app information, like [this](https://gitlab.com/JFronny/UpTool2#app-layout) but missing ID, File, Hash, Platform and Icon
- [`package.zip`](https://gitlab.com/JFronny/UpTool2#package-layout) The package that was downloaded on install
- `app` The app install path
- `__APPFILES` Copy of the app files from above, may contain user-configs
- `info.xml` File used by UpTool2 for saving info
@ -33,7 +30,7 @@ You can also add something like this to your Readme: [![UpTool2](https://img.shi
- `Name` The display name of the repository
- `Link` The source of the repo xml
- `Local Repo` A preprocessed copy of the online repos
- [`__APP`](https://github.com/JFronny/UpTool2#app-layout) A normal app with the icon processed as Base64
- [`__APP`](https://gitlab.com/JFronny/UpTool2#app-layout) A normal app with the icon processed as Base64
- `Install` The folder containing the actual tool
- `__ZIP CONTENTS` The app files
- `tmp` A temporary folder used during updates
@ -42,7 +39,7 @@ You can also add something like this to your Readme: [![UpTool2](https://img.shi
- `repo` The main repo tag
- `__APPLINK` Links to external app XMLs
- `__REPOLINK` Links to external repos
- [`__APP`](https://github.com/JFronny/UpTool2#app-layout) Apps
- [`__APP`](https://gitlab.com/JFronny/UpTool2#app-layout) Apps
## App layout
- app
- `Name` Name of the application
@ -53,6 +50,7 @@ You can also add something like this to your Readme: [![UpTool2](https://img.shi
- `Hash` The files SHA256 Hash
- `Icon` The apps icon, (optional)
- `MainFile` Main binary, used for starting, (optional)
- `Platform` The platform this works on (optional, defaults to current)
## Package layout
- `Install.bat` The script for installing the app
- `Remove.bat` The script for removing the app

View File

@ -0,0 +1,31 @@
using System;
using System.IO;
namespace UpTool_build_tool
{
internal static class BatchScripts
{
public static Tuple<string, string> Create(bool shortcuts, string? mainBin, string programName,
string? postInstall, string? postRemove)
{
string installBat = "@echo off\r\necho INSTALL";
string removeBat = "@echo off\r\necho REMOVE";
if (shortcuts)
{
installBat += "\r\n";
installBat +=
$@"powershell ""$s=(New-Object -COM WScript.Shell).CreateShortcut('%appdata%\Microsoft\Windows\Start Menu\Programs\{programName}.lnk');$s.TargetPath='%cd%\{Path.GetFileName(mainBin)}';$s.Save()""";
removeBat += "\r\n";
removeBat += $@"del ""%appdata%\Microsoft\Windows\Start Menu\Programs\{programName}.lnk""";
}
if (!string.IsNullOrWhiteSpace(mainBin))
{
removeBat += "\r\n";
removeBat += $@"taskkill /f /im ""{Path.GetFileName(mainBin)}""";
}
installBat += $"\r\n{postInstall}";
removeBat += $"\r\n{postRemove}";
return new Tuple<string, string>(installBat, removeBat);
}
}
}

View File

@ -5,7 +5,7 @@ using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace UpTool_build_tool
{
@ -14,21 +14,29 @@ namespace UpTool_build_tool
public static int Main(string[] args)
{
RootCommand rootCommand = new RootCommand();
Command build = new Command("build", "Builds a generic package with or without shortcuts from a directory");
build.AddOption(new Option<string>("--binDir", "Directory to package"));
build.AddOption(new Option<string>("--mainBin", "The applications main binary"));
build.AddOption(new Option<string>("--packageFile", "Directory to package"));
build.AddOption(new Option<string>("--postInstall", () => "", "Command(s) to run after installing the package"));
build.AddOption(new Option<string>("--postRemove", () => "", "Command(s) to run after removing the package"));
build.AddOption(new Option<bool>("--noLogo", "Disables the logo"));
build.AddOption(new Option<bool>("--noShortcuts",
"When this is enabled the scripts will not generate a start-menu item"));
build.Handler = CommandHandler.Create<string, string, string, string, string, bool, bool>(Build);
Command build = new Command("build", "Builds a generic package with or without shortcuts from a directory")
{
new Option<string>("--binDir", "Directory to package"),
new Option<string>("--mainBin", () => "FIND_BIN", "The applications main binary"),
new Option<string>("--packageFile", "Directory to package"),
new Option<string>("--postInstall", () => "",
"Command(s) to run after installing the package (This will be pasted into the .bat AND .sh file)"),
new Option<string>("--postRemove", () => "",
"Command(s) to run after removing the package (This will be pasted into the .bat AND .sh file)"),
new Option<bool>("--noLogo", "Disables the logo"),
new Option<bool>("--noShortcuts",
"When this is enabled the scripts will not generate a start-menu item"),
new Option<bool>("--noWine",
"This indicates that your program supports multiple platforms natively and doesn't require WINE")
};
build.Handler =
CommandHandler.Create((Action<string?, string, string, string, string, bool, bool, bool>) Build);
rootCommand.AddCommand(build);
return rootCommand.InvokeAsync(args).Result;
}
private static void Build(string binDir, string mainBin, string packageFile, string postInstall, string postRemove, bool noLogo, bool noShortcuts)
private static void Build(string? binDir, string? mainBin, string? packageFile, string? postInstall,
string? postRemove, bool noLogo, bool noShortcuts, bool noWine)
{
Stopwatch watch = Stopwatch.StartNew();
if (!noLogo)
@ -52,9 +60,7 @@ namespace UpTool_build_tool
{
archive.AddDirectory(binDir, "Data", new[] {".xml", ".pdb"}, new[] {packageFile});
Console.WriteLine("Creating batch scripts...");
string installBat = "@echo off\r\necho INSTALL";
string removeBat = "@echo off\r\necho REMOVE";
if (string.IsNullOrWhiteSpace(mainBin))
if (mainBin == "FIND_BIN")
{
string[] tmp = Directory.GetFiles(binDir, "*.exe");
if (tmp.Length > 0)
@ -68,35 +74,22 @@ namespace UpTool_build_tool
}
}
string programName = Path.GetFileNameWithoutExtension(mainBin);
if (!noShortcuts)
{
installBat += "\r\n";
installBat +=
$@"powershell ""$s=(New-Object -COM WScript.Shell).CreateShortcut('%appdata%\Microsoft\Windows\Start Menu\Programs\{programName}.lnk');$s.TargetPath='%cd%\{mainBin}';$s.Save()""";
removeBat += "\r\n";
removeBat += $@"del ""%appdata%\Microsoft\Windows\Start Menu\Programs\{programName}.lnk""";
}
if (!string.IsNullOrWhiteSpace(mainBin))
{
removeBat += "\r\n";
removeBat += $@"taskkill /f /im ""{Path.GetFileName(mainBin)}""";
}
installBat += $"\r\n{postInstall}";
removeBat += $"\r\n{postRemove}";
using (Stream s = archive.CreateEntry("Install.bat").Open())
{
using StreamWriter writer = new StreamWriter(s);
writer.Write(installBat);
}
using (Stream s = archive.CreateEntry("Remove.bat").Open())
{
using StreamWriter writer = new StreamWriter(s);
writer.Write(removeBat);
}
(string installBat, string removeBat) =
BatchScripts.Create(!noShortcuts, mainBin, programName, postInstall, postRemove);
archive.AddFile("Install.bat", installBat);
archive.AddFile("Remove.bat", removeBat);
ShScripts.Create(archive.AddFile, !noShortcuts, mainBin, programName, postInstall, postRemove, !noWine);
}
watch.Stop();
Console.WriteLine($"Completed package creation in {watch.Elapsed}");
Console.WriteLine($"Output file: {Path.GetFullPath(packageFile)}");
}
private static void AddFile(this ZipArchive archive, string fileName, string content)
{
using Stream s = archive.CreateEntry(fileName).Open();
using StreamWriter writer = new StreamWriter(s);
writer.Write(content);
}
}
}

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UpTool_build_tool")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UpTool_build_tool")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("AAB8D6BA-3A43-4DC4-95EE-6757482B77FD")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,41 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace UpTool_build_tool
{
internal static class ShScripts
{
public static void Create(Action<string, string> fileSave, bool shortcuts, string? mainBin, string programName,
string? postInstall, string? postRemove, bool wine)
{
Regex rgx = new Regex("[^a-z0-9]");
Regex upRgx = new Regex("[^a-zA-Z0-9 -]");
string lnkName = $"~/.local/share/applications/{rgx.Replace(programName.ToLower(), "")}.desktop";
string installSh = "#!/bin/bash\necho INSTALL";
string removeSh = "#!/bin/bash\necho REMOVE";
if (shortcuts)
{
installSh += $@"
echo ""[Desktop Entry]"" > {lnkName}
echo ""Exec={(wine ? "wine " : "")}{Path.GetFileName(mainBin)}"" >> {lnkName}
echo ""Icon=application/x-shellscript"" >> {lnkName}
echo ""Name={upRgx.Replace(programName, "")}"" >> {lnkName}
echo ""StartupNotify=false"" >> {lnkName}
echo ""Terminal=false"" >> {lnkName}
echo ""Type=Application"" >> {lnkName}";
removeSh += "\r\n";
removeSh += $@"rm {lnkName}";
}
if (!string.IsNullOrWhiteSpace(mainBin))
{
removeSh += "\r\n";
removeSh += $@"pkill -f ""{Path.GetFileName(mainBin)}""";
}
installSh += $"\r\n{postInstall}";
removeSh += $"\r\n{postRemove}";
fileSave("Install.sh", installSh);
fileSave("Remove.sh", removeSh);
}
}
}

View File

@ -1,20 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>UpTool_build_tool</RootNamespace>
<AssemblyName>pkgtool</AssemblyName>
<Deterministic>false</Deterministic>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AssemblyVersion>1.0.*</AssemblyVersion>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>.\pkgtool.exe build --noLogo --noShortcuts --binDir .</PostBuildEvent>
<PostBuildEvent Condition="'$(OS)' != 'Windows_NT'">.\pkgtool build --noLogo --noShortcuts --binDir . --mainBin ""</PostBuildEvent>
<PostBuildEvent Condition="'$(OS)' == 'Windows_NT'">pkgtool.exe build --noLogo --noShortcuts --binDir . --mainBin ""</PostBuildEvent>
<ApplicationIcon>..\UpTool2.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CC-Functions.Misc" Version="1.1.7384.27745" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20104.2" />
<PackageReference Include="CC-Functions.Core" Version="1.1.7628.34181" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
</ItemGroup>
</Project>
</Project>

View File

@ -8,14 +8,33 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9841227C-3F1B-4C32-8123-3DB2CF4E15EE}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
.github\workflows\main.yml = .github\workflows\main.yml
README.md = README.md
CLI.md = CLI.md
.gitlab-ci.yml = .gitlab-ci.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpTool build tool", "UpTool build tool\UpTool build tool.csproj", "{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{1D273392-3796-4BE9-A67F-BB402315D52D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolLib", "UpToolLib\UpToolLib.csproj", "{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolCLI", "UpToolCLI\UpToolCLI.csproj", "{3EC369B9-D927-4A53-BE1A-7E7006081BCE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GUI", "GUI", "{EA919DFD-766B-423C-99DF-C99356592842}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CLI", "CLI", "{3CFAB991-C12A-4B51-BC91-6965133DAF53}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{0E778462-504C-4183-A27E-44EEE7B8CCDD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallerCLI", "InstallerCLI\InstallerCLI.csproj", "{493B2CC5-29E9-4F10-A2F5-E10B9584D667}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolEto", "UpToolEto\UpToolEto\UpToolEto.csproj", "{213FF69B-426E-475F-8A77-0A20EA4257C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolEto.Gtk", "UpToolEto\UpToolEto.Gtk\UpToolEto.Gtk.csproj", "{8A544AEA-3081-45C9-BED2-7E424EB287B1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpToolEto.Wpf", "UpToolEto\UpToolEto.Wpf\UpToolEto.Wpf.csproj", "{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -34,6 +53,30 @@ Global
{1D273392-3796-4BE9-A67F-BB402315D52D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.Build.0 = Release|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2}.Release|Any CPU.Build.0 = Release|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EC369B9-D927-4A53-BE1A-7E7006081BCE}.Release|Any CPU.Build.0 = Release|Any CPU
{493B2CC5-29E9-4F10-A2F5-E10B9584D667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{493B2CC5-29E9-4F10-A2F5-E10B9584D667}.Debug|Any CPU.Build.0 = Debug|Any CPU
{493B2CC5-29E9-4F10-A2F5-E10B9584D667}.Release|Any CPU.ActiveCfg = Release|Any CPU
{493B2CC5-29E9-4F10-A2F5-E10B9584D667}.Release|Any CPU.Build.0 = Release|Any CPU
{213FF69B-426E-475F-8A77-0A20EA4257C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{213FF69B-426E-475F-8A77-0A20EA4257C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{213FF69B-426E-475F-8A77-0A20EA4257C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{213FF69B-426E-475F-8A77-0A20EA4257C2}.Release|Any CPU.Build.0 = Release|Any CPU
{8A544AEA-3081-45C9-BED2-7E424EB287B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A544AEA-3081-45C9-BED2-7E424EB287B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A544AEA-3081-45C9-BED2-7E424EB287B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A544AEA-3081-45C9-BED2-7E424EB287B1}.Release|Any CPU.Build.0 = Release|Any CPU
{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -41,4 +84,15 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {008127DC-F473-4709-A763-75F5FCED93AB}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FACD621F-6C6D-4D4B-B322-4364A0F9B4C2} = {0E778462-504C-4183-A27E-44EEE7B8CCDD}
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD} = {0E778462-504C-4183-A27E-44EEE7B8CCDD}
{C0C1E002-9E13-4E8F-A035-DBDC5128E00E} = {EA919DFD-766B-423C-99DF-C99356592842}
{3EC369B9-D927-4A53-BE1A-7E7006081BCE} = {3CFAB991-C12A-4B51-BC91-6965133DAF53}
{1D273392-3796-4BE9-A67F-BB402315D52D} = {EA919DFD-766B-423C-99DF-C99356592842}
{493B2CC5-29E9-4F10-A2F5-E10B9584D667} = {3CFAB991-C12A-4B51-BC91-6965133DAF53}
{213FF69B-426E-475F-8A77-0A20EA4257C2} = {EA919DFD-766B-423C-99DF-C99356592842}
{8A544AEA-3081-45C9-BED2-7E424EB287B1} = {EA919DFD-766B-423C-99DF-C99356592842}
{C89EC79F-CC2B-4B8E-B4CB-D4DFD30A58AB} = {EA919DFD-766B-423C-99DF-C99356592842}
EndGlobalSection
EndGlobal

View File

@ -1,14 +0,0 @@
using System;
namespace UpTool2.DataStructures
{
[Flags]
public enum Status
{
Not_Installed = 1,
Updatable = 2,
Installed = 4,
Local = 8,
All = 15
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using UpTool2.DataStructures;
namespace UpTool2
{
internal static class GlobalVariables
{
public static readonly Dictionary<Guid, App> Apps = new Dictionary<Guid, App>();
public static bool RelE = true;
public static Action ReloadElements;
public static Version minimumVer => Version.Parse("0.0.0.0");
}
}

View File

@ -46,13 +46,18 @@
this.controls_settings = new System.Windows.Forms.Button();
this.controls_reload = new System.Windows.Forms.Button();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.changesButton = new System.Windows.Forms.Button();
this.searchPackageDialog = new System.Windows.Forms.OpenFileDialog();
this.changesPanel = new System.Windows.Forms.Panel();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.changesLabel = new System.Windows.Forms.Label();
this.infoPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.optionsPanel.SuspendLayout();
this.changesPanel.SuspendLayout();
this.SuspendLayout();
//
// sidebarPanel
@ -62,7 +67,7 @@
this.sidebarPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.sidebarPanel.Location = new System.Drawing.Point(0, 68);
this.sidebarPanel.Name = "sidebarPanel";
this.sidebarPanel.Size = new System.Drawing.Size(312, 451);
this.sidebarPanel.Size = new System.Drawing.Size(312, 425);
this.sidebarPanel.TabIndex = 0;
//
// infoPanel
@ -76,7 +81,7 @@
this.infoPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.infoPanel.Location = new System.Drawing.Point(0, 0);
this.infoPanel.Name = "infoPanel";
this.infoPanel.Size = new System.Drawing.Size(616, 519);
this.infoPanel.Size = new System.Drawing.Size(616, 493);
this.infoPanel.TabIndex = 1;
//
// action_run
@ -128,9 +133,12 @@
//
// infoPanel_Description
//
this.infoPanel_Description.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.infoPanel_Description.Location = new System.Drawing.Point(3, 51);
this.infoPanel_Description.Name = "infoPanel_Description";
this.infoPanel_Description.Size = new System.Drawing.Size(611, 458);
this.infoPanel_Description.Size = new System.Drawing.Size(611, 439);
this.infoPanel_Description.TabIndex = 1;
//
// infoPanel_Title
@ -158,7 +166,7 @@
//
this.splitContainer.Panel2.Controls.Add(this.infoPanel);
this.splitContainer.Panel2MinSize = 160;
this.splitContainer.Size = new System.Drawing.Size(933, 519);
this.splitContainer.Size = new System.Drawing.Size(933, 493);
this.splitContainer.SplitterDistance = 312;
this.splitContainer.SplitterWidth = 5;
this.splitContainer.TabIndex = 0;
@ -237,16 +245,63 @@
this.toolTip.ReshowDelay = 100;
this.toolTip.ShowAlways = true;
//
// changesButton
//
this.changesButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.changesButton.Location = new System.Drawing.Point(906, 0);
this.changesButton.Name = "changesButton";
this.changesButton.Size = new System.Drawing.Size(27, 26);
this.changesButton.TabIndex = 4;
this.changesButton.Text = "→";
this.toolTip.SetToolTip(this.changesButton, "Perform changes");
this.changesButton.UseVisualStyleBackColor = true;
this.changesButton.Click += new System.EventHandler(this.changesButton_Click);
//
// searchPackageDialog
//
this.searchPackageDialog.Filter = "Packages (*.zip)|*.zip";
//
// changesPanel
//
this.changesPanel.Controls.Add(this.progressBar1);
this.changesPanel.Controls.Add(this.changesButton);
this.changesPanel.Controls.Add(this.changesLabel);
this.changesPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.changesPanel.Location = new System.Drawing.Point(0, 493);
this.changesPanel.Name = "changesPanel";
this.changesPanel.Size = new System.Drawing.Size(933, 26);
this.changesPanel.TabIndex = 1;
this.changesPanel.Visible = false;
//
// progressBar1
//
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.progressBar1.Location = new System.Drawing.Point(714, 0);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(186, 26);
this.progressBar1.Step = 1;
this.progressBar1.TabIndex = 5;
//
// changesLabel
//
this.changesLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.changesLabel.AutoSize = true;
this.changesLabel.Location = new System.Drawing.Point(7, 5);
this.changesLabel.Name = "changesLabel";
this.changesLabel.Size = new System.Drawing.Size(119, 15);
this.changesLabel.TabIndex = 0;
this.changesLabel.Text = "No Changes Selected";
this.changesLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.changesLabel.Click += new System.EventHandler(this.changesLabel_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(933, 519);
this.Controls.Add(this.splitContainer);
this.Controls.Add(this.changesPanel);
this.HelpButton = true;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(631, 269);
@ -262,11 +317,13 @@
this.splitContainer.ResumeLayout(false);
this.optionsPanel.ResumeLayout(false);
this.optionsPanel.PerformLayout();
this.changesPanel.ResumeLayout(false);
this.changesPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion
#endregion
private System.Windows.Forms.FlowLayoutPanel sidebarPanel;
private System.Windows.Forms.Panel infoPanel;
@ -285,6 +342,10 @@
private System.Windows.Forms.Button action_run;
private System.Windows.Forms.Button controls_upload;
private System.Windows.Forms.OpenFileDialog searchPackageDialog;
private System.Windows.Forms.Panel changesPanel;
private System.Windows.Forms.Label changesLabel;
private System.Windows.Forms.Button changesButton;
private System.Windows.Forms.ProgressBar progressBar1;
}
}

View File

@ -1,33 +1,36 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Windows.Forms;
using UpTool2.DataStructures;
using UpTool2.Properties;
using UpTool2.Tool;
#if DEBUG
using System.Threading;
using System.Linq;
#endif
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using UpToolLib;
using UpToolLib.DataStructures;
using System.Diagnostics;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpTool2
{
public sealed partial class MainForm : Form
{
HelpEventHandler help;
private readonly HelpEventHandler _help;
private List<AppTask> _tasks;
public MainForm()
{
GlobalVariables.ReloadElements = ReloadElements;
InitializeComponent();
help = MainForm_HelpRequested;
HelpRequested += help;
_tasks = new List<AppTask>();
_help = MainForm_HelpRequested;
HelpRequested += _help;
filterBox.DataSource = Enum.GetValues(typeof(Status));
if (Program.Online)
{
RepoManagement.FetchRepos();
Program.SetSplash(8, "Fetching repositories");
Program.Lib.V2.RepoManagement.FetchRepos();
}
else
{
@ -36,90 +39,67 @@ namespace UpTool2
filterBox.Enabled = false;
filterBox.SelectedIndex = 2;
}
Program.SetSplash(8, "Reloading data");
Program.SetSplash(9, "Reloading data");
ReloadElements();
if (!Directory.Exists(PathTool.appsPath))
Directory.CreateDirectory(PathTool.appsPath);
if (!Directory.Exists(Program.Lib.V1.PathTool.AppsPath))
Directory.CreateDirectory(Program.Lib.V1.PathTool.AppsPath);
}
private void Action_install_Click(object sender, EventArgs e)
{
bool trying = true;
while (trying)
App tmp = (App) action_install.Tag;
if (_tasks.Any(s => s is InstallTask t && t.App == tmp))
{
#if !DEBUG
try
{
#endif
AppInstall.Install((App) action_install.Tag);
trying = false;
#if !DEBUG
}
catch (Exception e1)
{
if (!GlobalVariables.RelE)
throw;
trying = MessageBox.Show(e1.ToString(), "Install failed", MessageBoxButtons.RetryCancel) ==
DialogResult.Retry;
}
#endif
_tasks = _tasks.Where(s => !(s is InstallTask t) || t.App != tmp).ToList();
action_install.ResetBackColor();
}
else
{
_tasks.Add(Program.Lib.V2.TaskFactory.CreateInstall(tmp, ReloadElements));
action_install.BackColor = Color.Green;
}
UpdateChangesLabel();
}
private void Action_remove_Click(object sender, EventArgs e)
{
try
App tmp = (App) action_install.Tag;
if (_tasks.Any(s => s is RemoveTask t && t.App == tmp))
{
string app = ((App) action_remove.Tag).appPath;
string tmp = PathTool.tempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
ZipFile.ExtractToDirectory(Path.Combine(app, "package.zip"), tmp);
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C \"{Path.Combine(tmp, "Remove.bat")}\"",
WorkingDirectory = Path.Combine(app, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
Directory.Delete(tmp, true);
Directory.Delete(app, true);
if (GlobalVariables.RelE)
ReloadElements();
_tasks = _tasks.Where(s => !(s is RemoveTask t) || t.App != tmp).ToList();
action_remove.ResetBackColor();
}
catch (Exception e1)
else
{
if (!GlobalVariables.RelE)
throw;
MessageBox.Show(e1.ToString(), "Removal failed");
_tasks.Add(Program.Lib.V2.TaskFactory.CreateRemove(tmp, ReloadElements));
action_remove.BackColor = Color.Green;
}
UpdateChangesLabel();
}
private void controls_upload_Click(object sender, EventArgs e)
{
#if !DEBUG
try
if (searchPackageDialog.ShowDialog() != DialogResult.OK)
return;
if (!_tasks.Any(s => s is UploadTask t && t.ZipFile == searchPackageDialog.FileName))
_tasks.Add(Program.Lib.V2.TaskFactory.CreateUpload(searchPackageDialog.FileName, AppNameDialog.Show(), ReloadElements));
UpdateChangesLabel();
}
private void Action_update_Click(object sender, EventArgs e)
{
App tmp = (App) action_install.Tag;
if (_tasks.Any(s => s is UpdateTask t && t.App == tmp))
{
#endif
if (searchPackageDialog.ShowDialog() != DialogResult.OK)
return;
Guid id = Guid.NewGuid();
while (GlobalVariables.Apps.ContainsKey(id) || Directory.Exists(PathTool.GetAppPath(id)))
id = Guid.NewGuid();
App appI = new App(AppNameDialog.Show(), "Locally installed package, removal only",
GlobalVariables.minimumVer, "", true, "", id, Color.Red, Resources.C_64.ToBitmap(), false, "");
AppInstall.InstallZip(searchPackageDialog.FileName, appI);
#if !DEBUG
_tasks = _tasks.Where(s => !(s is UpdateTask t) || t.App != tmp).ToList();
action_update.ResetBackColor();
}
catch (Exception e1)
else
{
if (!GlobalVariables.RelE)
throw;
MessageBox.Show(e1.ToString(), "Install failed");
_tasks.Add(Program.Lib.V2.TaskFactory.CreateUpdate(tmp, ReloadElements));
action_update.BackColor = Color.Green;
}
#endif
UpdateChangesLabel();
}
private void ReloadElements()
@ -129,9 +109,9 @@ namespace UpTool2
ClearSelection();
infoPanel_Title.Invalidate();
infoPanel_Description.Invalidate();
int F = sidebarPanel.Controls.Count;
for (int i = 0; i < F; i++) sidebarPanel.Controls[0].Dispose();
GlobalVariables.Apps.Clear();
int f = sidebarPanel.Controls.Count;
for (int i = 0; i < f; i++) sidebarPanel.Controls[0].Dispose();
Program.Lib.V1.Apps.Clear();
//add
toolTip.SetToolTip(controls_settings, "Settings");
toolTip.SetToolTip(controls_reload, "Refresh repositories");
@ -141,83 +121,89 @@ namespace UpTool2
toolTip.SetToolTip(action_remove, "Remove");
toolTip.SetToolTip(action_update, "Update");
toolTip.SetToolTip(action_run, "Run");
RepoManagement.GetReposFromDisk();
Program.Lib.V2.RepoManagement.GetReposFromDisk();
int availableUpdates = 0;
foreach (App app in GlobalVariables.Apps.Values)
foreach (App app in Program.Lib.V1.Apps.Values)
{
Panel sidebarIcon = new Panel();
sidebarIcon.Tag = app;
sidebarIcon.BackColor = app.Color;
sidebarIcon.Size = new Size(70, 70);
sidebarIcon.BackgroundImage = app.Icon;
sidebarIcon.BackgroundImageLayout = ImageLayout.Stretch;
bool updatable = !app.Local && (app.status & Status.Updatable) == Status.Updatable;
Panel sidebarIcon = new Panel
{
Tag = app,
BackColor = app.Color,
Size = new Size(70, 70),
BackgroundImage = (Bitmap) app.Icon,
BackgroundImageLayout = ImageLayout.Stretch
};
sidebarIcon.Paint += (sender, args) =>
{
args.Graphics.Clear(sidebarIcon.BackColor);
args.Graphics.DrawImage(sidebarIcon.BackgroundImage, args.ClipRectangle,
new Rectangle(new Point(0, 0), sidebarIcon.BackgroundImage.Size), GraphicsUnit.Pixel);
};
bool updateable = !app.Local && app.Status.Contains(Status.Updatable);
sidebarIcon.Click += (sender, e) =>
{
infoPanel_Title.Text = app.Name;
infoPanel_Title.ForeColor = app.Local ? Color.Red : Color.Black;
infoPanel_Description.Text = app.Description;
action_install.Tag = app;
action_install.Enabled = !(app.Local || Directory.Exists(app.appPath));
action_install.Enabled = !(app.Local || Directory.Exists(app.AppPath));
if (_tasks.Any(s => s is InstallTask t && t.App == app))
action_install.BackColor = Color.Green;
else
action_install.ResetBackColor();
action_remove.Tag = app;
action_remove.Enabled = Directory.Exists(app.appPath);
action_remove.Enabled = Directory.Exists(app.AppPath);
if (_tasks.Any(s => s is RemoveTask t && t.App == app))
action_remove.BackColor = Color.Green;
else
action_remove.ResetBackColor();
action_update.Tag = app;
action_update.Enabled = updatable;
action_update.Enabled = updateable;
if (_tasks.Any(s => s is UpdateTask t && t.App == app))
action_update.BackColor = Color.Green;
else
action_update.ResetBackColor();
action_run.Tag = app;
action_run.Enabled = (app.status & Status.Installed) == Status.Installed && !app.Local && app.Runnable && Directory.Exists(app.appPath);
action_run.Enabled = app.Status.Contains(Status.Installed) && !app.Local &&
app.Runnable && Directory.Exists(app.AppPath);
};
if (updatable)
if (updateable)
availableUpdates++;
toolTip.SetToolTip(sidebarIcon, app.Name);
sidebarPanel.Controls.Add(sidebarIcon);
}
UpdateSidebarV(null, null);
Text =
$"UpTool2 {(availableUpdates == 0 ? "(All up-to-date)" : $"({availableUpdates.ToString()} Updates)")}";
$"UpTool2 {(availableUpdates == 0 ? "(All up-to-date)" : $"({availableUpdates} Updates)")}";
}
private void Action_run_Click(object sender, EventArgs e)
{
string path = Path.Combine(((App) action_run.Tag).dataPath, ((App) action_run.Tag).MainFile);
try
{
Process.Start(
new ProcessStartInfo
{
FileName = path,
WorkingDirectory = ((App) action_run.Tag).dataPath
});
Program.Lib.V1.AppExtras.RunApp((App) action_run.Tag);
}
catch (Exception e1)
{
MessageBox.Show(e1
#if DEBUG
+ $"{Environment.NewLine}File was: {path}"
#endif
+ "Failed to start!");
MessageBox.Show($"{e1}Failed to start!");
}
}
private void Action_update_Click(object sender, EventArgs e)
{
try
{
GlobalVariables.RelE = false;
Action_remove_Click(sender, e);
Action_install_Click(sender, e);
}
catch (Exception e1)
{
MessageBox.Show(e1.ToString(), "Install failed");
}
ReloadElements();
GlobalVariables.RelE = true;
}
private void Controls_reload_Click(object sender, EventArgs e)
{
RepoManagement.FetchRepos();
ReloadElements();
Enabled = false;
if (MessageBox.Show("This may take a few minutes. Are you sure?", "", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
new Thread(() =>
{
Program.Lib.V2.RepoManagement.FetchRepos();
Invoke((Action) (() =>
{
ReloadElements();
Enabled = true;
}));
}).Start();
}
}
private void Controls_settings_Click(object sender, EventArgs e) => new SettingsForms().ShowDialog();
@ -225,24 +211,29 @@ namespace UpTool2
private void ClearSelection()
{
action_install.Enabled = false;
action_install.ResetBackColor();
action_remove.Enabled = false;
action_remove.ResetBackColor();
action_update.Enabled = false;
action_update.ResetBackColor();
action_run.Enabled = false;
action_run.ResetBackColor();
infoPanel_Title.Text = "";
infoPanel_Description.Text = "";
}
private void UpdateSidebarV(object sender, EventArgs e)
{
#if DEBUG
if (searchBox.Text == "!DEBUG:PRINT!")
{
searchBox.Text = "!DEBUG:PRINT";
string tmpFile = Path.GetTempFileName();
File.WriteAllText(tmpFile,
string.Join("\r\n\r\n",
GlobalVariables.Apps.Values.Select(app => app.ToString()).Concat(new[]
{"Assembly version: " + Assembly.GetExecutingAssembly().GetName().Version}).ToArray()));
Program.Lib.V1.Apps.Values.Select(app => app.ToString()).Concat(new[]
{
$"Assembly version: {Assembly.GetExecutingAssembly().GetName().Version}"
}).ToArray()));
new Thread(() =>
{
Process.Start("notepad", tmpFile).WaitForExit();
@ -251,31 +242,27 @@ namespace UpTool2
}
else
{
#endif
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
App app = (App) sidebarIcon.Tag;
sidebarIcon.Visible = app.Name.Contains(searchBox.Text) &&
((int) app.status & (int) (Program.Online ? status : Status.Installed)) != 0;
App[] apps = Program.Lib.V1.AppExtras.FindApps(searchBox.Text);
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
App app = (App) sidebarIcon.Tag;
sidebarIcon.Visible = apps.Contains(app) && app.Status.Contains(Program.Online ? status : Status.Installed);
}
ClearSelection();
}
ClearSelection();
#if DEBUG
}
#endif
}
private void MainForm_Load(object sender, EventArgs e)
{
if (Program.Splash.IsDisposed)
{
Close();
}
else
{
Program.Splash.Invoke((Action)Program.Splash.Hide);
Program.Splash.Invoke((Action) Program.Splash.Hide);
BringToFront();
UpdateChangesLabel(false);
}
}
@ -294,10 +281,7 @@ namespace UpTool2
}
finally
{
if (stream != null)
{
stream.Close();
}
stream?.Close();
}
int i = BitConverter.ToInt32(buffer, headerOffset);
@ -308,9 +292,9 @@ namespace UpTool2
return dt;
}
private void MainForm_HelpRequested(object sender, HelpEventArgs hlpevent)
private void MainForm_HelpRequested(object sender, HelpEventArgs hlpEvent)
{
HelpRequested -= help;
HelpRequested -= _help;
try
{
DateTime buildTime = GetBuildDateTime(Assembly.GetExecutingAssembly());
@ -320,9 +304,44 @@ Build Date: {buildTime:dd.MM.yyyy}", "UpTool2");
}
finally
{
HelpRequested += help;
hlpevent.Handled = true;
HelpRequested += _help;
hlpEvent.Handled = true;
}
}
private void changesButton_Click(object sender, EventArgs e)
{
if (TaskPreview.Show(ref _tasks, true))
{
progressBar1.Maximum = _tasks.Count;
progressBar1.Value = 0;
foreach (AppTask task in _tasks)
{
task.Run();
progressBar1.PerformStep();
}
_tasks.Clear();
UpdateChangesLabel();
}
}
private void changesLabel_Click(object sender, EventArgs e)
{
TaskPreview.Show(ref _tasks, false);
UpdateChangesLabel();
}
private void UpdateChangesLabel(bool showPanel = true)
{
changesPanel.Visible = showPanel;
changesButton.Enabled = _tasks.Count > 0;
progressBar1.Maximum = _tasks.Count;
changesLabel.Text = _tasks.Count switch
{
0 => "No Changes Selected",
1 => "1 Change Selected",
_ => $"{_tasks.Count} Changes Selected"
};
}
}
}

View File

@ -1,76 +1,69 @@
using System;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using UpTool2.Tool;
using UpToolLib;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace UpTool2
{
internal static class Program
{
public static Form Splash;
private static int SplashProgress;
private static string SplashMessage;
public static Form? Splash;
private static int _splashProgress;
private static string? _splashMessage;
public static bool Online;
public static UpToolLibMain Lib;
[STAThread]
private static void Main()
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
BuildSplash();
new Thread(() => { Splash.ShowDialog(); }).Start();
using Mutex mutex = new Mutex(false,
$"Global\\{{{((GuidAttribute) Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value}}}",
out bool _);
bool hasHandle = false;
Splash.Show();
try
{
Lib = new UpToolLibMain(new UtLibFunctions());
}
catch (MutexLockLockedException)
{
Console.WriteLine("Mutex property of other process, quitting");
Process[] processes = Process.GetProcessesByName("UpTool2");
if (processes.Length > 0)
WindowHelper.BringProcessToFront(Process.GetProcessesByName("UpTool2")[0]);
return;
}
#if !DEBUG
try
{
#endif
try
{
hasHandle = mutex.WaitOne(5000, false);
if (hasHandle == false)
{
Console.WriteLine("Mutex property of other process, quitting");
Process[] processes = Process.GetProcessesByName("UpTool2");
if (processes.Length > 0)
WindowHelper.BringProcessToFront(Process.GetProcessesByName("UpTool2")[0]);
Environment.Exit(0);
}
}
catch (AbandonedMutexException)
{
#if DEBUG
Debug.WriteLine("Mutex abandoned");
#endif
hasHandle = true;
}
SetSplash(1, "Initializing paths");
if (!Directory.Exists(PathTool.dir))
Directory.CreateDirectory(PathTool.dir);
if (!Directory.Exists(Lib.V1.PathTool.Dir))
Directory.CreateDirectory(Lib.V1.PathTool.Dir);
FixXml();
SetSplash(2, "Performing checks");
string metaXml = XDocument.Load(PathTool.InfoXml).Element("meta").Element("UpdateSource").Value;
Online = Ping(metaXml);
if (Application.ExecutablePath != PathTool.GetRelative("Install", "UpTool2.dll"))
Splash.Invoke((Action)(() => MessageBox.Show(Splash, $"WARNING!{Environment.NewLine}Running from outside the install directory is not recommended!")));
if (!Directory.Exists(PathTool.GetRelative("Apps")))
Directory.CreateDirectory(PathTool.GetRelative("Apps"));
try
{
Lib.V2.UpdateChecker.Check();
Online = true;
}
catch
{
Online = false;
}
if (!Directory.Exists(Lib.V1.PathTool.GetRelative("Apps")))
Directory.CreateDirectory(Lib.V1.PathTool.GetRelative("Apps"));
if (!Online)
SetSplash(7, "Opening");
if (!Online || UpdateCheck(metaXml))
if (!Online || UpdateCheck())
Application.Run(new MainForm());
#if !DEBUG
}
@ -78,7 +71,7 @@ namespace UpTool2
{
try
{
Splash.Invoke((Action)Splash.Hide);
Splash.Invoke((Action) Splash.Hide);
}
catch
{
@ -88,8 +81,7 @@ namespace UpTool2
}
finally
{
if (hasHandle)
mutex.ReleaseMutex();
Lib.Dispose();
}
#endif
}
@ -114,52 +106,40 @@ namespace UpTool2
{
Graphics g = e.Graphics;
//Draw background
Brush[] brushes = {Brushes.Purple, Brushes.MediumPurple, Brushes.Indigo, Brushes.Fuchsia, Brushes.OrangeRed};
Brush[] brushes =
{Brushes.Purple, Brushes.MediumPurple, Brushes.Indigo, Brushes.Fuchsia, Brushes.OrangeRed};
const int barWidth = 50;
const int topOffset = 100;
for (int i = 0; i < Splash.Width + topOffset; i += barWidth)
{
g.FillPolygon(brushes[(i / barWidth) % brushes.Length], new []
g.FillPolygon(brushes[i / barWidth % brushes.Length], new[]
{
new PointF(i, 0),
new PointF(i + barWidth, 0),
new PointF(i, Splash.Height),
new PointF(i - topOffset, Splash.Height)
});
}
//Draw Text: UpTool2 (by JFronny)^
Font font = new Font(FontFamily.GenericSansSerif, 40, FontStyle.Bold);
const string text = "UpTool2";
SizeF size = g.MeasureString(text, font);
RectangleF rect = new RectangleF((Splash.Width / 2f) - (size.Width / 2), (Splash.Height / 2f) - (size.Height / 2), size.Width, size.Height);
RectangleF rect = new RectangleF(Splash.Width / 2f - size.Width / 2,
Splash.Height / 2f - size.Height / 2, size.Width, size.Height);
g.DrawString(text, font, Brushes.White, rect);
Font smallFont = new Font(FontFamily.GenericSansSerif, 10);
const string subtitle = "by JFronny";
SizeF size2 = g.MeasureString(subtitle, smallFont);
g.DrawString(subtitle, smallFont, Brushes.White, new RectangleF(rect.Right - size2.Width, rect.Bottom - size2.Height, size2.Width, size2.Height));
g.DrawString(subtitle, smallFont, Brushes.White,
new RectangleF(rect.Right - size2.Width, rect.Bottom - size2.Height, size2.Width, size2.Height));
//Draw progress bar
Rectangle bar = new Rectangle((3 * Splash.Width) / 8, ((Splash.Height * 3) / 4) - 10, Splash.Width / 4, 20);
Rectangle bar = new Rectangle(3 * Splash.Width / 8, Splash.Height * 3 / 4 - 10, Splash.Width / 4,
20);
g.FillRectangle(Brushes.Gray, bar);
g.FillRectangle(Brushes.Black, new Rectangle(bar.X, bar.Y, (bar.Width * SplashProgress) / 10, bar.Height));
g.FillRectangle(Brushes.Black,
new Rectangle(bar.X, bar.Y, bar.Width * _splashProgress / 10, bar.Height));
g.DrawRectangle(Pens.DimGray, bar);
//g.DrawString(SplashMessage, smallFont, Brushes.White, new PointF(bar.Left, bar.Bottom));
g.DrawString(SplashMessage, smallFont, Brushes.White, bar, new StringFormat {Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center});
};
int xOff = 0;
int yOff = 0;
bool moving = false;
Splash.MouseDown += (sender, e) =>
{
moving = true;
xOff = e.X;
yOff = e.Y;
};
Splash.MouseUp += (sender, e) => moving = false;
Splash.MouseMove += (sender, e) =>
{
if (!moving) return;
Splash.Left = Cursor.Position.X - xOff;
Splash.Top = Cursor.Position.Y - yOff;
g.DrawString(_splashMessage, smallFont, Brushes.White, bar,
new StringFormat {Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center});
};
Splash.Load += (sender, e) => Splash.BringToFront();
Splash.FormClosed += (sender, e) => Splash.Dispose();
@ -167,9 +147,10 @@ namespace UpTool2
public static void SetSplash(int progress, string status) => Splash.Invoke(new Action(() =>
{
SplashProgress = progress;
Console.WriteLine(status);
SplashMessage = status;
Console.WriteLine($"{progress} - {status}");
Debug.WriteLine($"{progress} - {status}");
_splashProgress = progress;
_splashMessage = status;
Splash.Invoke((Action) Splash.Invalidate);
}));
@ -177,59 +158,29 @@ namespace UpTool2
{
try
{
if (!File.Exists(PathTool.InfoXml) || XDocument.Load(PathTool.InfoXml).Element("meta") == null)
new XElement("meta").Save(PathTool.InfoXml);
XDocument x = XDocument.Load(PathTool.InfoXml);
XElement meta = x.Element("meta");
if (meta.Element("UpdateSource") == null)
meta.Add(new XElement("UpdateSource"));
if (new[]
{
"",
"https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Meta.xml",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Meta.xml"
}
.Contains(meta.Element("UpdateSource").Value))
meta.Element("UpdateSource").Value =
"https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml";
if (meta.Element("Repos") == null)
meta.Add(new XElement("Repos"));
if (meta.Element("Repos").Elements("Repo").Count() == 0)
meta.Element("Repos").Add(new XElement("Repo", new XElement("Name", "UpTool2 official Repo"),
new XElement("Link",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml")));
meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link"))
.Where(s => new[]
{
null, "https://github.com/JFronny/UpTool2/releases/download/Repo/Repo.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Repo.xml"
}.Contains(s.Value))
.ToList().ForEach(s =>
s.Value =
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml");
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
x.Save(PathTool.InfoXml);
Lib.V1.XmlTool.FixXml();
}
catch (XmlException)
{
if (throwOnError) throw;
MessageBox.Show("Something went wrong while trying to parse XML. Retrying...");
File.Delete(PathTool.InfoXml);
File.Delete(Lib.V1.PathTool.InfoXml);
FixXml();
}
}
private static bool UpdateCheck(string metaXml)
private static bool UpdateCheck()
{
UpdateCheck check = Lib.V2.UpdateChecker.Check();
SetSplash(3, "Comparing online version");
XElement meta = XDocument.Load(metaXml).Element("meta");
if (Assembly.GetExecutingAssembly().GetName().Version >= Version.Parse(meta.Element("Version").Value))
if (Assembly.GetExecutingAssembly().GetName().Version >= check.OnlineVersion)
{
SetSplash(7, "Opening");
return true;
}
byte[] dl;
SetSplash(4, "Downloading latest");
using (DownloadDialog dlg = new DownloadDialog(meta.Element("File").Value))
using (DownloadDialog dlg = new DownloadDialog(check.Installer.AbsoluteUri))
{
if (dlg.ShowDialog() != DialogResult.OK)
throw new Exception("Failed to update");
@ -239,45 +190,30 @@ namespace UpTool2
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty).ToUpper();
if (pkgHash != meta.Element("Hash").Value.ToUpper())
throw new Exception("The hash is not equal to the one stored in the repo:\r\nPackage: " + pkgHash +
"\r\nOnline: " + meta.Element("Hash").Value.ToUpper());
if (pkgHash != check.InstallerHash)
throw new Exception(
$"The hash is not equal to the one stored in the repo:\r\nPackage: {pkgHash}\r\nOnline: {check.InstallerHash}");
}
SetSplash(9, "Installing");
if (Directory.Exists(PathTool.GetRelative("Install", "tmp")))
Directory.Delete(PathTool.GetRelative("Install", "tmp"), true);
Directory.CreateDirectory(PathTool.GetRelative("Install", "tmp"));
if (Directory.Exists(Lib.V1.PathTool.GetRelative("Install", "tmp")))
Directory.Delete(Lib.V1.PathTool.GetRelative("Install", "tmp"), true);
Directory.CreateDirectory(Lib.V1.PathTool.GetRelative("Install", "tmp"));
using (MemoryStream ms = new MemoryStream(dl))
{
using ZipArchive ar = new ZipArchive(ms);
ar.ExtractToDirectory(PathTool.GetRelative("Install", "tmp"), true);
ar.ExtractToDirectory(Lib.V1.PathTool.GetRelative("Install", "tmp"), true);
}
Splash.Hide();
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = @"/C timeout /t 2 & xcopy /s /e /y tmp\* .",
FileName = Lib.V1.PathTool.GetRelative("Install", "tmp", "Installer.exe"),
Arguments = "i -p",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = PathTool.GetRelative("Install")
WorkingDirectory = Lib.V1.PathTool.GetRelative("Install")
});
SetSplash(7, "Installing");
return false;
}
private static bool Ping(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
}
}

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UpTool2")]
[assembly: AssemblyDescription("Download and update applications from UpTool repos")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("JFronny")]
[assembly: AssemblyProduct("UpTool2")]
[assembly: AssemblyCopyright("Copyright © JFronny 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c0c1e002-9e13-4e8f-a035-dbdc5128e00e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.1.0")]

View File

@ -21,20 +21,16 @@
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForms));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpTool2.SettingsForms));
this.sourceGrid = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.sourceGrid)).BeginInit();
((System.ComponentModel.ISupportInitialize) (this.sourceGrid)).BeginInit();
this.SuspendLayout();
//
// sourceGrid
//
this.sourceGrid.BackgroundColor = System.Drawing.Color.White;
this.sourceGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.sourceGrid.Dock = System.Windows.Forms.DockStyle.Fill;
@ -44,28 +40,24 @@
this.sourceGrid.Name = "sourceGrid";
this.sourceGrid.Size = new System.Drawing.Size(933, 519);
this.sourceGrid.TabIndex = 0;
//
// SettingsForms
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(933, 519);
this.Controls.Add(this.sourceGrid);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
this.Name = "SettingsForms";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Sources";
this.TopMost = true;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SettingsForms_FormClosing);
((System.ComponentModel.ISupportInitialize)(this.sourceGrid)).EndInit();
((System.ComponentModel.ISupportInitialize) (this.sourceGrid)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView sourceGrid;
#endregion
private System.Windows.Forms.DataGridViewTextBoxColumn sbName;
private System.Windows.Forms.DataGridViewTextBoxColumn sbLink;
}

View File

@ -1,34 +1,27 @@
using System.Windows.Forms;
using System.Xml.Linq;
using UpTool2.Tool;
using System.Collections.Generic;
using System.Windows.Forms;
using UpToolLib.DataStructures;
namespace UpTool2
{
public partial class SettingsForms : Form
{
private readonly XDocument doc;
private readonly XElement meta;
private readonly XElement repos;
private readonly List<Repo> _repos = new List<Repo>();
public SettingsForms()
{
InitializeComponent();
Program.FixXml();
doc = XDocument.Load(PathTool.InfoXml);
meta = doc.Element("meta");
repos = meta.Element("Repos");
foreach (XElement repo in repos.Elements("Repo"))
sourceGrid.Rows.Add(repo.Element("Name").Value, repo.Element("Link").Value);
_repos.AddRange(Program.Lib.V2.RepoManagement.GetRepos());
sourceGrid.Columns.Clear();
sourceGrid.Columns.Add("name", "Name");
sourceGrid.Columns.Add("link", "Link");
foreach (Repo repo in _repos)
sourceGrid.Rows.Add(repo.Name, repo.Url);
}
private void SettingsForms_FormClosing(object sender, FormClosingEventArgs e)
{
repos.RemoveNodes();
for (int y = 0; y < sourceGrid.Rows.Count; y++)
if (y + 1 < sourceGrid.Rows.Count)
repos.Add(new XElement("Repo", new XElement("Name", (string) sourceGrid.Rows[y].Cells[0].Value),
new XElement("Link", (string) sourceGrid.Rows[y].Cells[1].Value)));
doc.Save(PathTool.InfoXml);
Program.Lib.V2.RepoManagement.Save(_repos);
}
}
}

32
UpTool2/TaskPreview.cs Normal file
View File

@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using UpToolLib.v2.TaskQueue;
namespace UpTool2
{
internal static class TaskPreview
{
public static bool Show(ref List<AppTask> tasks, bool showOk)
{
bool ok = false;
using Form tmp = new Form {Size = new Size(600, 300), MinimumSize = new Size(300, showOk ? 138 : 133)};
using CheckedListBox list = new CheckedListBox {Dock = DockStyle.Fill};
using Button okButton = new Button {Dock = DockStyle.Bottom, Text = "OK"};
list.Items.AddRange(tasks.ToArray());
for (int i = 0; i < tasks.Count; i++)
list.SetItemChecked(i, true);
tmp.Controls.Add(list);
okButton.Click += (sender, args) =>
{
ok = true;
tmp.Close();
};
if (showOk) tmp.Controls.Add(okButton);
tmp.ShowDialog();
tasks = list.Items.OfType<AppTask>().Where((s, i) => list.GetItemChecked(i)).ToList();
return !showOk || ok;
}
}
}

View File

@ -1,117 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.Xml.Linq;
using UpTool2.DataStructures;
namespace UpTool2.Tool
{
internal static class AppInstall
{
public static void Install(App appI)
{
string app = "";
string tmp = "";
#if !DEBUG
try
{
#endif
app = appI.appPath;
tmp = PathTool.tempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
if (Directory.Exists(app))
Directory.Delete(app, true);
Directory.CreateDirectory(app);
using DownloadDialog dlg = new DownloadDialog(appI.File);
if (dlg.ShowDialog() != DialogResult.OK)
throw new Exception("Download failed");
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlg.Result)).Replace("-", string.Empty)
.ToUpper();
if (pkgHash != appI.Hash.ToUpper())
throw new Exception($@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {appI.Hash.ToUpper()}");
}
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlg.Result);
CompleteInstall(appI);
#if !DEBUG
}
catch
{
if (Directory.Exists(app))
Directory.Delete(app, true);
throw;
}
finally
{
#endif
if (tmp != "" && Directory.Exists(tmp))
Directory.Delete(tmp, true);
#if !DEBUG
}
#endif
}
public static void InstallZip(string zipPath, App meta)
{
string app = "";
string tmp = "";
try
{
app = meta.appPath;
Directory.CreateDirectory(app);
tmp = PathTool.tempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
File.Copy(zipPath, Path.Combine(app, "package.zip"));
CompleteInstall(meta);
}
catch
{
if (Directory.Exists(app))
Directory.Delete(app, true);
throw;
}
finally
{
if (tmp != "" && Directory.Exists(tmp))
Directory.Delete(tmp, true);
}
}
//Use
//PowerShell -Command "Add-Type -AssemblyName PresentationFramework;[System.Windows.MessageBox]::Show('Hello World')"
//for message boxes
private static void CompleteInstall(App app) => CompleteInstall(app.appPath, app.Name, app.Description, app.Version, app.MainFile);
private static void CompleteInstall(string appPath, string name, string description, Version version, string mainFile)
{
string tmp = PathTool.tempPath;
ZipFile.ExtractToDirectory(Path.Combine(appPath, "package.zip"), tmp);
Directory.Move(Path.Combine(tmp, "Data"), Path.Combine(appPath, "app"));
XElement el = new XElement("app", new XElement("Name", name), new XElement("Description", description),
new XElement("Version", version));
if (mainFile != null)
el.Add(new XElement(new XElement("MainFile", mainFile)));
el.Save(Path.Combine(appPath, "info.xml"));
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C \"{Path.Combine(tmp, "Install.bat")}\"",
WorkingDirectory = Path.Combine(appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
if (GlobalVariables.RelE)
GlobalVariables.ReloadElements.Invoke();
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace UpTool2.Tool
{
internal static class PathTool
{
public static string dir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UpTool2");
public static string tempPath => GetRelative("tmp");
public static string appsPath => GetRelative("Apps");
public static string InfoXml => GetRelative("info.xml");
public static string GetRelative(params string[] segments) =>
Path.Combine(new[] {dir}.Concat(segments).ToArray());
public static string GetAppPath(Guid app) => Path.Combine(appsPath, app.ToString());
public static string GetDataPath(Guid app) => Path.Combine(GetAppPath(app), "app");
public static string GetInfoPath(Guid app) => Path.Combine(GetAppPath(app), "info.xml");
}
}

View File

@ -1,177 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Xml.Linq;
using CC_Functions.Misc;
using UpTool2.DataStructures;
using UpTool2.Properties;
namespace UpTool2.Tool
{
internal static class RepoManagement
{
public static void FetchRepos()
{
Program.FixXml();
XElement meta = XDocument.Load(PathTool.InfoXml).Element("meta");
List<XElement> tmpAppsList = new List<XElement>();
List<string> repArr = meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link").Value).Distinct()
.ToList();
using (WebClient client = new WebClient())
{
int i = 0;
while (i < repArr.Count)
{
#if !DEBUG
try
{
#endif
XDocument repo = XDocument.Load(new Uri(repArr[i]).Unshorten().AbsoluteUri);
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
.Where(s => !repArr.Contains(s)));
XElement[] tmp_apparray = repo.Element("repo").Elements("app").Where(app =>
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
!tmpAppsList
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
GetVer(a.Element("Version")) >= app.Element("Version").GetVer())).ToArray()
.Concat(repo.Element("repo").Elements("applink")
.Select(s => XDocument.Load(new Uri(s.Value).Unshorten().AbsoluteUri).Element("app")))
.ToArray();
for (int i1 = 0; i1 < tmp_apparray.Length; i1++)
{
XElement app = tmp_apparray[i1];
//"Sanity check"
Version.Parse(app.Element("Version").Value);
Guid.Parse(app.Element("ID").Value);
//Create XElement
tmpAppsList.Add(new XElement("App",
new XElement("Name", app.Element("Name").Value),
new XElement("Description", app.Element("Description").Value),
new XElement("Version", app.Element("Version").Value),
new XElement("ID", app.Element("ID").Value),
new XElement("File", app.Element("File").Value),
new XElement("Hash", app.Element("Hash").Value)
));
if (app.Element("MainFile") != null)
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
if (app.Element("Icon") != null)
try
{
//Scale Image and save as Base64
Image src = Image.FromStream(
client.OpenRead(new Uri(app.Element("Icon").Value).Unshorten()));
Bitmap dest = new Bitmap(70, 70);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
using (Graphics g = Graphics.FromImage(dest))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using ImageAttributes wrapMode = new ImageAttributes();
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
GraphicsUnit.Pixel, wrapMode);
}
using MemoryStream ms = new MemoryStream();
dest.Save(ms, ImageFormat.Png);
tmpAppsList.Last()
.Add(new XElement("Icon", Convert.ToBase64String(ms.ToArray())));
}
catch
{
}
if (tmpAppsList.Count(a => a.Element("ID").Value == app.Element("ID").Value) > 1)
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse()
.Skip(1)
.ToList().ForEach(a => tmpAppsList.Remove(a));
}
#if !DEBUG
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Failed to load repo: " + repArr[i]);
}
#endif
i++;
}
}
tmpAppsList.Sort((x, y) =>
string.Compare(x.Element("Name").Value, y.Element("Name").Value, StringComparison.Ordinal));
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
XElement repos = meta.Element("LocalRepo");
repos.RemoveNodes();
tmpAppsList.ForEach(app => repos.Add(app));
meta.Save(PathTool.InfoXml);
}
private static Version GetVer(this XElement el) =>
int.TryParse(el.Value, out int i) ? new Version(0, 0, 0, i) : Version.Parse(el.Value);
public static void GetReposFromDisk()
{
GlobalVariables.Apps.Clear();
string xml = PathTool.InfoXml;
XDocument.Load(xml).Element("meta").Element("LocalRepo").Elements().ToList().ForEach(app =>
{
Guid id = Guid.Parse(app.Element("ID").Value);
string locInPath = PathTool.GetInfoPath(id);
XElement locIn = File.Exists(locInPath) ? XDocument.Load(locInPath).Element("app") : app;
if (int.TryParse(app.Element("Version").Value, out _))
app.Element("Version").Value = GlobalVariables.minimumVer.ToString();
GlobalVariables.Apps.Add(id, new App(
locIn.Element("Name").Value,
locIn.Element("Description").Value,
Version.Parse(app.Element("Version").Value),
app.Element("File").Value,
false,
app.Element("Hash").Value,
id,
Color.White,
app.Element("Icon") == null
? Resources.C_64.ToBitmap()
: (Bitmap) new ImageConverter().ConvertFrom(
Convert.FromBase64String(app.Element("Icon").Value)),
locIn.Element("MainFile") != null || app.Element("MainFile") != null,
locIn.Element("MainFile") == null
? app.Element("MainFile") == null ? "" : app.Element("MainFile").Value
: locIn.Element("MainFile").Value
));
});
Directory.GetDirectories(PathTool.appsPath)
.Where(s => Guid.TryParse(Path.GetFileName(s), out Guid guid) &&
!GlobalVariables.Apps.ContainsKey(guid)).ToList().ForEach(s =>
{
Guid tmp = Guid.Parse(Path.GetFileName(s));
try
{
XElement data = XDocument.Load(PathTool.GetInfoPath(tmp)).Element("app");
GlobalVariables.Apps.Add(tmp,
new App("(local) " + data.Element("Name").Value, data.Element("Description").Value,
GlobalVariables.minimumVer, "", true, "", tmp, Color.Red, Resources.C_64.ToBitmap(),
data.Element("MainFile") != null,
data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
catch (Exception e)
{
if (MessageBox.Show($@"An error occured while loading this local repo:
{e.Message}
Do you want to exit? Otherwise the folder will be deleted, possibly causeing problems later.", "",
MessageBoxButtons.YesNo) == DialogResult.No)
Directory.Delete(PathTool.GetAppPath(tmp), true);
else
Environment.Exit(0);
}
});
}
}
}

60
UpTool2/UTLibFunctions.cs Normal file
View File

@ -0,0 +1,60 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Windows.Forms;
using UpTool2.Properties;
using UpTool2.Tool;
using UpToolLib.DataStructures;
namespace UpTool2
{
internal class UtLibFunctions : IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link)
{
using DownloadDialog dialog = new DownloadDialog(link.AbsoluteUri);
bool success = dialog.ShowDialog() == DialogResult.OK;
return new Tuple<bool, byte[]>(success, success ? dialog.Result : null);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new WebClient();
Image src = Image.FromStream(
client.OpenRead(link));
Bitmap dest = new Bitmap(70, 70);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
using (Graphics g = Graphics.FromImage(dest))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using ImageAttributes wrapMode = new ImageAttributes();
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
GraphicsUnit.Pixel, wrapMode);
}
using MemoryStream ms = new MemoryStream();
dest.Save(ms, ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool _) =>
MessageBox.Show(text, "", MessageBoxButtons.YesNo) == DialogResult.Yes;
public void OkDialog(string text) => MessageBox.Show(text);
public object GetDefaultIcon() => Resources.C_64.ToBitmap();
public object ImageFromB64(string b64) =>
(Bitmap) new ImageConverter().ConvertFrom(Convert.FromBase64String(b64));
public void Log(string text)
{
}
}
}

View File

@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<LangVersion>latest</LangVersion>
<LangVersion>8</LangVersion>
<Deterministic>false</Deterministic>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<Deterministic>false</Deterministic>
<AssemblyVersion>1.0.*</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@ -19,6 +20,6 @@
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CC-Functions.Misc" Version="1.1.7384.27745" />
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using System.Reflection;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace UpToolCLI
{
public static class CacheManagement
{
public static void RegisterCommands(RootCommand rootCommand)
{
rootCommand.AddCommand(new Command("list", "Lists installed packages")
{
Handler = CommandHandler.Create(List)
});
Command search = new("search", "Search for packages")
{
new Argument<string>("identifier", "Something to identify the app")
};
search.Handler = CommandHandler.Create<string>(Search);
rootCommand.AddCommand(search);
Command show = new("show", "Shows package info")
{
new Argument<string>("identifier", "Something to identify the app")
};
show.Handler = CommandHandler.Create<string>(Show);
rootCommand.AddCommand(show);
rootCommand.AddCommand(new Command("update", "Updates the cache")
{
Handler = CommandHandler.Create(Update)
});
}
private static void List()
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
Console.WriteLine(Program.Lib.V1.Apps.Where(s => s.Value.Status.Contains(Status.Installed))
.ToStringTable(new[]
{
"Name", "State", "Guid"
},
u => u.Value.Name,
u => u.Value.Local ? "Local" :
u.Value.Status.Contains(Status.Updatable) ? "Updatable" : "None",
u => u.Key));
}
private static void Search(string identifier)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
Console.WriteLine($"Found {apps.Length} app(s)");
if (apps.Length > 0)
Console.WriteLine(apps.ToStringTable(new[]
{
"Name", "Guid"
},
u => u.Name,
u => u.Id));
}
private static void Show(string identifier)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
Console.WriteLine(apps.First());
}
private static void Update()
{
Console.WriteLine("Fetching Repos...");
Program.Lib.V2.RepoManagement.FetchRepos();
Program.Lib.V2.RepoManagement.GetReposFromDisk();
Console.WriteLine();
IEnumerable<App> tmp = Program.Lib.V1.Apps.Where(s =>
s.Value.Status.Contains(Status.Updatable)).Select(s => s.Value);
IEnumerable<App> apps = tmp as App[] ?? tmp.ToArray();
int updatableCount = apps.Count();
Console.WriteLine(updatableCount == 0
? "All up-to-date"
: $@"Found {updatableCount} Updates:
{string.Join(Environment.NewLine, apps.Select(s => $"- {s.Name} ({s.Version})"))}");
Version vLocal = Assembly.GetExecutingAssembly().GetName().Version;
Version vOnline = Program.Lib.V2.UpdateChecker.Check().OnlineVersion;
if (vLocal < vOnline)
Console.WriteLine($"uptool is outdated ({vLocal} vs {vOnline}), update using \"uptool upgrade-self\"");
}
}
}

104
UpToolCLI/Other.cs Normal file
View File

@ -0,0 +1,104 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
using Process = System.Diagnostics.Process;
namespace UpToolCLI
{
public class Other
{
public static void RegisterCommands(RootCommand rootCommand)
{
Command command = new("upgrade-self", "Upgrades UpToolCLI")
{
new Option<bool>(new[] {"--force", "-f"}, "Overwrites older files")
};
command.Handler = CommandHandler.Create<bool>(UpgradeSelf);
rootCommand.AddCommand(command);
Command start = new("start", "Starts an app")
{
new Argument<string>("identifier", "Something to identify the app"),
new Option<string>(new[] {"--arguments", "--args", "-a"}, () => "", "The arguments to run the file with"),
new Option<string>(new[] {"--file", "-f"}, () => null, "The file to run instead of the MainFile"),
new Option<bool>(new[] {"--waitForExit", "-wait"}, "Waits until the program quits")
};
start.Handler = CommandHandler.Create<string, string, string, bool>(Start);
rootCommand.AddCommand(start);
}
public static void UpgradeSelf(bool force)
{
PathTool pathTool = Program.Lib.V1.PathTool;
UpdateCheck updateCheck = Program.Lib.V2.UpdateChecker.Check();
if (!force && Assembly.GetExecutingAssembly().GetName().Version >= updateCheck.OnlineVersion)
Console.WriteLine("Already up-to-date");
else
{
Console.WriteLine("Downloading latest");
(bool success, byte[] dl) = Program.Functions.Download(updateCheck.Installer);
if (!success)
throw new Exception("Failed to update");
Console.WriteLine("Verifying");
using (SHA256CryptoServiceProvider sha256 = new())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty).ToUpper();
if (pkgHash != updateCheck.InstallerHash)
throw new Exception($@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {updateCheck.InstallerHash}");
}
Console.WriteLine("Installing");
if (Directory.Exists(pathTool.GetRelative("Install", "tmp")))
Directory.Delete(pathTool.GetRelative("Install", "tmp"), true);
Directory.CreateDirectory(pathTool.GetRelative("Install", "tmp"));
using (MemoryStream ms = new(dl))
{
using ZipArchive ar = new(ms);
ar.ExtractToDirectory(pathTool.GetRelative("Install", "tmp"), true);
}
string file = pathTool.GetRelative("Install", "tmp", "Installer.exe");
Console.WriteLine($"Starting {file}");
Process.Start(new ProcessStartInfo
{
FileName = file,
Arguments = "i",
WorkingDirectory = pathTool.GetRelative("Install"),
UseShellExecute = false
});
}
}
private static void Start(string identifier, string arguments, string file, bool waitForExit)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if (tmp.Runnable)
{
Console.WriteLine($"Starting {tmp.Name}");
Process tmp1 = Program.Lib.V1.AppExtras.RunApp(tmp, file ?? tmp.MainFile, arguments);
if (waitForExit)
tmp1.WaitForExit();
}
else
Console.WriteLine($"{tmp.Name} is not runnable");
}
Console.WriteLine("Done!");
}
}
}

View File

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.v1;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace UpToolCLI
{
public static class PackageManagement
{
public static void RegisterCommands(RootCommand rootCommand)
{
Command install = new("install", "Install a package")
{
new Argument<string>("identifier", "Something to identify the app or the file name"),
new Option<bool>(new[] {"--force", "-f"}, "Overwrites older files")
};
install.Handler = CommandHandler.Create<string, bool>(Install);
rootCommand.AddCommand(install);
Command upgrade = new("upgrade", "Upgrade a package")
{
new Argument<string>("identifier", "Something to identify the app"),
new Option<bool>(new[] {"--force", "-f"}, "Overwrites older files")
};
upgrade.Handler = CommandHandler.Create<string, bool>(Upgrade);
rootCommand.AddCommand(upgrade);
Command reinstall = new("reinstall", "Reinstall a package")
{
new Argument<string>("identifier", "Something to identify the app"),
new Option<bool>(new[] {"--force", "-f"}, "Overwrites older files")
};
reinstall.Handler = CommandHandler.Create<string, bool>(Reinstall);
rootCommand.AddCommand(reinstall);
Command remove = new("remove", "Remove a package")
{
new Argument<string>("identifier", "Something to identify the app")
};
remove.Handler = CommandHandler.Create<string>(Remove);
rootCommand.AddCommand(remove);
Command purge = new("purge", "Completely remove a package")
{
new Argument<string>("identifier", "Something to identify the app")
};
purge.Handler = CommandHandler.Create<string>(Purge);
rootCommand.AddCommand(purge);
rootCommand.AddCommand(new Command("dist-upgrade", "Upgrades all packages")
{
Handler = CommandHandler.Create(DistUpgrade)
});
}
private static void Install(string identifier, bool force)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
{
if (File.Exists(identifier))
{
Console.WriteLine("Name:");
string name = Console.ReadLine();
Program.Lib.V1.Installer.InstallZip(identifier, Program.Lib.V2.AppFactory.CreateApp(name, "Locally installed package, removal only",
UpToolLibV1.MinimumVer, "", true, "",
Guid.NewGuid(), Color.Red, "", false, ""), force);
Console.WriteLine($"Successfully installed \"{name}\"");
}
else
{
Console.WriteLine("Package not found.");
Console.WriteLine(identifier);
}
}
else
{
App tmp = apps.First();
if (tmp.Status.Contains(Status.Installed))
Console.WriteLine("Package is already installed");
else
{
Console.WriteLine($"Installing {tmp.Name}");
Program.Lib.V1.Installer.Install(tmp, true);
}
}
Console.WriteLine("Done!");
}
private static void Upgrade(string identifier, bool force)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if (tmp.Status.Contains(Status.Updatable))
{
Console.WriteLine($"Upgrading {tmp.Name}");
Program.Lib.V1.AppExtras.Update(tmp, force);
}
else
Console.WriteLine("Package is up-to-date");
}
Console.WriteLine("Done!");
}
private static void Reinstall(string identifier, bool force)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
Console.WriteLine($"Reinstalling {tmp.Name}");
Program.Lib.V1.AppExtras.Update(tmp, force);
}
Console.WriteLine("Done!");
}
private static void Remove(string identifier)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if (tmp.Status.Contains(Status.Installed))
{
Console.WriteLine($"Removing {tmp.Name}");
Program.Lib.V1.AppExtras.Remove(tmp, false);
}
else
Console.WriteLine("Package is not installed");
}
Console.WriteLine("Done!");
}
private static void Purge(string identifier)
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
App[] apps = Program.Lib.V1.AppExtras.FindApps(identifier);
if (apps.Length == 0)
Console.WriteLine("Package not found.");
else
{
App tmp = apps.First();
if (tmp.Status.Contains(Status.Installed))
{
Console.WriteLine($"Purging {tmp.Name}");
Program.Lib.V1.AppExtras.Remove(tmp, true);
}
else
Console.WriteLine("Package is not installed");
}
Console.WriteLine("Done!");
}
private static void DistUpgrade()
{
Program.Lib.V2.RepoManagement.GetReposFromDisk();
foreach (KeyValuePair<Guid, App> app in Program.Lib.V1.Apps.Where(s =>
s.Value.Status.Contains(Status.Updatable)))
{
Console.WriteLine($"Updating {app.Value.Name}");
Program.Lib.V1.AppExtras.Update(app.Value, false);
}
if (Assembly.GetExecutingAssembly().GetName().Version < Program.Lib.V2.UpdateChecker.Check().OnlineVersion)
{
Console.WriteLine("Updating self");
Other.UpgradeSelf(false);
}
Console.WriteLine("Done!");
}
}
}

41
UpToolCLI/Program.cs Normal file
View File

@ -0,0 +1,41 @@
using System;
using System.CommandLine;
using UpToolLib;
namespace UpToolCLI
{
public static class Program
{
public static readonly UtLibFunctions Functions = new();
public static bool Basic;
public static UpToolLibMain Lib;
public static int Main(string[] args)
{
try
{
Basic = args.Length > 0 && args[0].ToLower() == "--basic";
Lib = new UpToolLibMain(Functions);
Lib.V1.XmlTool.FixXml();
RootCommand rootCommand = new();
rootCommand.AddGlobalOption(new Option<bool>("--basic", "Use only basic console functionality. Must be the first parameter in the call"));
PackageManagement.RegisterCommands(rootCommand);
CacheManagement.RegisterCommands(rootCommand);
ReposManagement.RegisterCommands(rootCommand);
Other.RegisterCommands(rootCommand);
return rootCommand.InvokeAsync(args).Result;
}
catch (Exception e)
{
Console.WriteLine($"FAILED: {e}");
return 1;
}
finally
{
Lib?.Dispose();
}
}
}
}

View File

@ -0,0 +1,93 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using System.Xml.Linq;
using UpToolLib.v1.Tool;
namespace UpToolCLI
{
public class ReposManagement
{
private static string InfoXml => Program.Lib.V1.PathTool.InfoXml;
public static void RegisterCommands(RootCommand rootCommand)
{
rootCommand.AddCommand(new Command("list-repo", "Lists current repositories")
{
Handler = CommandHandler.Create(ListRepo)
});
Command addRepo = new("add-repo", "Adds a repository")
{
new Argument<string>("name", "The new repositories name"),
new Argument<string>("link", "A link to the repositories XML")
};
addRepo.Handler = CommandHandler.Create<string, string>(AddRepo);
rootCommand.AddCommand(addRepo);
Command removeRepo = new("remove-repo", "Removes a repository")
{
new Argument<string>("name", "The repositories name")
};
removeRepo.Handler = CommandHandler.Create<string>(RemoveRepo);
rootCommand.AddCommand(removeRepo);
}
private static void ListRepo()
{
XDocument doc = XDocument.Load(InfoXml);
XElement repos = doc.Element("meta").Element("Repos");
Console.WriteLine("Current repos:");
Console.WriteLine(repos.Elements("Repo").ToStringTable(new[]
{
"Name", "Link"
},
u => u.Element("Name").Value,
u => u.Element("Link").Value));
}
private static void AddRepo(string name, string link)
{
XDocument doc = XDocument.Load(InfoXml);
XElement repos = doc.Element("meta").Element("Repos");
repos.Add(new XElement("Repo", new XElement("Name", name),
new XElement("Link", link)));
doc.Save(InfoXml);
Console.WriteLine("Added repo. Remember to update the cache using \"uptool update\"");
}
private static void RemoveRepo(string name)
{
XDocument doc = XDocument.Load(InfoXml);
XElement repos = doc.Element("meta").Element("Repos");
XElement[] sRepos = repos.Elements("Repo")
.Where(s => s.Element("Name").Value.ToLower().StartsWith(name.ToLower())).ToArray();
switch (sRepos.Length)
{
case 0:
Console.WriteLine("No repo was found that matches your input!");
return;
case 1:
break;
default:
Console.WriteLine("Found multiple repos that match your input:");
Console.WriteLine(sRepos.ToStringTable(new[]
{
"Name", "Link"
},
u => u.Element("Name").Value,
u => u.Element("Link").Value));
if (!Program.Functions.YesNoDialog("Are you sure you want to delete them all?", false))
return;
break;
}
foreach (XElement t in sRepos)
{
Console.WriteLine($"Removing {t.Element("Name").Value}");
t.Remove();
}
doc.Save(InfoXml);
Console.WriteLine("Removed repo. Remember to update the cache using \"uptool update\"");
}
}
}

104
UpToolCLI/TableParser.cs Normal file
View File

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace UpToolCLI
{
public static class TableParser
{
public static string ToStringTable<T>(this IEnumerable<T> values, string[] columnHeaders,
params Func<T, object>[] valueSelectors) => ToStringTable(values.ToArray(), columnHeaders, valueSelectors);
public static string ToStringTable<T>(this T[] values, string[] columnHeaders,
params Func<T, object>[] valueSelectors)
{
Debug.Assert(columnHeaders.Length == valueSelectors.Length);
string[,] arrValues = new string[values.Length + 1, valueSelectors.Length];
// Fill headers
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
arrValues[0, colIndex] = columnHeaders[colIndex];
// Fill table rows
for (int rowIndex = 1; rowIndex < arrValues.GetLength(0); rowIndex++)
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
{
object value = valueSelectors[colIndex].Invoke(values[rowIndex - 1]);
arrValues[rowIndex, colIndex] = value != null ? value.ToString() : "null";
}
return ToStringTable(arrValues);
}
public static string ToStringTable(this string[,] arrValues)
{
int[] maxColumnsWidth = GetMaxColumnsWidth(arrValues);
string headerSpliter = new('-', maxColumnsWidth.Sum(i => i + 3) - 1);
StringBuilder sb = new();
for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
{
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
{
// Print cell
string cell = arrValues[rowIndex, colIndex];
cell = cell.PadRight(maxColumnsWidth[colIndex]);
sb.Append(" | ");
sb.Append(cell);
}
// Print end of line
sb.Append(" | ");
sb.AppendLine();
// Print splitter
if (rowIndex == 0)
{
sb.AppendFormat(" |{0}| ", headerSpliter);
sb.AppendLine();
}
}
return sb.ToString();
}
private static int[] GetMaxColumnsWidth(string[,] arrValues)
{
int[] maxColumnsWidth = new int[arrValues.GetLength(1)];
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
{
int newLength = arrValues[rowIndex, colIndex].Length;
int oldLength = maxColumnsWidth[colIndex];
if (newLength > oldLength) maxColumnsWidth[colIndex] = newLength;
}
return maxColumnsWidth;
}
public static string ToStringTable<T>(this IEnumerable<T> values,
params Expression<Func<T, object>>[] valueSelectors)
{
string[] headers = valueSelectors.Select(func => GetProperty(func).Name).ToArray();
Func<T, object>[] selectors = valueSelectors.Select(exp => exp.Compile()).ToArray();
return ToStringTable(values, headers, selectors);
}
private static PropertyInfo GetProperty<T>(Expression<Func<T, object>> expresstion)
{
if (expresstion.Body is UnaryExpression expression)
if (expression.Operand is MemberExpression memberExpression)
return memberExpression.Member as PropertyInfo;
if (expresstion.Body is MemberExpression body) return body.Member as PropertyInfo;
return null;
}
}
}

117
UpToolCLI/UTLibFunctions.cs Normal file
View File

@ -0,0 +1,117 @@
using System;
using System.IO;
using System.Net;
using System.Threading;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using UpToolLib.DataStructures;
using static UpToolCLI.Program;
namespace UpToolCLI
{
public class UtLibFunctions : IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link)
{
using WebClient client = new();
byte[] result = new byte[0];
bool finished = false;
bool success = true;
client.DownloadDataCompleted += (sender, e) =>
{
success = !e.Cancelled;
if (success)
result = e.Result;
finished = true;
};
client.DownloadProgressChanged += (sender, e) =>
{
if (!Basic)
{
Console.Write(
$"{new string('=', e.ProgressPercentage / 10)}[{e.ProgressPercentage}]{new string('-', 10 - e.ProgressPercentage / 10)}");
Console.CursorLeft = 0;
}
};
client.DownloadDataAsync(link);
while (!finished)
Thread.Sleep(100);
return new Tuple<bool, byte[]>(success, result);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new();
using Image image = Image.Load(client.OpenRead(link));
image.Mutate(x => x.Resize(70, 70));
using MemoryStream ms = new();
image.SaveAsPng(ms);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool defaultVal)
{
if (Basic)
{
Console.WriteLine(text);
Console.WriteLine($"Selecting: {defaultVal}");
return defaultVal;
}
else
{
bool choosing = true;
bool current = defaultVal;
Console.WriteLine(text);
while (choosing)
{
Console.CursorLeft = 0;
Console.BackgroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.Write("Yes");
Console.ResetColor();
Console.Write(" ");
Console.BackgroundColor = current ? ConsoleColor.Black : ConsoleColor.White;
Console.ForegroundColor = current ? ConsoleColor.White : ConsoleColor.Black;
Console.Write("No");
Console.ResetColor();
switch (Console.ReadKey().Key)
{
case ConsoleKey.LeftArrow:
case ConsoleKey.RightArrow:
current = !current;
break;
case ConsoleKey.Enter:
choosing = false;
break;
case ConsoleKey.Escape:
current = defaultVal;
choosing = false;
break;
}
}
Console.ResetColor();
Console.WriteLine($" Selecting: {current}");
return current;
}
}
public void OkDialog(string text)
{
if (Basic)
Console.WriteLine(text);
else
{
Console.WriteLine(text);
Console.BackgroundColor = ConsoleColor.White;
Console.Write("OK");
Console.ResetColor();
Console.ReadKey();
}
}
public object GetDefaultIcon() => 0;
public object ImageFromB64(string b64) => 0;
public void Log(string text) => Console.WriteLine(text);
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>uptool</AssemblyName>
<Deterministic>false</Deterministic>
<AssemblyVersion>1.0.*</AssemblyVersion>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>..\UpTool2.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.2" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,17 @@
using System;
using Eto.Forms;
namespace UpToolEto.Gtk
{
class MainClass
{
[STAThread]
public static void Main(string[] args)
{
new Main(new Application(Eto.Platforms.Gtk), () =>
{
}, args).Entry();
}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolEto\UpToolEto.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Eto.Platform.Gtk" Version="2.5.10"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
using System;
using Eto.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace UpToolEto.Wpf
{
class MainClass
{
[STAThread]
public static void Main(string[] args)
{
new Main(new Application(Eto.Platforms.Wpf), () =>
{
Process[] processes = Process.GetProcessesByName("UpTool2");
if (processes.Length > 0)
BringProcessToFront(processes[0]);
}, args).Entry();
}
public static void BringProcessToFront(Process process)
{
IntPtr handle = process.MainWindowHandle;
if (IsIconic(handle))
ShowWindow(handle, 9);
SetForegroundWindow(handle);
}
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr handle);
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\UpToolEto\UpToolEto.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Eto.Platform.Wpf" Version="2.5.10"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Eto.Drawing;
using Eto.Forms;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls
{
public abstract class AppControlButton : Button
{
public abstract void ReloadState();
public abstract void SetApp(App app);
public abstract void Clear();
}
public class AppControlButton<T> : AppControlButton where T : KnownAppTask
{
private readonly IList<AppTask> _tasks;
private readonly Func<App, bool> _enabledCheck;
private readonly Color _defaultColor;
private App _app;
public AppControlButton(string text, Func<App, Action?, AppTask> factory, IList<AppTask> tasks, Action reloadState, Func<App, bool> enabledCheck)
{
_tasks = tasks;
_enabledCheck = enabledCheck;
_defaultColor = BackgroundColor;
Text = text;
Click += (_, _) =>
{
bool found = false;
for (var i = tasks.ToArray().Length - 1; i >= 0; i--)
{
if (tasks[i] is T t && t.App == _app)
{
found = true;
tasks.RemoveAt(i);
}
}
if (!found)
tasks.Add(factory(_app, ReloadState));
reloadState();
};
}
public override void ReloadState()
{
Enabled = _enabledCheck(_app);
BackgroundColor = _tasks.Any(s => s is T t && t.App == _app) ? Colors.Green : _defaultColor;
}
public override void SetApp(App app)
{
_app = app;
ReloadState();
}
public override void Clear()
{
Enabled = false;
}
}
}

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Eto.Drawing;
using Eto.Forms;
using UpToolEto.Forms;
using UpToolLib.DataStructures;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls
{
public class AppControls : StackLayout
{
private readonly IList<AppTask> _tasks;
private readonly List<AppControlButton> _buttons;
private readonly Button _applyButton;
public AppControls(TaskFactory factory, IList<AppTask> tasks, IExternalFunctionality platform, Action update)
{
_tasks = tasks;
_buttons = new List<AppControlButton>
{
new AppControlButton<InstallTask>("Install", factory.CreateInstall, tasks, ReloadState,
app => !app.Status.Contains(Status.Installed)),
new AppControlButton<UpdateTask>("Update", factory.CreateUpdate, tasks, ReloadState,
app => app.Status.Contains(Status.Updatable)),
new AppControlButton<RemoveTask>("Remove", factory.CreateRemove, tasks, ReloadState,
app => app.Status.Contains(Status.Installed))
};
_applyButton = new Button((_, _) =>
{
try
{
QueueOverview overview = new(tasks);
overview.ShowModal();
if (!overview.Cancelled)
{
foreach (AppTask task in overview.TasksResulting)
{
task.Run();
_tasks.RemoveAt(0);
}
}
}
catch (Exception e)
{
platform.OkDialog("Failed to complete queue:\r\n" + e);
}
finally
{
ReloadState();
update();
}
})
{
Text = "Apply",
Enabled = false
};
foreach (AppControlButton button in _buttons) Items.Add(button);
Items.Add(new StackLayoutItem(_applyButton, HorizontalAlignment.Right));
if (Main.DebugColors)
BackgroundColor = Colors.Yellow;
Orientation = Orientation.Horizontal;
}
public void SetApp(App app)
{
foreach (AppControlButton button in _buttons) button.SetApp(app);
ReloadState();
}
public void Clear()
{
foreach (AppControlButton button in _buttons) button.Clear();
}
private void ReloadState()
{
foreach (AppControlButton button in _buttons) button.ReloadState();
_applyButton.Enabled = _tasks.Any();
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Eto.Drawing;
using Eto.Forms;
using UpToolEto.Forms;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls
{
public class AppList : StackLayout
{
private readonly AppExtras _extras;
private readonly Action<Guid, App> _itemClickEvent;
private readonly StackLayout _layout;
private readonly AppListSearchProvider _searchProvider;
public AppList(AppExtras extras, Action<Guid, App> itemClickEvent, bool online, TaskFactory factory, IList<AppTask> tasks)
{
_extras = extras;
_itemClickEvent = itemClickEvent;
_searchProvider = new AppListSearchProvider(online, Update);
Items.Add(_searchProvider);
_layout = new StackLayout
{
Padding = 10,
Orientation = Orientation.Vertical,
Width = 200
};
Scrollable scrollable = new()
{
Content = _layout
};
if (Main.DebugColors)
scrollable.BackgroundColor = Colors.YellowGreen;
Items.Add(new StackLayoutItem(scrollable, VerticalAlignment.Stretch, true));
Orientation = Orientation.Vertical;
if (Main.DebugColors)
BackgroundColor = Colors.Green;
Update();
}
public void Update()
{
_layout.Items.Clear();
foreach (App app in _extras.FindApps(_searchProvider.GetSearchTerms()))
if (_searchProvider.Matches(app))
_layout.Items.Add(new Button((_, _) => _itemClickEvent(app.Id, app))
{
Text = app.Name,
Image = (Icon)app.Icon,
ImagePosition = ButtonImagePosition.Left,
});
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using Eto.Forms;
using UpToolLib.DataStructures;
using UpToolLib.v2;
namespace UpToolEto.Controls
{
public class AppListSearchProvider : StackLayout
{
private readonly bool _online;
private readonly TextBox _search;
private readonly EnumDropDown<Status> _state;
public AppListSearchProvider(bool online, Action refresh)
{
_online = online;
_search = new SearchBox();
_state = new EnumDropDown<Status>();
_state.SelectedValue = online ? Status.NotInstalled : Status.Installed;
_state.Enabled = online;
_search.TextChanged += (_, _) => refresh();
_state.SelectedIndexChanged += (_, _) => refresh();
Orientation = Orientation.Vertical;
Items.Add(new StackLayoutItem(_search, HorizontalAlignment.Stretch));
Items.Add(_state);
}
public bool Matches(App app) => app.Status.Contains(_online ? _state.SelectedValue : Status.Installed);
public string GetSearchTerms() => _search.Text;
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using Eto.Drawing;
using Eto.Forms;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls
{
public class AppPanel : Panel
{
private readonly Button _appNameLabel;
private readonly Label _appDescriptionLabel;
private readonly AppControls _appControls;
private App _app;
public AppPanel(TaskFactory factory, AppExtras extras, IList<AppTask> tasks, IExternalFunctionality platform, Action updateAppList)
{
_appDescriptionLabel = new Label();
_appNameLabel = new Button((_, _) =>
{
try
{
extras.RunApp(_app);
}
catch (Exception e)
{
platform.OkDialog("Failed to start\r\n" + e);
}
});
_appNameLabel.Font = new Font(_appNameLabel.Font.Family, _appNameLabel.Font.Size * 2);
_appControls = new AppControls(factory, tasks, platform, () =>
{
updateAppList();
SetApp(_app);
});
Content = new StackLayout
{
Items =
{
new StackLayoutItem(_appNameLabel, HorizontalAlignment.Center),
new StackLayoutItem(_appDescriptionLabel, HorizontalAlignment.Center, true),
new StackLayoutItem(_appControls, HorizontalAlignment.Stretch)
},
Orientation = Orientation.Vertical
};
if (Main.DebugColors)
BackgroundColor = Colors.Red;
Clear();
}
public void SetApp(App app)
{
_app = app;
_appNameLabel.Text = app.Name;
_appNameLabel.Enabled = app.Status.Contains(Status.Installed) && app.Runnable;
_appDescriptionLabel.Text = app.Description;
_appControls.SetApp(app);
}
public void Clear()
{
_appNameLabel.Text = "Welcome to UpTool2";
_appNameLabel.Enabled = false;
_appDescriptionLabel.Text = "Select an app to get started";
_appControls.Clear();
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Eto.Forms;
using UpToolLib.DataStructures;
namespace UpToolEto.Controls
{
public class RepoItem : StackLayout
{
public RepoItem(Repo repo, int index, Action update, IList<Repo> repos)
{
TextBox name = new()
{
Text = repo.Name
};
name.TextChanged += (_, _) => repo.Name = name.Text;
TextBox link = new()
{
Text = repo.Url
};
link.TextChanged += (_, _) => repo.Url = link.Text;
Orientation = Orientation.Horizontal;
Items.Add(name);
Items.Add(new StackLayoutItem(link, HorizontalAlignment.Stretch, true));
Items.Add(new Button((_, _) =>
{
repos.RemoveAt(index);
update();
})
{
Text = "-"
});
}
}
}

View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
using Eto.Forms;
using UpToolEto.Forms;
using UpToolLib.DataStructures;
using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls
{
public class UTMenuBar : MenuBar
{
public UTMenuBar(MainForm mainForm, RepoManagement repoManagement, TaskFactory factory, IList<AppTask> tasks, AppList appList, IExternalFunctionality platform)
{
Command reloadRepos = new() {MenuText = "Reload", ToolBarText = "Reload"};
reloadRepos.Executed += (_, _) =>
{
if (platform.YesNoDialog("This may take some time. Are you sure?", true))
{
repoManagement.FetchRepos();
repoManagement.GetReposFromDisk();
appList.Update();
}
};
Command editSources = new() {MenuText = "Sources", ToolBarText = "Sources"};
editSources.Executed += (_, _) => new RepoForm(repoManagement).ShowModal();
Command addPackage = new() {MenuText = "Add Package", ToolBarText = "Add Package"};
addPackage.Executed += (_, _) =>
{
OpenFileDialog dialog = new() {MultiSelect = false, CheckFileExists = true, Filters = { new FileFilter("App package", ".zip")}};
if (dialog.ShowDialog(mainForm) == DialogResult.Ok)
{
if (!tasks.Any(s => s is UploadTask t && t.ZipFile == dialog.FileName))
{
StringDialog sd = new("Package name") {Text = "New package"};
sd.ShowModal();
tasks.Add(factory.CreateUpload(dialog.FileName, sd.Text));
}
}
};
Command quitCommand = new() {MenuText = "Quit", Shortcut = Application.Instance.CommonModifier | Keys.Q};
quitCommand.Executed += (_, _) => Application.Instance.Quit();
Command aboutCommand = new() {MenuText = "About Eto..."};
aboutCommand.Executed += (_, _) => new AboutDialog().ShowDialog(mainForm);
Items.Add(new ButtonMenuItem
{
Text = "&File", Items =
{
reloadRepos,
editSources,
addPackage
}
});
// File submenu
// new ButtonMenuItem { Text = "&Edit", Items = { /* commands/items */ } },
// new ButtonMenuItem { Text = "&View", Items = { /* commands/items */ } },
/*ApplicationItems =
{
// application (OS X) or file menu (others)
new ButtonMenuItem {Text = "&Preferences..."},
},*/
QuitItem = quitCommand;
AboutItem = aboutCommand;
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Net;
using System.Threading;
using Eto.Drawing;
using Eto.Forms;
using UpToolLib.DataStructures;
namespace UpToolEto.Forms
{
public class DownloadDialog : Dialog
{
private readonly Uri _url;
private readonly Application _application;
private readonly IExternalFunctionality _platform;
public State CurrentState = State.NotStarted;
public byte[] Download = new byte[0];
private readonly ProgressBar _bar;
public DownloadDialog(Uri url, Application application, IExternalFunctionality platform)
{
_url = url;
_application = application;
_platform = platform;
Title = "Downloader";
Resizable = false;
Maximizable = false;
Minimizable = false;
WindowStyle = WindowStyle.Utility;
_bar = new();
_bar.MaxValue = 100;
Content = new StackLayout
{
Padding = 10,
Items =
{
"Downloading " + url,
new StackLayoutItem(_bar, HorizontalAlignment.Stretch, true)
}
};
Size = new Size(700, 400);
}
public void StartDownload()
{
CurrentState = State.Downloading;
new Thread(() =>
{
try
{
WebClient client = new();
client.DownloadProgressChanged += (_, args) => _application.Invoke(() =>
{
_bar.Value = args.ProgressPercentage;
_application.RunIteration();
});
client.DownloadDataCompleted += (_, args) =>
{
CurrentState = State.Success;
Download = args.Result;
_application.Invoke(Close);
};
client.DownloadDataAsync(_url, client);
}
catch
{
CurrentState = State.Failed;
_application.Invoke(Close);
}
}).Start();
}
public enum State
{
NotStarted,
Downloading,
Failed,
Success
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using Eto.Drawing;
using Eto.Forms;
using UpToolLib.DataStructures;
namespace UpToolEto.Forms
{
public class InitScreen : Form
{
private readonly Application _application;
private readonly IExternalFunctionality _platform;
private readonly Label _lab;
public InitScreen(Application application, IExternalFunctionality platform)
{
_application = application;
_platform = platform;
Title = "UpTool2 Init";
Resizable = false;
Maximizable = false;
Minimizable = false;
WindowStyle = WindowStyle.None;
_lab = new Label();
Label header = new();
header.Font = new Font(header.Font.Family, header.Font.Size * 2);
header.Text = "UpTool2";
Content = new StackLayout
{
Padding = 10,
Items =
{
new StackLayoutItem(header, HorizontalAlignment.Center),
new StackLayoutItem(_lab, HorizontalAlignment.Center)
},
VerticalContentAlignment = VerticalAlignment.Center
};
Shown += (_, _) => Size = new Size(700, 400);
}
public void SetText(string text)
{
_application.Invoke(() =>
{
_platform.Log(text);
_lab.Text = text;
_application.RunIteration();
});
}
public override void Close() => _application.Invoke(() => base.Close());
}
}

View File

@ -0,0 +1,37 @@
using System.Collections.Generic;
using Eto.Drawing;
using Eto.Forms;
using UpToolEto.Controls;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Forms
{
public partial class MainForm : Form
{
private readonly AppPanel _appPanel;
private readonly IList<AppTask> _tasks;
public MainForm(InitScreen init, UpToolLibMain lib, IExternalFunctionality platform, bool online)
{
_tasks = new List<AppTask>();
Title = "UpTool2";
MinimumSize = new Size(600, 100);
AppList appList = new(lib.V1.AppExtras, (_, app) => _appPanel.SetApp(app), online, lib.V2.TaskFactory, _tasks);
_appPanel = new AppPanel(lib.V2.TaskFactory, lib.V1.AppExtras, _tasks, platform, appList.Update);
Content = new StackLayout
{
Padding = 10,
Items =
{
new StackLayoutItem(appList, VerticalAlignment.Stretch),
new StackLayoutItem(_appPanel, VerticalAlignment.Stretch, true)
},
Orientation = Orientation.Horizontal
};
Menu = new UTMenuBar(this, lib.V2.RepoManagement, lib.V2.TaskFactory, _tasks, appList, platform);
Shown += (_, _) => init.Close();
}
}
}

View File

@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using Eto.Forms;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Forms
{
public class QueueOverview : Dialog
{
private readonly IList<AppTask> _tasks;
public bool Cancelled;
CheckBoxList cbl;
public List<AppTask> TasksResulting => cbl.SelectedValues.Select(s => (AppTask) s).ToList();
public QueueOverview(IList<AppTask> tasks)
{
_tasks = tasks;
StackLayout layout = new();
layout.Items.Add(new StackLayoutItem(new StackLayout()
{
Items =
{
new StackLayoutItem(new Button((_, _) =>
{
Cancelled = true;
Close();
})
{
Text = "Cancel"
}, HorizontalAlignment.Stretch),
new StackLayoutItem(new Button((_, _) =>
{
Close();
})
{
Text = "OK"
}, HorizontalAlignment.Stretch)
},
Orientation = Orientation.Horizontal
}, HorizontalAlignment.Stretch));
cbl = new CheckBoxList {DataStore = tasks, SelectedValues = tasks};
layout.Items.Add(cbl);
Content = layout;
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using Eto.Forms;
using UpToolEto.Controls;
using UpToolLib.DataStructures;
using UpToolLib.v2;
namespace UpToolEto.Forms
{
public class RepoForm : Dialog
{
private readonly RepoManagement _management;
private List<Repo> _repos = new();
private StackLayout _layout;
public RepoForm(RepoManagement management)
{
_management = management;
_repos.AddRange(management.GetRepos());
Title = "Sources";
_layout = new StackLayout();
Content = _layout;
Update();
}
private void Update()
{
_layout.Items.Clear();
_layout.Items.Add(new StackLayoutItem(new Button((_, _) =>
{
_repos.Add(new Repo
{
Name = "New repo",
Url = "https://example.com/repo.xml"
});
Update();
})
{
Text = "Add",
}, HorizontalAlignment.Stretch));
StackLayout reposLayout = new();
for (int i = 0; i < _repos.Count; i++)
reposLayout.Items.Add(new StackLayoutItem(new RepoItem(_repos[i], i, Update, _repos), HorizontalAlignment.Stretch));
_layout.Items.Add(new StackLayoutItem(new Scrollable{Content = reposLayout}, HorizontalAlignment.Stretch, true));
_layout.Items.Add(new StackLayoutItem(new Button((_, _) =>
{
_management.Save(_repos);
Close();
})
{
Text = "Save"
}, HorizontalAlignment.Stretch));
}
}
}

View File

@ -0,0 +1,20 @@
using Eto.Forms;
namespace UpToolEto.Forms
{
public class StringDialog : Dialog
{
private readonly TextBox _tb;
public string Text
{
get => _tb.Text;
set => _tb.Text = value;
}
public StringDialog(string title)
{
_tb = new TextBox();
Content = _tb;
Title = title;
}
}
}

164
UpToolEto/UpToolEto/Main.cs Normal file
View File

@ -0,0 +1,164 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading;
using System.Xml;
using Eto.Forms;
using UpToolEto.Forms;
using UpToolLib;
using UpToolLib.DataStructures;
using UpToolLib.v1;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace UpToolEto
{
public class Main
{
private readonly IExternalFunctionality _platform;
private readonly Application _application;
private readonly Action _activityExistsException;
private readonly InitScreen _init;
private readonly bool _skipFetch;
public static bool DebugColors { get; private set; }
public Main(Application application, Action activityExistsException, string[] args)
{
_skipFetch = args.Contains("--skip-fetch");
DebugColors = args.Contains("--debug-colors");
_platform = new UTLibFunctions(application);
_application = application;
_activityExistsException = activityExistsException;
_init = new(application, _platform);
}
public void Entry()
{
new Thread(InitThread).Start();
_application.Run(_init);
}
private void InitThread()
{
UpToolLibMain lib = null;
try
{
lib = new UpToolLibMain(_platform);
_init.SetText("Initializing paths");
if (!Directory.Exists(lib.V1.PathTool.Dir))
Directory.CreateDirectory(lib.V1.PathTool.Dir);
FixXml(lib.V1.XmlTool, lib.V1.PathTool);
_init.SetText("Performing checks");
bool online = false;
UpdateCheck updateCheck = null;
try
{
updateCheck = lib.V2.UpdateChecker.Check();
online = true;
}
catch
{
_platform.Log("Could not perform update check, starting offline");
}
if (online && UpdateCheck(updateCheck, lib.V1.PathTool, _init))
_platform.Log("Quitting");
else
{
if (!Directory.Exists(lib.V1.PathTool.GetRelative("Apps")))
Directory.CreateDirectory(lib.V1.PathTool.GetRelative("Apps"));
if (!_skipFetch && online)
{
_init.SetText("Fetching repos");
lib.V2.RepoManagement.FetchRepos();
}
lib.V2.RepoManagement.GetReposFromDisk();
_init.SetText("Opening");
_application.Invoke(() => _application.Run(new MainForm(_init, lib, _platform, online)));
}
}
catch (MutexLockLockedException)
{
_application.Invoke(() =>
{
_init.Close();
_platform.OkDialog("Mutex property of other process, quitting");
_activityExistsException();
});
}
catch (Exception e)
{
lib?.Dispose();
_platform.Log(e.ToString());
}
finally
{
lib?.Dispose();
_application.Invoke(() => _application.Quit());
}
}
public void FixXml(XmlTool xmlTool, PathTool pathTool, bool throwOnError = false)
{
try
{
xmlTool.FixXml();
}
catch (XmlException)
{
if (throwOnError) throw;
_platform.OkDialog("Something went wrong while trying to parse XML. Retrying...");
File.Delete(pathTool.InfoXml);
FixXml(xmlTool, pathTool);
}
}
private bool UpdateCheck(UpdateCheck updateCheck, PathTool pathTool, InitScreen init)
{
init.SetText("Comparing online version");
if (Assembly.GetExecutingAssembly().GetName().Version >= updateCheck.OnlineVersion) return false;
if (PlatformCheck.IsWindows)
{
init.SetText("Downloading latest");
(bool success, byte[] dl) = _platform.Download(updateCheck.Installer);
if (!success)
throw new Exception("Failed to update");
init.SetText("Verifying");
using (SHA256CryptoServiceProvider sha256 = new())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty).ToUpper();
if (pkgHash != updateCheck.InstallerHash)
throw new Exception(
$"The hash is not equal to the one stored in the repo:\r\nPackage: {pkgHash}\r\nOnline: {updateCheck.InstallerHash}");
}
init.SetText("Installing");
if (Directory.Exists(pathTool.GetRelative("Install", "tmp")))
Directory.Delete(pathTool.GetRelative("Install", "tmp"), true);
Directory.CreateDirectory(pathTool.GetRelative("Install", "tmp"));
using (MemoryStream ms = new(dl))
{
using ZipArchive ar = new(ms);
ar.ExtractToDirectory(pathTool.GetRelative("Install", "tmp"), true);
}
init.Close();
Process.Start(new ProcessStartInfo
{
FileName = pathTool.GetRelative("Install", "tmp", "Installer.exe"),
Arguments = "i -p",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = pathTool.GetRelative("Install")
});
return true;
}
else
{
_platform.OkDialog("A new version is available. Please install it");
return false;
}
}
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.IO;
using System.Net;
using System.Threading;
using Eto.Drawing;
using Eto.Forms;
using UpToolEto.Forms;
using UpToolLib;
using UpToolLib.DataStructures;
namespace UpToolEto
{
public class UTLibFunctions : IExternalFunctionality
{
private readonly Application _application;
private const int ImgSize = 32;
public Tuple<bool, byte[]> Download(Uri link)
{
DownloadDialog dlg = new(link, _application, this);
_application.AsyncInvoke(() => dlg.ShowModal());
dlg.StartDownload();
Log("Downloading " + link);
while (dlg.CurrentState == DownloadDialog.State.Downloading) Thread.Sleep(20);
Log("Download complete");
return new Tuple<bool, byte[]>(dlg.CurrentState == DownloadDialog.State.Success, dlg.Download);
}
public string FetchImageB64(Uri link)
{
using WebClient client = new();
using Stream s = client.OpenRead(link);
using Bitmap source = new(s);
using Icon bmp = source.WithSize(ImgSize, ImgSize);
using Bitmap bitmapResized = new(bmp);
using MemoryStream ms = new();
bitmapResized.Save(ms, ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
public bool YesNoDialog(string text, bool defaultVal) =>
_application.Invoke(() => MessageBox.Show(text, MessageBoxButtons.YesNo,
defaultButton: defaultVal ? MessageBoxDefaultButton.Yes : MessageBoxDefaultButton.No)) ==
DialogResult.Yes;
public void OkDialog(string text) => _application.Invoke(() => MessageBox.Show(text));
public object GetDefaultIcon() => Bitmap.FromResource("UpToolLib.C_64.ico", typeof(UpToolLibMain)).WithSize(ImgSize, ImgSize);
public object ImageFromB64(string b64) => new Bitmap(Convert.FromBase64String(b64)).WithSize(ImgSize, ImgSize);
public void Log(string text)
{
Console.WriteLine(text);
//TODO implement visual logging
}
public UTLibFunctions(Application application) => _application = application;
}
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Eto.Forms" Version="2.5.10" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\UpToolLib\UpToolLib.csproj" />
</ItemGroup>
</Project>

BIN
UpToolLib/C_64.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,15 @@
using System;
namespace UpToolLib.DataStructures
{
public interface IExternalFunctionality
{
public Tuple<bool, byte[]> Download(Uri link);
public string FetchImageB64(Uri link);
public bool YesNoDialog(string text, bool defaultVal);
public void OkDialog(string text);
public object GetDefaultIcon();
public object ImageFromB64(string b64);
public void Log(string text);
}
}

View File

@ -0,0 +1,8 @@
namespace UpToolLib.DataStructures
{
public class Repo
{
public string Name { get; set; }
public string Url { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
namespace UpToolLib.DataStructures
{
[Flags]
public enum Status
{
NotInstalled = 1,
Updatable = 2,
Installed = 4,
Local = 8,
All = 0
}
public static class StatusExtensions
{
public static bool Contains(this Status status, Status other) => (status & other) == other;
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace UpToolLib
{
public class MutexLockLockedException : Exception
{
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Deterministic>false</Deterministic>
<AssemblyVersion>1.0.*</AssemblyVersion>
</PropertyGroup>
<ItemGroup>
<Content Remove="C_64.ico" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="C_64.ico" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
using System;
using System.Threading;
using UpToolLib.DataStructures;
using UpToolLib.v1;
using UpToolLib.v2;
namespace UpToolLib
{
public class UpToolLibMain : IDisposable
{
private static Mutex _mutex;
public UpToolLibMain(IExternalFunctionality platform)
{
V1 = new UpToolLibV1(platform);
V2 = new UpToolLibV2(platform, V1.Installer, V1.AppExtras, V1.PathTool, V1.XmlTool, V1.Apps);
_mutex = new Mutex(false,
"Global\\{c0c1e002-9e13-4e8f-a035-dbdc5128e00e}",
out bool _);
try
{
if (_mutex.WaitOne(5000, false))
return;
throw new MutexLockLockedException();
}
catch (AbandonedMutexException)
{
#if DEBUG
_platform.Log("Mutex abandoned");
#endif
}
}
public readonly UpToolLibV1 V1;
public readonly UpToolLibV2 V2;
public void Dispose() => _mutex.ReleaseMutex();
~UpToolLibMain() => Dispose();
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Linq;
namespace UpToolLib.v1
{
public static class PlatformCheck
{
public static bool IsWindows => new[]
{
PlatformID.Xbox, PlatformID.Win32S, PlatformID.Win32Windows, PlatformID.Win32NT,
PlatformID.WinCE
}
.Contains(Environment.OSVersion.Platform);
public static bool IsPosix => !IsWindows;
public const string Windows = "WINDOWS";
public const string Posix = "POSIX";
public static string CurrentPlatform =>
IsWindows ? Windows :
IsPosix ? Posix : throw new Exception("Unexpected PlatformCheck");
}
}

View File

@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using UpToolLib.v2;
namespace UpToolLib.v1.Tool
{
public class AppExtras
{
private readonly AppInstall _appInstall;
private readonly PathTool _pathTool;
private readonly IDictionary<Guid, App> _apps;
internal AppExtras(AppInstall appInstall, PathTool pathTool, IDictionary<Guid, App> apps)
{
_appInstall = appInstall;
_pathTool = pathTool;
_apps = apps;
}
public Process RunApp(App app) => RunApp(app, app.MainFile, "");
public Process RunApp(App app, string arguments) => RunApp(app, app.MainFile, arguments);
public Process RunApp(App app, string file, string arguments) =>
Process.Start(
new ProcessStartInfo
{
FileName = Path.Combine(app.DataPath, file),
Arguments = arguments,
WorkingDirectory = app.DataPath
});
public void Update(App app, bool overwrite)
{
Remove(app, overwrite);
_appInstall.Install(app, overwrite);
}
public void Remove(App app, bool deleteAll)
{
string tmp = _pathTool.TempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
if (File.Exists(Path.Combine(app.AppPath, "package.zip")))
{
ZipFile.ExtractToDirectory(Path.Combine(app.AppPath, "package.zip"), tmp);
/*Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C \"{Path.Combine(tmp, "Remove.bat")}\"",
WorkingDirectory = Path.Combine(app.AppPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();*/
int key = PlatformCheck.IsWindows ? 0 :
File.Exists(Path.Combine(tmp, "Remove.sh")) ? 1 : 2;
ProcessStartInfo prc = new()
{
FileName = key switch
{
0 => "cmd.exe",
1 => "bash",
2 => "wine",
_ => throw new Exception()
},
WorkingDirectory = Path.Combine(app.AppPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
foreach (string s in key switch
{
0 => new[] {"/C", $"{Path.Combine(tmp, "Remove.bat")}"},
1 => new[] {Path.Combine(tmp, "Remove.sh")},
2 => new[] {"cmd", "/C", $"{Path.Combine(tmp, "Remove.bat")}"},
_ => throw new Exception()
})
prc.ArgumentList.Add(s);
Process.Start(prc)?.WaitForExit();
if (!deleteAll) CheckDirecory(Path.Combine(tmp, "Data"), app.DataPath);
Directory.Delete(tmp, true);
}
if (File.Exists(app.InfoPath))
File.Delete(app.InfoPath);
if (File.Exists(Path.Combine(app.AppPath, "package.zip")))
File.Delete(Path.Combine(app.AppPath, "package.zip"));
if (deleteAll || Directory.Exists(app.DataPath) &&
Directory.GetFiles(app.DataPath).Length + Directory.GetDirectories(app.DataPath).Length ==
0)
Directory.Delete(app.AppPath, true);
}
private void CheckDirecory(string tmp, string app)
{
foreach (string file in Directory.GetFiles(tmp))
{
string tmp1 = Path.Combine(app, Path.GetFileName(file));
if (File.Exists(tmp1))
File.Delete(tmp1);
}
foreach (string directory in Directory.GetDirectories(tmp))
CheckDirecory(directory, Path.Combine(app, Path.GetFileName(directory)));
if (Directory.Exists(app) && Directory.GetFiles(app).Length + Directory.GetDirectories(app).Length == 0)
Directory.Delete(app);
}
public App[] FindApps(string identifier)
{
if (string.IsNullOrWhiteSpace(identifier))
return _apps.Values.ToArray();
IEnumerable<KeyValuePair<Guid, App>> tmp1 = _apps.Where(s => s.Key.ToString().StartsWith(identifier));
tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Name.Contains(identifier)));
tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Description.Contains(identifier)));
return tmp1.Select(s => s.Value).ToArray();
}
}
}

View File

@ -0,0 +1,201 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Xml.Linq;
using UpToolLib.DataStructures;
using UpToolLib.v2;
namespace UpToolLib.v1.Tool
{
public class AppInstall
{
private readonly IExternalFunctionality _platform;
private readonly PathTool _pathTool;
internal AppInstall(IExternalFunctionality platform, PathTool pathTool)
{
_platform = platform;
_pathTool = pathTool;
}
/// <summary>
/// Install an application
/// </summary>
/// <param name="appI">The app to install</param>
/// <param name="force">Set to true to overwrite all old data</param>
public void Install(App appI, bool force)
{
string app = "";
string tmp = "";
#if !DEBUG
try
{
#endif
app = appI.AppPath;
tmp = _pathTool.TempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
if (force)
{
if (Directory.Exists(app))
Directory.Delete(app, true);
Directory.CreateDirectory(app);
}
else
{
if (!Directory.Exists(app))
Directory.CreateDirectory(app);
}
(bool dlSuccess, byte[] dlData) = _platform.Download(new Uri(appI.File));
if (!dlSuccess)
throw new Exception("Download failed");
using (SHA256CryptoServiceProvider sha256 = new())
{
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlData)).Replace("-", string.Empty)
.ToUpper();
if (pkgHash != appI.Hash.ToUpper())
throw new Exception($@"The hash is not equal to the one stored in the repo:
Package: {pkgHash}
Online: {appI.Hash.ToUpper()}");
}
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlData);
CompleteInstall(appI, force);
#if !DEBUG
}
catch
{
if (Directory.Exists(app))
Directory.Delete(app, true);
throw;
}
finally
{
#endif
if (tmp != "" && Directory.Exists(tmp))
Directory.Delete(tmp, true);
#if !DEBUG
}
#endif
}
public void InstallZip(string zipPath, App meta, bool force)
{
string app = "";
string tmp = "";
try
{
app = meta.AppPath;
Directory.CreateDirectory(app);
tmp = _pathTool.TempPath;
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
File.Copy(zipPath, Path.Combine(app, "package.zip"));
CompleteInstall(meta, force);
}
catch
{
if (Directory.Exists(app))
Directory.Delete(app, true);
throw;
}
finally
{
if (tmp != "" && Directory.Exists(tmp))
Directory.Delete(tmp, true);
}
}
//Use
//PowerShell -Command "Add-Type -AssemblyName PresentationFramework;[System.Windows.MessageBox]::Show('Hello World')"
//for message boxes
private void CompleteInstall(App app, bool force) => CompleteInstall(app.AppPath, app.Name,
app.Description, app.Version, app.MainFile, force);
private void CompleteInstall(string appPath, string name, string description, Version version,
string mainFile, bool force)
{
string tmp = _pathTool.TempPath;
ZipFile.ExtractToDirectory(Path.Combine(appPath, "package.zip"), tmp);
if (force)
Directory.Move(Path.Combine(tmp, "Data"), Path.Combine(appPath, "app"));
else
{
CopyAll(Path.Combine(tmp, "Data"), Path.Combine(appPath, "app"));
Directory.Delete(Path.Combine(tmp, "Data"), true);
}
XElement el = new("app", new XElement("Name", name), new XElement("Description", description),
new XElement("Version", version));
if (mainFile != null)
el.Add(new XElement(new XElement("MainFile", mainFile)));
el.Save(Path.Combine(appPath, "info.xml"));
/*if (new[] { PlatformID.Xbox, PlatformID.Win32S, PlatformID.Win32Windows, PlatformID.Win32NT, PlatformID.WinCE }.Contains(Environment.OSVersion.Platform))
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
ArgumentList = {"/C", $"{Path.Combine(tmp, "Install.bat")}"},
WorkingDirectory = Path.Combine(appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
else if (File.Exists(Path.Combine(tmp, "Install.sh")))
Process.Start(new ProcessStartInfo
{
FileName = "bash",
ArgumentList = {Path.Combine(tmp, "Install.sh")},
WorkingDirectory = Path.Combine(appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
else
Process.Start(new ProcessStartInfo
{
FileName = "wine",
ArgumentList = {"cmd", "/C", $"{Path.Combine(tmp, "Install.bat")}"},
WorkingDirectory = Path.Combine(appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();*/
int key = PlatformCheck.IsWindows ? 0 :
File.Exists(Path.Combine(tmp, "Install.sh")) ? 1 : 2;
ProcessStartInfo prc = new()
{
FileName = key switch
{
0 => "cmd.exe",
1 => "bash",
2 => "wine",
_ => throw new Exception()
},
WorkingDirectory = Path.Combine(appPath, "app"),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
foreach (string s in key switch
{
0 => new[] {"/C", $"{Path.Combine(tmp, "Install.bat")}"},
1 => new[] {Path.Combine(tmp, "Install.sh")},
2 => new[] {"cmd", "/C", $"{Path.Combine(tmp, "Install.bat")}"},
_ => throw new Exception()
})
prc.ArgumentList.Add(s);
Process.Start(prc)?.WaitForExit();
}
private void CopyAll(string source, string target)
{
if (string.Equals(Path.GetFullPath(source), Path.GetFullPath(target),
StringComparison.CurrentCultureIgnoreCase))
return;
if (!Directory.Exists(target))
Directory.CreateDirectory(target);
foreach (string file in Directory.GetFiles(source))
File.Copy(file, Path.Combine(target, Path.GetFileName(file)), true);
foreach (string dir in Directory.GetDirectories(source))
CopyAll(dir, Path.Combine(target, Path.GetFileName(dir)));
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.IO;
using System.Linq;
namespace UpToolLib.v1.Tool
{
public class PathTool
{
public string Dir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UpTool2");
public string TempPath => GetRelative("tmp");
public string AppsPath => GetRelative("Apps");
public string InfoXml => GetRelative("info.xml");
public string GetRelative(params string[] segments) =>
Path.Combine(new[] {Dir}.Concat(segments).ToArray());
public string GetAppPath(Guid app) => Path.Combine(AppsPath, app.ToString());
public string GetDataPath(Guid app) => Path.Combine(GetAppPath(app), "app");
public string GetInfoPath(Guid app) => Path.Combine(GetAppPath(app), "info.xml");
}
}

View File

@ -0,0 +1,69 @@
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UpToolLib.DataStructures;
namespace UpToolLib.v1.Tool
{
public class XmlTool
{
private readonly IExternalFunctionality _platform;
private readonly PathTool _pathTool;
internal XmlTool(IExternalFunctionality platform, PathTool pathTool)
{
_platform = platform;
_pathTool = pathTool;
}
public void FixXml()
{
if (!Directory.Exists(_pathTool.AppsPath))
Directory.CreateDirectory(_pathTool.AppsPath);
if (!File.Exists(_pathTool.InfoXml) || XDocument.Load(_pathTool.InfoXml).Element("meta") == null)
new XElement("meta").Save(_pathTool.InfoXml);
XDocument x = XDocument.Load(_pathTool.InfoXml);
XElement meta = x.Element("meta");
if (meta.Element("UpdateSource") == null)
meta.Add(new XElement("UpdateSource"));
if (new[]
{
"",
"https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Meta.xml",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Meta.xml",
"https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml",
"https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/meta.xml?job=uptool"
}
.Contains(meta.Element("UpdateSource").Value))
meta.Element("UpdateSource").Value =
"https://gitlab.com/uptool/UpTool2/-/jobs/artifacts/master/raw/meta.xml?job=uptool";
if (meta.Element("Repos") == null)
meta.Add(new XElement("Repos"));
if (meta.Element("Repos").Elements("Repo").Count() == 0)
{
if (_platform.YesNoDialog(
"No active repository was detected. Add the default repo?", false))
{
meta.Element("Repos").Add(new XElement("Repo", new XElement("Name", "UpTool2 official Repo"),
new XElement("Link",
"https://gitlab.com/uptool/UpTool2/-/snippets/1988600/raw/master/Repo.xml")));
}
}
meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link"))
.Where(s => new[]
{
null, "https://github.com/JFronny/UpTool2/releases/download/Repo/Repo.xml",
"https://raw.githubusercontent.com/JFronny/UpTool2/master/Repo.xml",
"https://gist.githubusercontent.com/JFronny/f1ccbba3d8a2f5862592bb29fdb612c4/raw/Repo.xml",
"https://gitlab.com/JFronny/UpTool2/snippets/1988600/raw"
}.Contains(s.Value))
.ToList().ForEach(s =>
s.Value =
"https://gitlab.com/uptool/UpTool2/-/snippets/1988600/raw/master/Repo.xml");
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
x.Save(_pathTool.InfoXml);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2;
namespace UpToolLib.v1
{
public class UpToolLibV1
{
internal UpToolLibV1(IExternalFunctionality platform)
{
PathTool = new PathTool();
XmlTool = new XmlTool(platform, PathTool);
Installer = new AppInstall(platform, PathTool);
AppExtras = new AppExtras(Installer, PathTool, Apps);
}
public readonly AppExtras AppExtras;
public readonly AppInstall Installer;
public readonly PathTool PathTool;
public readonly XmlTool XmlTool;
public readonly IDictionary<Guid, App> Apps = new Dictionary<Guid, App>();
public static Version MinimumVer => Version.Parse("0.0.0.0");
}
}

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using UpTool2.Tool;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using static System.Environment;
namespace UpTool2.DataStructures
namespace UpToolLib.v2
{
public struct App : IEquatable<App>
{
@ -16,14 +17,15 @@ namespace UpTool2.DataStructures
public readonly string File;
public readonly bool Local;
public readonly string Hash;
private Guid _id;
public readonly Guid Id;
public Color Color;
public readonly Image Icon;
public readonly object Icon;
public readonly bool Runnable;
public readonly string MainFile;
private readonly PathTool _pathTool;
public App(string name, string description, Version version, string file, bool local, string hash, Guid iD,
Color color, Image icon, bool runnable, string mainFile)
internal App(string name, string description, Version version, string file, bool local, string hash, Guid iD,
Color color, object icon, bool runnable, string mainFile, PathTool pathTool)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
Description = description ?? throw new ArgumentNullException(nameof(description));
@ -31,20 +33,21 @@ namespace UpTool2.DataStructures
File = file ?? throw new ArgumentNullException(nameof(file));
Local = local;
Hash = hash ?? throw new ArgumentNullException(nameof(hash));
_id = iD;
Id = iD;
Color = color;
Icon = icon ?? throw new ArgumentNullException(nameof(icon));
Runnable = runnable;
MainFile = mainFile ?? throw new ArgumentNullException(nameof(mainFile));
_pathTool = pathTool;
}
public Status status
public Status Status
{
get
{
if (!System.IO.File.Exists(infoPath))
return Status.Not_Installed;
if (Version.TryParse(XDocument.Load(infoPath).Element("app").Element("Version").Value,
if (!System.IO.File.Exists(InfoPath))
return Status.NotInstalled;
if (Version.TryParse(XDocument.Load(InfoPath).Element("app").Element("Version").Value,
out Version ver) && ver >= Version)
return Local ? Status.Installed | Status.Local : Status.Installed;
return Status.Installed | Status.Updatable;
@ -53,30 +56,30 @@ namespace UpTool2.DataStructures
public override bool Equals(object obj) => obj is App app && Equals(app);
public bool Equals(App other) => _id.Equals(other._id);
public bool Equals(App other) => Id.Equals(other.Id);
public override int GetHashCode() => 1213502048 + EqualityComparer<Guid>.Default.GetHashCode(_id);
public override int GetHashCode() => 1213502048 + EqualityComparer<Guid>.Default.GetHashCode(Id);
public override string ToString() => $@"Name: {Name}
Description:
{string.Join(NewLine, Description.Split('\n').Select(s => { if (s.EndsWith("\r")) s.Remove(s.Length - 1, 1); return "> " + s; }))}
{string.Join(NewLine, Description.Split('\n').Select(s => { if (s.EndsWith("\r")) s.Remove(s.Length - 1, 1); return $"> {s}"; }))}
Version: {Version}
File: {File}
Local: {Local.ToString()}
Local: {Local}
Hash: {Hash}
ID: {_id.ToString()}
Color: {Color.ToKnownColor().ToString()}
ID: {Id}
Color: {Color.ToKnownColor()}
Runnable: {Runnable}
MainFile: {MainFile}
Status: {status.ToString()}
Status: {Status}
Object Hash Code: {GetHashCode()}";
public static bool operator ==(App left, App right) => left.Equals(right);
public static bool operator !=(App left, App right) => !(left == right);
public string appPath => PathTool.GetAppPath(_id);
public string dataPath => PathTool.GetDataPath(_id);
public string infoPath => PathTool.GetInfoPath(_id);
public string AppPath => _pathTool.GetAppPath(Id);
public string DataPath => _pathTool.GetDataPath(Id);
public string InfoPath => _pathTool.GetInfoPath(Id);
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Drawing;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2
{
public class AppFactory
{
private readonly PathTool _pathTool;
internal AppFactory(PathTool pathTool) => _pathTool = pathTool;
public App CreateApp(string name, string description, Version version, string file, bool local, string hash,
Guid iD, Color color, object icon, bool runnable, string mainFile) =>
new(name, description, version, file, local, hash, iD, color, icon, runnable, mainFile, _pathTool);
}
}

View File

@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UpToolLib.DataStructures;
using UpToolLib.v1;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2
{
public class RepoManagement
{
private readonly IExternalFunctionality _platform;
private readonly XmlTool _xmlTool;
private readonly PathTool _pathTool;
private readonly AppFactory _appFactory;
private readonly IDictionary<Guid, App> _apps;
public RepoManagement(IExternalFunctionality platform, XmlTool xmlTool, PathTool pathTool, AppFactory appFactory, IDictionary<Guid, App> apps)
{
_platform = platform;
_xmlTool = xmlTool;
_pathTool = pathTool;
_appFactory = appFactory;
_apps = apps;
}
public void Save(IEnumerable<Repo> repos)
{
XDocument doc = XDocument.Load(_pathTool.InfoXml);
XElement reposEl = doc.Element("meta").Element("Repos");
reposEl.RemoveNodes();
foreach (Repo repo in repos)
reposEl.Add(new XElement("Repo", new XElement("Name", repo.Name), new XElement("Link", repo.Url)));
doc.Save(_pathTool.InfoXml);
}
public IEnumerable<Repo> GetRepos()
{
_xmlTool.FixXml();
XDocument doc = XDocument.Load(_pathTool.InfoXml);
XElement reposEl = doc.Element("meta").Element("Repos");
List<Repo> repos = new();
foreach (XElement repo in reposEl.Elements("Repo"))
{
repos.Add(new Repo
{
Name = repo.Element("Name").Value,
Url = repo.Element("Link").Value
});
}
return repos.ToArray();
}
public void FetchRepos()
{
_xmlTool.FixXml();
XElement meta = XDocument.Load(_pathTool.InfoXml).Element("meta");
List<XElement> tmpAppsList = new();
List<string> repArr = meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link").Value).Distinct()
.ToList();
int i = 0;
while (i < repArr.Count)
{
string status = "Initializing";
#if !DEBUG
try
{
#endif
_platform.Log($"[{i + 1}] Loading {repArr[i]}");
status = $"Loading {repArr[i]}";
XDocument repo = XDocument.Load(new Uri(repArr[i]).AbsoluteUri);
status = $"Extracting repolinks";
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
.Where(s => !repArr.Contains(s)));
status = $"Extracting apps";
XElement[] tmpApparray = repo.Element("repo").Elements("app").Where(app =>
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
!tmpAppsList
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
GetVer(a.Element("Version")) >= GetVer(app.Element("Version")))).ToArray()
.Concat(repo.Element("repo").Elements("applink")
.Select(s =>
{
_platform.Log($"- Loading {s.Value}");
status = $"Fetching app data tag: {s.Value}";
XElement ret = XDocument.Load(new Uri(s.Value).AbsoluteUri)
.Element("app");
return ret;
}))
.ToArray();
status = $"Creating app cache";
foreach (XElement app in tmpApparray)
{
//"Sanity check"
Version.Parse(app.Element("Version").Value);
Guid.Parse(app.Element("ID").Value);
//Create XElement
tmpAppsList.Add(new XElement("App",
new XElement("Name", app.Element("Name").Value),
new XElement("Description", app.Element("Description").Value),
new XElement("Version", app.Element("Version").Value),
new XElement("ID", app.Element("ID").Value),
new XElement("File", new Uri(app.Element("File").Value).ToString()),
new XElement("Hash", app.Element("Hash").Value)
));
if (app.Element("MainFile") != null)
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
if (app.Element("Icon") != null)
try
{
tmpAppsList.Last()
.Add(new XElement("Icon",
_platform.FetchImageB64(new Uri(app.Element("Icon").Value))));
}
catch
{
// ignored
}
tmpAppsList.Last().Add(new XElement("Platform",
app.Element("Platform") == null ||
!new[] {PlatformCheck.Posix, PlatformCheck.Windows}.Contains(app.Element("Platform")
.Value)
? PlatformCheck.CurrentPlatform
: app.Element("Platform").Value));
XElement app1 = app;
if (tmpAppsList.Count(a => a.Element("ID").Value == app1.Element("ID").Value) > 1)
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse()
.Skip(1)
.ToList().ForEach(a => tmpAppsList.Remove(a));
}
#if !DEBUG
}
catch (Exception e)
{
_platform.OkDialog(
$"Failed to load repo: {repArr[i]}{Environment.NewLine}Last status was: {status}{Environment.NewLine}{e}");
}
#endif
i++;
}
tmpAppsList.Sort((x, y) =>
string.Compare(x.Element("Name").Value, y.Element("Name").Value, StringComparison.Ordinal));
if (meta.Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
XElement repos = meta.Element("LocalRepo");
repos.RemoveNodes();
tmpAppsList.ForEach(app => repos.Add(app));
meta.Save(_pathTool.InfoXml);
}
private Version GetVer(XElement el) =>
int.TryParse(el.Value, out int i) ? new Version(0, 0, 0, i) : Version.Parse(el.Value);
/// <summary>
/// Load the repository cache
/// </summary>
/// <param name="errorHandler">Function to call on an exception, will ask the user whether he wants to quit</param>
public void GetReposFromDisk()
{
_apps.Clear();
string xml = _pathTool.InfoXml;
XDocument.Load(xml).Element("meta").Element("LocalRepo").Elements().ToList().ForEach(app =>
{
if (app.Element("Platform").Value != PlatformCheck.CurrentPlatform) return;
Guid id = Guid.Parse(app.Element("ID").Value);
string locInPath = _pathTool.GetInfoPath(id);
XElement locIn = File.Exists(locInPath) ? XDocument.Load(locInPath).Element("app") : app;
if (int.TryParse(app.Element("Version").Value, out _))
app.Element("Version").Value = UpToolLibV1.MinimumVer.ToString();
_apps.Add(id, _appFactory.CreateApp(
locIn.Element("Name").Value,
locIn.Element("Description").Value,
Version.Parse(app.Element("Version").Value),
app.Element("File").Value,
false,
app.Element("Hash").Value,
id,
Color.White,
app.Element("Icon") == null
? _platform.GetDefaultIcon()
: _platform.ImageFromB64(app.Element("Icon").Value),
locIn.Element("MainFile") != null || app.Element("MainFile") != null,
locIn.Element("MainFile") == null
? app.Element("MainFile") == null ? "" : app.Element("MainFile").Value
: locIn.Element("MainFile").Value
));
});
Directory.GetDirectories(_pathTool.AppsPath)
.Where(s => Guid.TryParse(Path.GetFileName(s), out Guid guid) &&
!_apps.ContainsKey(guid)).ToList().ForEach(s =>
{
Guid tmp = Guid.Parse(Path.GetFileName(s));
try
{
XElement data = XDocument.Load(_pathTool.GetInfoPath(tmp)).Element("app");
_apps.Add(tmp,
_appFactory.CreateApp($"(local) {data.Element("Name").Value}", data.Element("Description").Value,
UpToolLibV1.MinimumVer, "", true, "", tmp, Color.Red,
_platform.GetDefaultIcon(),
data.Element("MainFile") != null,
data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
catch (Exception e)
{
if (_platform.YesNoDialog(
$@"An error occured while loading this local repo:
{e.Message}
Do you want to exit? Otherwise the folder will be deleted, possibly causeing problems later.", false))
Environment.Exit(0);
else
Directory.Delete(_pathTool.GetAppPath(tmp), true);
}
});
}
}
}

View File

@ -0,0 +1,13 @@
using UpToolLib.DataStructures;
namespace UpToolLib.v2.TaskQueue
{
public abstract class AppTask
{
public abstract void Run();
public AppTask(IExternalFunctionality platform) => Platform = platform;
protected IExternalFunctionality Platform { get; }
}
}

View File

@ -0,0 +1,43 @@
using System;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2.TaskQueue
{
public class InstallTask : KnownAppTask
{
private readonly AppInstall _installer;
private readonly Action? _postInstall;
internal InstallTask(IExternalFunctionality platform, AppInstall installer, App app, Action? postInstall) : base(platform)
{
App = app;
_installer = installer;
_postInstall = postInstall;
}
public override App App { get; }
public override void Run()
{
bool trying = true;
while (trying)
{
#if !DEBUG
try
{
#endif
_installer.Install(App, true);
_postInstall?.Invoke();
trying = false;
#if !DEBUG
}
catch (Exception e1)
{
trying = Platform.YesNoDialog("Install failed. Retry?\r\nException=" + e1, true);
}
#endif
}
}
}
}

View File

@ -0,0 +1,25 @@
using UpToolLib.DataStructures;
namespace UpToolLib.v2.TaskQueue
{
public abstract class KnownAppTask : AppTask
{
public abstract App App { get; }
public override string ToString() => $"{TrimEnd(GetType().Name, "Task")} {App.Name}";
private static string TrimEnd(string target, string trimString)
{
if (string.IsNullOrEmpty(trimString)) return target;
string result = target;
while (result.EndsWith(trimString)) result = result.Substring(0, result.Length - trimString.Length);
return result;
}
protected KnownAppTask(IExternalFunctionality platform) : base(platform)
{
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2.TaskQueue
{
public class RemoveTask : KnownAppTask
{
private readonly AppExtras _extras;
private readonly Action? _postInstall;
internal RemoveTask(IExternalFunctionality platform, AppExtras extras, App app, Action? postInstall) : base(platform)
{
App = app;
_extras = extras;
_postInstall = postInstall;
}
public override App App { get; }
public override void Run()
{
#if !DEBUG
try
{
#endif
_extras.Remove(App, true);
_postInstall?.Invoke();
#if !DEBUG
}
catch (Exception e1)
{
Platform.OkDialog("Removal failed.\r\nException=" + e1);
}
#endif
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2.TaskQueue
{
public class TaskFactory
{
private IExternalFunctionality _platform;
private readonly AppInstall _installer;
private readonly AppExtras _extras;
private readonly PathTool _pathTool;
private readonly AppFactory _appFactory;
private readonly IDictionary<Guid, App> _apps;
internal TaskFactory(IExternalFunctionality platform, AppInstall installer, AppExtras extras, PathTool pathTool, AppFactory appFactory, IDictionary<Guid, App> apps)
{
_platform = platform;
_installer = installer;
_extras = extras;
_pathTool = pathTool;
_appFactory = appFactory;
_apps = apps;
}
public KnownAppTask CreateInstall(App app, Action? postInstall = null) => new InstallTask(_platform, _installer, app, postInstall);
public KnownAppTask CreateRemove(App app, Action? postInstall = null) => new RemoveTask(_platform, _extras, app, postInstall);
public KnownAppTask CreateUpdate(App app, Action? postInstall = null) => new UpdateTask(_platform, _extras, app, postInstall);
public AppTask CreateUpload(string zipFile, string name, Action? postInstall = null) => new UploadTask(_platform, _installer, _appFactory, _pathTool, _apps, zipFile, name, postInstall);
}
}

View File

@ -0,0 +1,38 @@
using System;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2.TaskQueue
{
public class UpdateTask : KnownAppTask
{
private readonly AppExtras _extras;
private readonly Action? _postInstall;
internal UpdateTask(IExternalFunctionality platform, AppExtras extras, App app, Action? postInstall) : base(platform)
{
App = app;
_extras = extras;
_postInstall = postInstall;
}
public override App App { get; }
public override void Run()
{
#if !DEBUG
try
{
#endif
_extras.Update(App, false);
_postInstall?.Invoke();
#if !DEBUG
}
catch (Exception e1)
{
Platform.OkDialog("Update failed.\r\nException=" + e1);
}
#endif
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using UpToolLib.DataStructures;
using UpToolLib.v1;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2.TaskQueue
{
public class UploadTask : AppTask
{
private readonly string _name;
private readonly Action? _postInstall;
private readonly AppInstall _installer;
private readonly AppFactory _appFactory;
private readonly PathTool _pathTool;
private readonly IDictionary<Guid, App> _apps;
public readonly string ZipFile;
internal UploadTask(IExternalFunctionality platform, AppInstall installer, AppFactory appFactory, PathTool pathTool, IDictionary<Guid, App> apps, string zipFile, string name, Action? postInstall) : base(platform)
{
_installer = installer;
_appFactory = appFactory;
_pathTool = pathTool;
_apps = apps;
ZipFile = zipFile;
_name = name;
_postInstall = postInstall;
}
public override void Run()
{
#if !DEBUG
try
{
#endif
Guid id = Guid.NewGuid();
while (_apps.ContainsKey(id) || Directory.Exists(_pathTool.GetAppPath(id)))
id = Guid.NewGuid();
App appI = _appFactory.CreateApp(_name, "Locally installed package, removal only",
UpToolLibV1.MinimumVer, "", true, "", id, Color.Red, Platform.GetDefaultIcon(), false, "");
_installer.InstallZip(ZipFile, appI, true);
_postInstall?.Invoke();
#if !DEBUG
}
catch (Exception e1)
{
Platform.OkDialog("Upload failed.\r\nException=" + e1);
}
#endif
}
public override string ToString() => $"Install local {Path.GetFileName(ZipFile)}";
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2.TaskQueue;
namespace UpToolLib.v2
{
public class UpToolLibV2
{
internal UpToolLibV2(IExternalFunctionality platform, AppInstall install, AppExtras extras, PathTool pathTool, XmlTool xmlTool, IDictionary<Guid, App> apps)
{
AppFactory = new AppFactory(pathTool);
UpdateChecker = new UpdateChecker(pathTool);
TaskFactory = new TaskFactory(platform, install, extras, pathTool, AppFactory, apps);
RepoManagement = new RepoManagement(platform, xmlTool, pathTool, AppFactory, apps);
}
public readonly UpdateChecker UpdateChecker;
public readonly TaskFactory TaskFactory;
public readonly AppFactory AppFactory;
public readonly RepoManagement RepoManagement;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Xml.Linq;
namespace UpToolLib.v2
{
public class UpdateCheck
{
public readonly Version OnlineVersion;
public readonly Uri Installer;
public readonly string InstallerHash;
public readonly Uri App;
public readonly string AppHash;
public UpdateCheck(XElement meta)
{
OnlineVersion = Version.Parse(meta.Element("Version").Value);
Installer = new Uri(meta.Element("Installer").Value);
InstallerHash = meta.Element("InstallerHash").Value.ToUpper();
App = new Uri(meta.Element("File").Value);
AppHash = meta.Element("Hash").Value.ToUpper();
}
}
}

View File

@ -0,0 +1,13 @@
using System.Xml.Linq;
using UpToolLib.v1.Tool;
namespace UpToolLib.v2
{
public class UpdateChecker
{
private readonly PathTool _pathTool;
public UpdateCheck Check() => Check(XDocument.Load(_pathTool.InfoXml).Element("meta").Element("UpdateSource").Value);
public UpdateCheck Check(string source) => new(XDocument.Load(source).Element("meta"));
internal UpdateChecker(PathTool pathTool) => _pathTool = pathTool;
}
}

13
renovate.json Normal file
View File

@ -0,0 +1,13 @@
{
"extends": [
"config:base"
],
"hostRules": [
{
"domainName": "github.com",
"encrypted": {
"token": "o53wjvsApqgx2krTKwD5LBnbmtK7gZ4zgAYsFIxLxf3blIMY2y9tUpsVNo4thY/kTA1tDOvIiP9PNdJV/DRYqvMDQMxvKiGHE1eSrpmrICRaq4Bhdc9/QZotkliqcziynLV0vD+xXZ7tyXKhR+nZijp4K1H2euCAv8vCVAUrpXIlBf/gmHvfEjmTDKUqJTEAvzre7H7l3C7SmQ2VwyE6gEFD91K9jGbgfI6MIgjx3i3O4fxM/JLXmUR19mGVK//Hpc1GXyVePB1sdzYhsyMU/3hzR3d/lJLOrHhr40WO1vNf3aB0WVDqqsl+XwoFxBxFqhSPTVHkEsylD+l+d8fsXA=="
}
}
]
}