From a361285d628ec79c1bdb7b96436d09ab55b4f256 Mon Sep 17 00:00:00 2001 From: STAM Date: Sat, 7 Oct 2023 03:02:45 +0300 Subject: [PATCH 1/7] gha fixes --- .github/workflows/dotnet-develop.yml | 1 - .github/workflows/dotnet-master.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/dotnet-develop.yml b/.github/workflows/dotnet-develop.yml index 0341795..93d6519 100644 --- a/.github/workflows/dotnet-develop.yml +++ b/.github/workflows/dotnet-develop.yml @@ -20,7 +20,6 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: '6.0.x' - include-prerelease: true - name: Restore env: diff --git a/.github/workflows/dotnet-master.yml b/.github/workflows/dotnet-master.yml index 8cf19b8..811721f 100644 --- a/.github/workflows/dotnet-master.yml +++ b/.github/workflows/dotnet-master.yml @@ -19,7 +19,6 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: '6.0.x' - include-prerelease: true - name: Restore env: From c2d6260d61fb0fdb7f8e1d800a41c5e0ac7837dd Mon Sep 17 00:00:00 2001 From: STAM Date: Wed, 11 Oct 2023 16:36:59 +0300 Subject: [PATCH 2/7] dotnet8 draft switch x BROKEN x --- src/atlassian-downloader.csproj | 31 +++++++-------- src/build.bat | 69 ++++++++++++++++++-------------- src/build.sh | 70 +++++++++++++++++++-------------- 3 files changed, 94 insertions(+), 76 deletions(-) diff --git a/src/atlassian-downloader.csproj b/src/atlassian-downloader.csproj index df4d620..062e11a 100644 --- a/src/atlassian-downloader.csproj +++ b/src/atlassian-downloader.csproj @@ -1,5 +1,4 @@  - Exe true @@ -8,7 +7,7 @@ win-x64 true true - net6.0 + net8.0 favicon.ico EpicMorg.Atlassian.Downloader EpicMorg, kasthack, stam @@ -27,32 +26,30 @@ EpicMorg README.md - - - - - - - - - - - + + + + + True \ True - + + + + + + + - Always - - + \ No newline at end of file diff --git a/src/build.bat b/src/build.bat index 6ff5a3a..34b3f42 100644 --- a/src/build.bat +++ b/src/build.bat @@ -1,36 +1,47 @@ SET DOTNET_CLI_TELEMETRY_OPTOUT=true SET DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true -dotnet.exe publish --runtime win7-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime win7-x86 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime win81-arm --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime win10-arm64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime linux-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-musl-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime osx-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime win-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet.exe publish --runtime win-x86 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet.exe publish --runtime win-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet.exe publish --runtime osx-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime osx-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime linux-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime linux-musl-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime linux-arm --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime linux-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish --runtime linux-bionic-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -del /F bin\\Release\\net6.0\\linux-musl-x64\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\linux-x64\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\osx-x64\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\win10-arm64\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\win7-x64\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\win7-x86\\publish\\atlassian-downloader.pdb -del /F bin\\Release\\net6.0\\win81-arm\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\win-x64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\win-x86\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\win-arm64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\osx-x64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\osx-arm64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\linux-x64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\linux-musl-x64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\linux-arm\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\linux-arm64\\publish\\atlassian-downloader.pdb +del /F bin\\Release\\net8.0\\linux-bionic-x64\\publish\\atlassian-downloader.pdb -type nul > bin/Release/net6.0/linux-musl-x64/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/linux-x64/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/osx-x64/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/win10-arm64/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/win7-x64/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/win7-x86/publish/createdump.exe.ignore -type nul > bin/Release/net6.0/win81-arm/publish/createdump.exe.ignore - -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-linux-musl-x64.zip ./bin/Release/net6.0/linux-musl-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-linux-x64.zip ./bin/Release/net6.0/linux-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-osx-x64.zip ./bin/Release/net6.0/osx-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win10-arm64.zip ./bin/Release/net6.0/win10-arm64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win7-x64.zip ./bin/Release/net6.0/win7-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win7-x86.zip ./bin/Release/net6.0/win7-x86/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win81-arm.zip ./bin/Release/net6.0/win81-arm/publish/* +type nul > bin/Release/net8.0/win-x64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/win-x86/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/win-arm64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/osx-x64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/osx-arm64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/linux-x64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/linux-musl-x64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/linux-arm/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/linux-arm64/publish/createdump.exe.ignore +type nul > bin/Release/net8.0/linux-bionic-x64/publish/createdump.exe.ignore +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-x64.zip ./bin/Release/net8.0/win-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-x86.zip ./bin/Release/net8.0/win-x86/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-arm64.zip ./bin/Release/net8.0/win-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-osx-x64.zip ./bin/Release/net8.0/osx-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-osx-arm64.zip ./bin/Release/net8.0/osx-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-x64.zip ./bin/Release/net8.0/linux-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-musl-x64.zip ./bin/Release/net8.0/linux-musl-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-arm.zip ./bin/Release/net8.0/linux-arm/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-arm64.zip ./bin/Release/net8.0/linux-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-bionic-x64.zip ./bin/Release/net8.0/linux-bionic-x64/publish/* diff --git a/src/build.sh b/src/build.sh index 219374a..679cc95 100644 --- a/src/build.sh +++ b/src/build.sh @@ -2,36 +2,46 @@ export DOTNET_CLI_TELEMETRY_OPTOUT=true export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true -dotnet publish --runtime win7-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime win7-x86 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime win81-arm --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime win10-arm64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime linux-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime linux-musl-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime osx-x64 --force --self-contained true --framework net6.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish --runtime win-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet publish --runtime win-x86 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet publish --runtime win-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true +dotnet publish --runtime osx-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish --runtime osx-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish --runtime linux-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=fal +dotnet publish --runtime linux-musl-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=falsese +dotnet publish --runtime linux-arm --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish --runtime linux-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish --runtime linux-bionic-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -rm -rfv ./bin/Release/net6.0/linux-musl-x64/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/linux-x64/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/osx-x64/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/win10-arm64/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/win7-x64/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/win7-x86/publish/atlassian-downloader.pdb -rm -rfv ./bin/Release/net6.0/win81-arm/publish/atlassian-downloader.pdb - -touch ./bin/Release/net6.0/linux-musl-x64/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/linux-x64/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/osx-x64/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/win10-arm64/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/win7-x64/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/win7-x86/publish/createdump.exe.ignore -touch ./bin/Release/net6.0/win81-arm/publish/createdump.exe.ignore - -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-linux-musl-x64.zip ././bin/Release/net6.0/linux-musl-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-linux-x64.zip ././bin/Release/net6.0/linux-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-osx-x64.zip ././bin/Release/net6.0/osx-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win10-arm64.zip ././bin/Release/net6.0/win10-arm64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win7-x64.zip ././bin/Release/net6.0/win7-x64/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win7-x86.zip ././bin/Release/net6.0/win7-x86/publish/* -7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net6.0-win81-arm.zip ././bin/Release/net6.0/win81-arm/publish/* +rm -rfv ./bin/Release/net8.0/win-x64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/win-x86/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/win-arm64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/osx-x64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/osx-arm64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/linux-x64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/linux-musl-x64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/linux-arm/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/linux-arm64/publish/atlassian-downloader.pdb +rm -rfv ./bin/Release/net8.0/linux-bionic-x64/publish/atlassian-downloader.pdb +touch ./bin/Release/net8.0/win-x64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/win-x86/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/win-arm64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/osx-x64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/osx-arm64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/linux-x64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/linux-musl-x64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/linux-arm/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/linux-arm64/publish/createdump.exe.ignore +touch ./bin/Release/net8.0/linux-bionic-x64/publish/createdump.exe.ignore +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-x64.zip ././bin/Release/net8.0/win-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-x86.zip ././bin/Release/net8.0/win-x86/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-win-arm64.zip ././bin/Release/net8.0/win-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-osx-x64.zip ././bin/Release/net8.0/osx-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-osx-arm64.zip ././bin/Release/net8.0/osx-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-x64.zip ././bin/Release/net8.0/linux-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-musl-x64.zip ././bin/Release/net8.0/linu-musl-x64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-arm.zip ././bin/Release/net8.0/linux-arm/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-arm64.zip ././bin/Release/net8.0/linux-arm64/publish/* +7z a -tzip -mx5 -r0 ./bin/atlassian-downloader-net8.0-linux-bionic-x64.zip ././bin/Release/net8.0/linu-bionic-x64/publish/* From 00000a2119b2fc56c908608253dca4ab33934e2a Mon Sep 17 00:00:00 2001 From: Konstantin Safonov Date: Thu, 12 Oct 2023 23:33:26 +0300 Subject: [PATCH 3/7] Fix #36: restore args parsing. Move bells and whistles from downloader service Apply code styles. Fix exception when parsing json Move sources to a separate type --- src/Core/BellsAndWhistles.cs | 116 ++++++++ src/Core/DownloaderService.cs | 233 ++++++++++++++++ src/DonloaderService.cs | 410 ----------------------------- src/Models/DownloadAction.cs | 41 ++- src/Models/DownloaderOptions.cs | 8 +- src/Models/ResponseItem.cs | 40 +-- src/Models/SourceInformation.cs | 85 ++++++ src/Program.cs | 81 +++--- src/Properties/launchSettings.json | 3 +- src/atlassian-downloader.csproj | 28 +- 10 files changed, 531 insertions(+), 514 deletions(-) create mode 100644 src/Core/BellsAndWhistles.cs create mode 100644 src/Core/DownloaderService.cs delete mode 100644 src/DonloaderService.cs create mode 100644 src/Models/SourceInformation.cs diff --git a/src/Core/BellsAndWhistles.cs b/src/Core/BellsAndWhistles.cs new file mode 100644 index 0000000..e3619c2 --- /dev/null +++ b/src/Core/BellsAndWhistles.cs @@ -0,0 +1,116 @@ +namespace EpicMorg.Atlassian.Downloader.Models; + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; + +using Microsoft.Extensions.Logging; + +internal class BellsAndWhistles +{ + private static readonly string assemblyEnvironment = string.Format("[{1}, {0}]", RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(), RuntimeInformation.FrameworkDescription); + + private static readonly Assembly entryAssembly = Assembly.GetEntryAssembly(); + + private static readonly string assemblyVersion = entryAssembly.GetCustomAttribute().InformationalVersion; + + private static readonly string fileVersion = entryAssembly.GetCustomAttribute().Version; + + private static readonly string assemblyName = entryAssembly.GetCustomAttribute().Product; + const string assemblyBuildType = +#if DEBUG + "[Debug]" +#else + + "[Release]" +#endif + ; + + private const ConsoleColor DEFAULT = ConsoleColor.Blue; + + public static void ShowVersionInfo(ILogger logger) + { + logger.LogInformation($"{assemblyName} {assemblyVersion} {assemblyEnvironment} {assemblyBuildType}"); + Console.BackgroundColor = ConsoleColor.Black; + WriteColorLine("%╔═╦═══════════════════════════════════════════════════════════════════════════════════════╦═╗"); + WriteColorLine("%╠═╝ .''. %╚═%╣"); + WriteColorLine("%║ .:cc;. %║"); + WriteColorLine("%║ .;cccc;. %║"); + WriteColorLine("%║ .;cccccc;. !╔══════════════════════════════════════════════╗ %║"); + WriteColorLine($"%║ .:ccccccc;. !║ {assemblyName} !║ %║"); + WriteColorLine("%║ 'ccccccccc;. !╠══════════════════════════════════════════════╣ %║"); + WriteColorLine("%║ ,cccccccccc;. !║ &Code: @kasthack !║ %║"); + WriteColorLine("%║ ,ccccccccccc;. !║ &GFX: @stam !║ %║"); + WriteColorLine("%║ .... .:ccccccccccc;. !╠══════════════════════════════════════════════╣ %║"); + WriteColorLine($"%║ .',,'..;cccccccccccc;. !║ &Version: {fileVersion} !║ %║"); + WriteColorLine("%║ .,,,,,'.';cccccccccccc;. !║ &GitHub: $EpicMorg/atlassian-downloader !║ %║"); + WriteColorLine("%║ .,;;;;;,'.':cccccccccccc;. !╚══════════════════════════════════════════════╝ %║"); + WriteColorLine("%║ .;:;;;;;;,...:cccccccccccc;. %║"); + WriteColorLine("%║ .;:::::;;;;'. .;:ccccccccccc;. %║"); + WriteColorLine("%║ .:cc::::::::,. ..:ccccccccccc;. %║"); + WriteColorLine("%║ .:cccccc:::::' .:ccccccccccc;. %║"); + WriteColorLine("%║ .;:::::::::::,. .;:::::::::::,. %║"); + WriteColorLine("%╠═╗ ............ ............ %╔═╣"); + WriteColorLine("%╚═╩═══════════════════════════════════════════════════════════════════════════════════════╩═╝"); + Console.ResetColor(); + } + public static void SetConsoleTitle() => Console.Title = $@"{assemblyName} {assemblyVersion} {assemblyEnvironment} - {assemblyBuildType}"; + + private static void WriteColorLine(string text, params object[] args) + { + Dictionary colors = new() + { + { '!', ConsoleColor.Red }, + { '@', ConsoleColor.Green }, + { '#', ConsoleColor.Blue }, + { '$', ConsoleColor.Magenta }, + { '&', ConsoleColor.Yellow }, + { '%', ConsoleColor.Cyan } + }; + // TODO: word wrap, backslash escapes + text = string.Format(text, args); + var chunk = ""; + var paren = false; + for (var i = 0; i < text.Length; i++) + { + var c = text[i]; + if (colors.ContainsKey(c) && StringNext(text, i) != ' ') + { + Console.Write(chunk); + chunk = ""; + if (StringNext(text, i) == '(') + { + i++; // skip past the paren + paren = true; + } + + Console.ForegroundColor = colors[c]; + } + else if (paren && c == ')') + { + paren = false; + Console.ForegroundColor = DEFAULT; + } + else if (Console.ForegroundColor != DEFAULT) + { + Console.Write(c); + if (c == ' ' && !paren) + { + Console.ForegroundColor = DEFAULT; + } + } + else + { + chunk += c; + } + } + + Console.WriteLine(chunk); + Console.ForegroundColor = DEFAULT; + } + + private static char StringNext(string text, int index) => index < text.Length ? text[index + 1] : '\0'; + +} + diff --git a/src/Core/DownloaderService.cs b/src/Core/DownloaderService.cs new file mode 100644 index 0000000..9e9c10b --- /dev/null +++ b/src/Core/DownloaderService.cs @@ -0,0 +1,233 @@ +namespace EpicMorg.Atlassian.Downloader.Core; + +using EpicMorg.Atlassian.Downloader.Models; + +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +internal class DownloaderService : IHostedService +{ + private readonly string UserAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0"; + + private readonly ILogger logger; + private readonly DownloaderOptions options; + private readonly HttpClient client; + private readonly IHostApplicationLifetime hostApplicationLifetime; + + public DownloaderService(IHostApplicationLifetime hostApplicationLifetime, ILogger logger, HttpClient client, DownloaderOptions options) + { + this.logger = logger; + this.client = client; + client.DefaultRequestHeaders.Add("User-Agent", this.UserAgentString); + this.options = options; + this.hostApplicationLifetime = hostApplicationLifetime; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + BellsAndWhistles.SetConsoleTitle(); + BellsAndWhistles.ShowVersionInfo(this.logger); + + if (!this.options.Version && !string.IsNullOrWhiteSpace(this.options.OutputDir)) + { + var feedUrls = this.GetFeedUrls(); + + this.logger.LogInformation($"Task started"); + foreach (var feedUrl in feedUrls) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var (json, versions) = await this.GetJson(feedUrl, this.options.ProductVersion, cancellationToken).ConfigureAwait(false); + + switch (this.options.Action) + { + case DownloadAction.ShowRawJson: + Console.Out.WriteLine(json); + break; + case DownloadAction.Download: + await this.DownloadFilesFromFeed(feedUrl, versions, cancellationToken).ConfigureAwait(false); + break; + case DownloadAction.ListURLs: + foreach (var versionProg in versions) + { + foreach (var file in versionProg.Value) + { + Console.Out.WriteLine(file.ZipUrl); + } + } + + break; + case DownloadAction.ListVersions: + foreach (var versionProg in versions) + { + foreach (var file in versionProg.Value) + { + Console.Out.WriteLine(file.Version); + } + } + + break; + } + } + } + + this.logger.LogInformation($"Complete"); + + this.hostApplicationLifetime.StopApplication(); + } + + private async Task<(string json, IDictionary versions)> GetJson(string feedUrl, string productVersion = null, CancellationToken cancellationToken = default) + { + var atlassianJson = await this.client.GetStringAsync(feedUrl, cancellationToken).ConfigureAwait(false); + var json = atlassianJson.Trim()["downloads(".Length..^1]; + this.logger.LogTrace("Downloaded json: {0}", json); + var parsed = JsonSerializer.Deserialize(json, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + this.logger.LogDebug("Found {releaseCount} releases", parsed.Length); + var versions = parsed + .GroupBy(a => a.Version) + .Where(a => productVersion is null || a.Key == productVersion) + .ToDictionary(a => a.Key, a => a.ToArray()); + this.logger.LogDebug("Found {releaseCount} releases", versions.Count); + return (json, versions); + } + + private IReadOnlyList GetFeedUrls() => this.options.CustomFeed != null + ? this.options.CustomFeed.Select(a => a.ToString()).ToArray() + : SourceInformation.AtlassianSources; + + private async Task DownloadFilesFromFeed(string feedUrl, IDictionary versions, CancellationToken cancellationToken) + { + + var feedDir = Path.Combine(this.options.OutputDir, feedUrl[(feedUrl.LastIndexOf('/') + 1)..feedUrl.LastIndexOf('.')]); + this.logger.LogInformation("Download from JSON \"{feedUrl}\" started", feedUrl); + foreach (var version in versions) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var directory = Path.Combine(feedDir, version.Key); + if (!Directory.Exists(directory)) + { + _ = Directory.CreateDirectory(directory); + } + + foreach (var file in version.Value) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + if (file.ZipUrl == null) + { + this.logger.LogWarning($"Empty ZipUrl found for version '{version.Key}' in {feedUrl}"); + continue; + } + + var serverPath = file.ZipUrl.PathAndQuery; + var outputFile = Path.Combine(directory, serverPath[(serverPath.LastIndexOf('/') + 1)..]); + if (!File.Exists(outputFile)) + { + await this.DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); + } + else + { + this.logger.LogWarning($"File \"{outputFile}\" already exists. File sizes will be compared."); + var localFileSize = new FileInfo(outputFile).Length; + this.logger.LogInformation($"Size of local file is {localFileSize} bytes."); + try + { + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("User-Agent", this.UserAgentString); + var response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, file.ZipUrl)); + if (response.IsSuccessStatusCode) + { + if (response.Content.Headers.ContentLength.HasValue) + { + var remoteFileSize = response.Content.Headers.ContentLength.Value; + this.logger.LogInformation($"Size of remote file is \"{remoteFileSize}\" bytes."); + + if (remoteFileSize == localFileSize) + { + this.logger.LogInformation($"Size of remote and local files and are same ({remoteFileSize} bytes and {localFileSize} bytes). Nothing to download. Operation skipped."); + } + else + { + this.logger.LogWarning($"Size of remote and local files and are not same ({remoteFileSize} bytes and {localFileSize} bytes). Download started."); + File.Delete(outputFile); + await this.DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); + } + } + else + { + this.logger.LogWarning($"Cant get size of remote file \"{file.ZipUrl}\". May be server not support it feature. Sorry."); + continue; + } + } + else + { + this.logger.LogCritical($"Request execution error: \"{response.StatusCode}\". Sorry."); + } + } + catch (HttpRequestException ex) + { + this.logger.LogCritical($"HTTP request error: \"{ex.Message}\", \"{ex.StackTrace}\", \"{ex.StatusCode}\". Sorry."); + } + } + } + } + + this.logger.LogInformation($"All files from \"{feedUrl}\" successfully downloaded."); + + } + + private async Task DownloadFile(ResponseItem file, string outputFile, CancellationToken cancellationToken) + { + if (!string.IsNullOrEmpty(file.Md5)) + { + File.WriteAllText(outputFile + ".md5", file.Md5); + } + + try + { + using var outputStream = File.OpenWrite(outputFile); + using var request = await this.client.GetStreamAsync(file.ZipUrl, cancellationToken).ConfigureAwait(false); + await request.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); + } + catch (Exception downloadEx) + { + this.logger.LogError(downloadEx, "Failed to download file \"{uri}\" to \"{outputFile}\".", file.ZipUrl, outputFile); + try + { + File.Delete(outputFile); + } + catch (Exception removeEx) + { + this.logger.LogError(removeEx, $"Failed to remove incomplete file \"{outputFile}\"."); + } + } + + this.logger.LogInformation($"File \"{file.ZipUrl}\" successfully downloaded to \"{outputFile}\"."); + } + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + public async Task StopAsync(CancellationToken cancellationToken) { } +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously +} diff --git a/src/DonloaderService.cs b/src/DonloaderService.cs deleted file mode 100644 index 64fabc7..0000000 --- a/src/DonloaderService.cs +++ /dev/null @@ -1,410 +0,0 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Reflection; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace EpicMorg.Atlassian.Downloader -{ - class DonloaderService : IHostedService - { - private readonly string UserAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0"; - - private readonly ILogger logger; - private readonly DownloaderOptions options; - private readonly HttpClient client; - private readonly IHostApplicationLifetime hostApplicationLifetime; - private readonly string assemblyEnvironment = string.Format("[{1}, {0}]", - System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(), - System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription); - private readonly string assemblyVersion = Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion; - - private readonly string fileVersion = Assembly.GetEntryAssembly().GetCustomAttribute().Version; - - private readonly string assemblyName = Assembly.GetEntryAssembly().GetCustomAttribute().Product; - const string assemblyBuildType = -#if DEBUG - "[Debug]" -#else - - "[Release]" -#endif - ; - - public DonloaderService(IHostApplicationLifetime hostApplicationLifetime, ILogger logger, HttpClient client, DownloaderOptions options) - { - this.logger = logger; - this.client = client; - client.DefaultRequestHeaders.Add("User-Agent", UserAgentString); - this.options = options; - this.hostApplicationLifetime = hostApplicationLifetime; - } - public const ConsoleColor DEFAULT = ConsoleColor.Blue; - - public static void WriteColorLine(string text, params object[] args) - { - Dictionary colors = new() - { - { '!', ConsoleColor.Red }, - { '@', ConsoleColor.Green }, - { '#', ConsoleColor.Blue }, - { '$', ConsoleColor.Magenta }, - { '&', ConsoleColor.Yellow }, - { '%', ConsoleColor.Cyan } - }; - // TODO: word wrap, backslash escapes - text = string.Format(text, args); - string chunk = ""; - bool paren = false; - for (int i = 0; i < text.Length; i++) - { - char c = text[i]; - if (colors.ContainsKey(c) && StringNext(text, i) != ' ') - { - Console.Write(chunk); - chunk = ""; - if (StringNext(text, i) == '(') - { - i++; // skip past the paren - paren = true; - } - Console.ForegroundColor = colors[c]; - } - else if (paren && c == ')') - { - paren = false; - Console.ForegroundColor = DEFAULT; - } - else if (Console.ForegroundColor != DEFAULT) - { - Console.Write(c); - if (c == ' ' && !paren) - Console.ForegroundColor = DEFAULT; - } - else - chunk += c; - } - Console.WriteLine(chunk); - Console.ForegroundColor = DEFAULT; - } - - public static char StringPrev(string text, int index) - { - return (index == 0 || text.Length == 0) ? '\0' : text[index - 1]; - } - - public static char StringNext(string text, int index) - { - return (index < text.Length) ? text[index + 1] : '\0'; - } - - public async Task StartAsync(CancellationToken cancellationToken) - { - SetConsoleTitle(); - if (options.Version || string.IsNullOrWhiteSpace(options.OutputDir)) - { - ShowVersionInfo(); - } - else - { - var feedUrls = this.GetFeedUrls(); - - ShowVersionInfo(); - logger.LogInformation($"Task started"); - foreach (var feedUrl in feedUrls) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - var (json, versions) = await this.GetJson(feedUrl, options.ProductVersion, cancellationToken).ConfigureAwait(false); - - switch (options.Action) - { - case DownloadAction.ShowRawJson: - Console.Out.WriteLine(json); - break; - case DownloadAction.Download: - await this.DownloadFilesFromFeed(feedUrl, versions, cancellationToken).ConfigureAwait(false); - break; - case DownloadAction.ListURLs: - foreach (var versionProg in versions) - { - foreach (var file in versionProg.Value) - { - Console.Out.WriteLine(file.ZipUrl); - } - } - break; - case DownloadAction.ListVersions: - foreach (var versionProg in versions) - { - foreach (var file in versionProg.Value) - { - Console.Out.WriteLine(file.Version); - } - } - break; - } - } - } - logger.LogInformation($"Complete"); - - this.hostApplicationLifetime.StopApplication(); - } - - private void ShowVersionInfo() - { - logger.LogInformation($"{assemblyName} {assemblyVersion} {assemblyEnvironment} {assemblyBuildType}"); - Console.BackgroundColor = ConsoleColor.Black; - WriteColorLine("%╔═╦═══════════════════════════════════════════════════════════════════════════════════════╦═╗"); - WriteColorLine("%╠═╝ .''. %╚═%╣"); - WriteColorLine("%║ .:cc;. %║"); - WriteColorLine("%║ .;cccc;. %║"); - WriteColorLine("%║ .;cccccc;. !╔══════════════════════════════════════════════╗ %║"); - WriteColorLine("%║ .:ccccccc;. !║ " + assemblyName + " !║ %║"); - WriteColorLine("%║ 'ccccccccc;. !╠══════════════════════════════════════════════╣ %║"); - WriteColorLine("%║ ,cccccccccc;. !║ &Code: @kasthack !║ %║"); - WriteColorLine("%║ ,ccccccccccc;. !║ &GFX: @stam !║ %║"); - WriteColorLine("%║ .... .:ccccccccccc;. !╠══════════════════════════════════════════════╣ %║"); - WriteColorLine("%║ .',,'..;cccccccccccc;. !║ &Version: " + fileVersion + " !║ %║"); - WriteColorLine("%║ .,,,,,'.';cccccccccccc;. !║ &GitHub: $EpicMorg/atlassian-downloader !║ %║"); - WriteColorLine("%║ .,;;;;;,'.':cccccccccccc;. !╚══════════════════════════════════════════════╝ %║"); - WriteColorLine("%║ .;:;;;;;;,...:cccccccccccc;. %║"); - WriteColorLine("%║ .;:::::;;;;'. .;:ccccccccccc;. %║"); - WriteColorLine("%║ .:cc::::::::,. ..:ccccccccccc;. %║"); - WriteColorLine("%║ .:cccccc:::::' .:ccccccccccc;. %║"); - WriteColorLine("%║ .;:::::::::::,. .;:::::::::::,. %║"); - WriteColorLine("%╠═╗ ............ ............ %╔═╣"); - WriteColorLine("%╚═╩═══════════════════════════════════════════════════════════════════════════════════════╩═╝"); - Console.ResetColor(); - } - - private async Task<(string json, IDictionary versions)> GetJson(string feedUrl, string? productVersion = null, CancellationToken cancellationToken = default) - { - var atlassianJson = await client.GetStringAsync(feedUrl, cancellationToken).ConfigureAwait(false); - var json = atlassianJson.Trim()["downloads(".Length..^1]; - logger.LogTrace("Downloaded json: {0}", json); - var parsed = JsonSerializer.Deserialize(json, new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }); - logger.LogDebug("Found {0} releases", parsed.Length); - var versions = parsed - .GroupBy(a => a.Version) - .Where(a => productVersion is null || a.Key == productVersion) - .ToDictionary(a => a.Key, a => a.ToArray()); - logger.LogDebug("Found {0} releases", versions.Count); - return (json, versions); - } - - private string[] GetFeedUrls() => options.CustomFeed != null - ? options.CustomFeed.Select(a => a.ToString()).ToArray() - : new[] { - - //official links - "https://my.atlassian.com/download/feeds/archived/bamboo.json", - "https://my.atlassian.com/download/feeds/archived/clover.json", - "https://my.atlassian.com/download/feeds/archived/confluence.json", - "https://my.atlassian.com/download/feeds/archived/crowd.json", - "https://my.atlassian.com/download/feeds/archived/crucible.json", - "https://my.atlassian.com/download/feeds/archived/fisheye.json", - "https://my.atlassian.com/download/feeds/archived/jira-core.json", - "https://my.atlassian.com/download/feeds/archived/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/archived/jira-software.json", - "https://my.atlassian.com/download/feeds/archived/jira.json", - "https://my.atlassian.com/download/feeds/archived/stash.json", - "https://my.atlassian.com/download/feeds/archived/mesh.json", - - //cdn mirror of official links - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/bamboo.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/clover.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/confluence.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/crowd.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/crucible.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/fisheye.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-core.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-servicedesk.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-software.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/stash.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/mesh.json", - - //official links - "https://my.atlassian.com/download/feeds/current/bamboo.json", - "https://my.atlassian.com/download/feeds/current/clover.json", - "https://my.atlassian.com/download/feeds/current/confluence.json", - "https://my.atlassian.com/download/feeds/current/crowd.json", - "https://my.atlassian.com/download/feeds/current/crucible.json", - "https://my.atlassian.com/download/feeds/current/fisheye.json", - "https://my.atlassian.com/download/feeds/current/jira-core.json", - "https://my.atlassian.com/download/feeds/current/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/current/jira-software.json", - "https://my.atlassian.com/download/feeds/current/stash.json", - "https://my.atlassian.com/download/feeds/current/mesh.json", - - //cdn mirror of official links - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/bamboo.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/clover.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/confluence.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/crowd.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/crucible.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/fisheye.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-core.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-servicedesk.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-software.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/stash.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/mesh.json", - - //official links - "https://my.atlassian.com/download/feeds/eap/bamboo.json", - "https://my.atlassian.com/download/feeds/eap/confluence.json", - "https://my.atlassian.com/download/feeds/eap/jira.json", - "https://my.atlassian.com/download/feeds/eap/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/eap/stash.json", - //"https://my.atlassian.com/download/feeds/eap/mesh.json", //404 - - //cdn mirror of official links - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/bamboo.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/confluence.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/jira.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/jira-servicedesk.json", - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/stash.json", - //"https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/mesh.json", //404 - - //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json //unstable link with r\l - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json", - - //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json //unstable link with r\l - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json" - - }; - - private void SetConsoleTitle() - { - Console.Title = $@"{assemblyName} {assemblyVersion} {assemblyEnvironment} - {assemblyBuildType}"; - } - - private async Task DownloadFilesFromFeed(string feedUrl, IDictionary versions, CancellationToken cancellationToken) - { - - var feedDir = Path.Combine(options.OutputDir, feedUrl[(feedUrl.LastIndexOf('/') + 1)..(feedUrl.LastIndexOf('.'))]); - logger.LogInformation($"Download from JSON \"{feedUrl}\" started"); - foreach (var version in versions) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var directory = Path.Combine(feedDir, version.Key); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - foreach (var file in version.Value) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - if (file.ZipUrl == null) - { - logger.LogWarning($"Empty ZipUrl found for version '{version.Key}' in {feedUrl}"); - continue; - } - var serverPath = file.ZipUrl.PathAndQuery; - var outputFile = Path.Combine(directory, serverPath[(serverPath.LastIndexOf("/") + 1)..]); - if (!File.Exists(outputFile)) - { - await DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); - } - else - { - logger.LogWarning($"File \"{outputFile}\" already exists. File sizes will be compared."); - long localFileSize = new System.IO.FileInfo(outputFile).Length; - logger.LogInformation($"Size of local file is {localFileSize} bytes."); - try - { - var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Add("User-Agent", UserAgentString); - HttpResponseMessage response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, file.ZipUrl)); - if (response.IsSuccessStatusCode) - { - if (response.Content.Headers.ContentLength.HasValue) - { - long remoteFileSize = response.Content.Headers.ContentLength.Value; - logger.LogInformation($"Size of remote file is \"{remoteFileSize}\" bytes."); - - if (remoteFileSize == localFileSize) { - logger.LogInformation($"Size of remote and local files and are same ({remoteFileSize} bytes and {localFileSize} bytes). Nothing to download. Operation skipped."); - } - else - { - logger.LogWarning($"Size of remote and local files and are not same ({remoteFileSize} bytes and {localFileSize} bytes). Download started."); - File.Delete(outputFile); - await DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); - } - - } - else - { - logger.LogWarning($"Cant get size of remote file \"{file.ZipUrl}\". May be server not support it feature. Sorry."); - continue; - } - } - else - { - logger.LogCritical($"Request execution error: \"{response.StatusCode}\". Sorry."); - } - } - catch (HttpRequestException ex) - { - logger.LogCritical($"HTTP request error: \"{ex.Message}\", \"{ex.StackTrace}\", \"{ex.StatusCode}\". Sorry."); - } - } - } - } - logger.LogInformation($"All files from \"{feedUrl}\" successfully downloaded."); - - } - - private async Task DownloadFile(ResponseItem file, string outputFile, CancellationToken cancellationToken) - { - if (!string.IsNullOrEmpty(file.Md5)) - { - File.WriteAllText(outputFile + ".md5", file.Md5); - } - try - { - using var outputStream = File.OpenWrite(outputFile); - using var request = await client.GetStreamAsync(file.ZipUrl, cancellationToken).ConfigureAwait(false); - await request.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); - } - catch (Exception downloadEx) - { - logger.LogError(downloadEx, $"Failed to download file \"{file.ZipUrl}\" to \"{outputFile}\"."); - try - { - File.Delete(outputFile); - } - catch (Exception removeEx) - { - logger.LogError(removeEx, $"Failed to remove incomplete file \"{outputFile}\"."); - } - } - logger.LogInformation($"File \"{file.ZipUrl}\" successfully downloaded to \"{outputFile}\"."); - } - -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - public async Task StopAsync(CancellationToken cancellationToken) { } -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - } -} diff --git a/src/Models/DownloadAction.cs b/src/Models/DownloadAction.cs index 97b3c5e..7772bdb 100644 --- a/src/Models/DownloadAction.cs +++ b/src/Models/DownloadAction.cs @@ -1,22 +1,21 @@ -namespace EpicMorg.Atlassian.Downloader -{ - public enum DownloadAction - { - /// - /// Download application files - /// - Download, - /// - /// Print download URLs and exit - /// - ListURLs, - /// - /// Print available application versions and exit - /// - ListVersions, - /// - /// Print feed JSONs to stdout and exit - /// - ShowRawJson, - } +namespace EpicMorg.Atlassian.Downloader; + +public enum DownloadAction +{ + /// + /// Download application files + /// + Download, + /// + /// Print download URLs and exit + /// + ListURLs, + /// + /// Print available application versions and exit + /// + ListVersions, + /// + /// Print feed JSONs to stdout and exit + /// + ShowRawJson, } \ No newline at end of file diff --git a/src/Models/DownloaderOptions.cs b/src/Models/DownloaderOptions.cs index 616423d..1b42621 100644 --- a/src/Models/DownloaderOptions.cs +++ b/src/Models/DownloaderOptions.cs @@ -1,6 +1,4 @@ -using System; +namespace EpicMorg.Atlassian.Downloader; +using System; -namespace EpicMorg.Atlassian.Downloader -{ - public record DownloaderOptions(string OutputDir, Uri[] CustomFeed, DownloadAction Action,bool Version, string ProductVersion) { } -} \ No newline at end of file +public record DownloaderOptions(string OutputDir, Uri[] CustomFeed, DownloadAction Action,bool Version, string ProductVersion) { } \ No newline at end of file diff --git a/src/Models/ResponseItem.cs b/src/Models/ResponseItem.cs index ce4e66e..3e0fff1 100644 --- a/src/Models/ResponseItem.cs +++ b/src/Models/ResponseItem.cs @@ -1,31 +1,19 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; +namespace EpicMorg.Atlassian.Downloader; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -namespace EpicMorg.Atlassian.Downloader +public partial class ResponseItem { - - public partial class ResponseItem - { - public string Description { get; set; } - public string Edition { get; set; } - public Uri ZipUrl { get; set; } - public object TarUrl { get; set; } - public string Md5 { get; set; } - public string Size { get; set; } - public string Released { get; set; } - public string Type { get; set; } - public string Platform { get; set; } - public string Version { get; set; } - public Uri ReleaseNotes { get; set; } - public Uri UpgradeNotes { get; set; } - } + public string Description { get; set; } + public string Edition { get; set; } + public Uri ZipUrl { get; set; } + public object TarUrl { get; set; } + public string Md5 { get; set; } + public string Size { get; set; } + public string Released { get; set; } + public string Type { get; set; } + public string Platform { get; set; } + public string Version { get; set; } + public Uri ReleaseNotes { get; set; } + public Uri UpgradeNotes { get; set; } } \ No newline at end of file diff --git a/src/Models/SourceInformation.cs b/src/Models/SourceInformation.cs new file mode 100644 index 0000000..47f68ee --- /dev/null +++ b/src/Models/SourceInformation.cs @@ -0,0 +1,85 @@ +namespace EpicMorg.Atlassian.Downloader.Models; +using System.Collections.Generic; + +internal static class SourceInformation +{ + public static IReadOnlyList AtlassianSources { get; } = new[] { + + //official links + "https://my.atlassian.com/download/feeds/archived/bamboo.json", + "https://my.atlassian.com/download/feeds/archived/clover.json", + "https://my.atlassian.com/download/feeds/archived/confluence.json", + "https://my.atlassian.com/download/feeds/archived/crowd.json", + "https://my.atlassian.com/download/feeds/archived/crucible.json", + "https://my.atlassian.com/download/feeds/archived/fisheye.json", + "https://my.atlassian.com/download/feeds/archived/jira-core.json", + "https://my.atlassian.com/download/feeds/archived/jira-servicedesk.json", + "https://my.atlassian.com/download/feeds/archived/jira-software.json", + "https://my.atlassian.com/download/feeds/archived/jira.json", + "https://my.atlassian.com/download/feeds/archived/stash.json", + "https://my.atlassian.com/download/feeds/archived/mesh.json", + + //cdn mirror of official links + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/bamboo.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/clover.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/confluence.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/crowd.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/crucible.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/fisheye.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-core.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-servicedesk.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira-software.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/jira.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/stash.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/mesh.json", + + //official links + "https://my.atlassian.com/download/feeds/current/bamboo.json", + "https://my.atlassian.com/download/feeds/current/clover.json", + "https://my.atlassian.com/download/feeds/current/confluence.json", + "https://my.atlassian.com/download/feeds/current/crowd.json", + "https://my.atlassian.com/download/feeds/current/crucible.json", + "https://my.atlassian.com/download/feeds/current/fisheye.json", + "https://my.atlassian.com/download/feeds/current/jira-core.json", + "https://my.atlassian.com/download/feeds/current/jira-servicedesk.json", + "https://my.atlassian.com/download/feeds/current/jira-software.json", + "https://my.atlassian.com/download/feeds/current/stash.json", + "https://my.atlassian.com/download/feeds/current/mesh.json", + + //cdn mirror of official links + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/bamboo.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/clover.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/confluence.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/crowd.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/crucible.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/fisheye.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-core.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-servicedesk.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/jira-software.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/stash.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/mesh.json", + + //official links + "https://my.atlassian.com/download/feeds/eap/bamboo.json", + "https://my.atlassian.com/download/feeds/eap/confluence.json", + "https://my.atlassian.com/download/feeds/eap/jira.json", + "https://my.atlassian.com/download/feeds/eap/jira-servicedesk.json", + "https://my.atlassian.com/download/feeds/eap/stash.json", + //"https://my.atlassian.com/download/feeds/eap/mesh.json", //404 + + //cdn mirror of official links + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/bamboo.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/confluence.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/jira.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/jira-servicedesk.json", + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/stash.json", + //"https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/eap/mesh.json", //404 + + //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json //unstable link with r\l + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json", + + //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json //unstable link with r\l + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json" + + }; +} diff --git a/src/Program.cs b/src/Program.cs index 32cb34c..9563ecb 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,4 +1,8 @@ -using Microsoft.Extensions.Configuration; +namespace EpicMorg.Atlassian.Downloader; + +using EpicMorg.Atlassian.Downloader.Core; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -6,47 +10,42 @@ using Serilog; using System; -using System.IO; -using System.Reflection; using System.Threading.Tasks; -namespace EpicMorg.Atlassian.Downloader +public class Program { - public class Program - { - /// - /// Atlassian archive downloader. See https://github.com/EpicMorg/atlassian-downloader for more info - /// - /// Action to perform - /// Override output directory to download - /// Override URIs to import - /// Show credits banner - /// Override target version to download some product. Advice: Use it with "customFeed". - static async Task Main(string OutputDir, Uri[] customFeed = null, DownloadAction Action = DownloadAction.Download, bool Version = false, string productVersion = null) => await - Host - .CreateDefaultBuilder() - .ConfigureHostConfiguration(configHost => configHost.AddEnvironmentVariables()) - .ConfigureAppConfiguration((ctx, configuration) => - configuration - .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true) - .AddEnvironmentVariables()) - .ConfigureServices((ctx, services) => services - .AddOptions() - .AddLogging(builder => - { - Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(ctx.Configuration) - .CreateLogger(); - builder - .ClearProviders() - .AddSerilog(dispose: true); - }) - .AddHostedService() - .AddSingleton(new DownloaderOptions(OutputDir, customFeed, Action, Version, productVersion)) - .AddHttpClient()) - .RunConsoleAsync() - .ConfigureAwait(false); - } + /// + /// Atlassian archive downloader. See https://github.com/EpicMorg/atlassian-downloader for more info + /// + /// Action to perform + /// Override output directory to download + /// Override URIs to import + /// Show credits banner + /// Override target version to download some product. Advice: Use it with "customFeed". + static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction action = DownloadAction.Download, bool about = false, string productVersion = null) => await + Host + .CreateDefaultBuilder() + .ConfigureHostConfiguration(configHost => configHost.AddEnvironmentVariables()) + .ConfigureAppConfiguration((ctx, configuration) => + configuration + .SetBasePath(System.AppContext.BaseDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true) + .AddEnvironmentVariables()) + .ConfigureServices((ctx, services) => services + .AddOptions() + .AddLogging(builder => + { + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(ctx.Configuration) + .CreateLogger(); + _ = builder + .ClearProviders() + .AddSerilog(dispose: true); + }) + .AddHostedService() + .AddSingleton(new DownloaderOptions(outputDir, customFeed, action, about, productVersion)) + .AddHttpClient()) + .RunConsoleAsync() + .ConfigureAwait(false); } \ No newline at end of file diff --git a/src/Properties/launchSettings.json b/src/Properties/launchSettings.json index 1ea6c9f..874b865 100644 --- a/src/Properties/launchSettings.json +++ b/src/Properties/launchSettings.json @@ -2,7 +2,8 @@ "profiles": { "atlassian-downloader": { "commandName": "Project", - "commandLineArgs": "--help" + //"commandLineArgs": "--help" + "commandLineArgs": "--action=ShowRawJson --output-dir=F:\\temp\\atlassian\\test1" } } } \ No newline at end of file diff --git a/src/atlassian-downloader.csproj b/src/atlassian-downloader.csproj index 062e11a..cfd5065 100644 --- a/src/atlassian-downloader.csproj +++ b/src/atlassian-downloader.csproj @@ -1,14 +1,22 @@  - Exe - true + + + false + false false true + false win-x64 - true - true + + + Exe net8.0 + false favicon.ico + + + EpicMorg.Atlassian.Downloader EpicMorg, kasthack, stam Atlassian Downloader by EpicMorg @@ -22,11 +30,16 @@ 1.1.0.0 EpicMorg 2023 Atlassian Downloader - true EpicMorg README.md + EpicMorg.Atlassian.Downloader + + + + + @@ -41,11 +54,6 @@ - - - - - From ce023a7358364e04cbe9a988d6d00c3c673fbcc5 Mon Sep 17 00:00:00 2001 From: STAM Date: Fri, 13 Oct 2023 01:03:20 +0300 Subject: [PATCH 4/7] Fix #38: build config migrated to publish profiles. --- CHANGELOG.md | 6 +++ README.md | 51 +++++++++++-------- .../PublishProfiles/linux-arm.pubxml | 19 +++++++ src/Properties/PublishProfiles/linux-arm.user | 6 +++ .../PublishProfiles/linux-arm64.pubxml | 19 +++++++ .../PublishProfiles/linux-arm64.user | 6 +++ .../PublishProfiles/linux-bionic-x64.pubxml | 19 +++++++ .../PublishProfiles/linux-bionic-x64.user | 6 +++ .../PublishProfiles/linux-musl-x64.pubxml | 19 +++++++ .../PublishProfiles/linux-musl-x64.user | 6 +++ .../PublishProfiles/linux-x64.pubxml | 19 +++++++ src/Properties/PublishProfiles/linux-x64.user | 6 +++ .../PublishProfiles/osx-arm64.pubxml | 19 +++++++ src/Properties/PublishProfiles/osx-arm64.user | 6 +++ src/Properties/PublishProfiles/osx-x64.pubxml | 19 +++++++ src/Properties/PublishProfiles/osx-x64.user | 6 +++ .../PublishProfiles/win-arm64.pubxml | 19 +++++++ src/Properties/PublishProfiles/win-arm64.user | 6 +++ src/Properties/PublishProfiles/win-x64.pubxml | 19 +++++++ .../PublishProfiles/win-x64.pubxml.user | 6 +++ src/Properties/PublishProfiles/win-x86.pubxml | 20 ++++++++ .../PublishProfiles/win-x86.pubxml.user | 6 +++ src/build.bat | 20 ++++---- src/build.sh | 20 ++++---- 24 files changed, 308 insertions(+), 40 deletions(-) create mode 100644 src/Properties/PublishProfiles/linux-arm.pubxml create mode 100644 src/Properties/PublishProfiles/linux-arm.user create mode 100644 src/Properties/PublishProfiles/linux-arm64.pubxml create mode 100644 src/Properties/PublishProfiles/linux-arm64.user create mode 100644 src/Properties/PublishProfiles/linux-bionic-x64.pubxml create mode 100644 src/Properties/PublishProfiles/linux-bionic-x64.user create mode 100644 src/Properties/PublishProfiles/linux-musl-x64.pubxml create mode 100644 src/Properties/PublishProfiles/linux-musl-x64.user create mode 100644 src/Properties/PublishProfiles/linux-x64.pubxml create mode 100644 src/Properties/PublishProfiles/linux-x64.user create mode 100644 src/Properties/PublishProfiles/osx-arm64.pubxml create mode 100644 src/Properties/PublishProfiles/osx-arm64.user create mode 100644 src/Properties/PublishProfiles/osx-x64.pubxml create mode 100644 src/Properties/PublishProfiles/osx-x64.user create mode 100644 src/Properties/PublishProfiles/win-arm64.pubxml create mode 100644 src/Properties/PublishProfiles/win-arm64.user create mode 100644 src/Properties/PublishProfiles/win-x64.pubxml create mode 100644 src/Properties/PublishProfiles/win-x64.pubxml.user create mode 100644 src/Properties/PublishProfiles/win-x86.pubxml create mode 100644 src/Properties/PublishProfiles/win-x86.pubxml.user diff --git a/CHANGELOG.md b/CHANGELOG.md index 654ec63..9ec71ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Atlassian Downloader - Changelog +## 2.x + +* `2.0.0.0` - migrated to `dotnet8` and updated libs. code optimized by [@kasthack](https://github.com/kasthack). reworked build scripts via `cli` and `vs`. added translations to `ru` and `en`. added new dists - `osx-arm64`, `linux-bionic-x64`. + +## 1.x +* `1.1.0.0` - added automatic compare of local and remote file sizes. If they differ - the file will be re-downloaded. * `1.0.1.1` - minor update: added `UserAgent` to HTTP headers and added mirrors of json files. * `1.0.1.0` - added support of `Atlassian Bitbucket (Mesh)` product, updated deps, fixed `Chocolatey` support and start logic. * `1.0.0.9` - updated deps. diff --git a/README.md b/README.md index e8fadcb..df18427 100644 --- a/README.md +++ b/README.md @@ -2,36 +2,44 @@ # Atlassian Downloader -Console app written with `c#` and `dotnet6` for downloading all avalible products from `Atlassian`. Why not? +Console app written with `c#` and `dotnet8` for downloading all avalible products from `Atlassian`. Why not? ![Atlassian Downloader](https://rawcdn.githack.com/EpicMorg/atlassian-downloader/87f1d7fd4e3f22b29b4be87d02d80dd0b3e0280e/.github/media/screenshot-01.png) ![Atlassian Downloader](https://rawcdn.githack.com/EpicMorg/atlassian-downloader/87f1d7fd4e3f22b29b4be87d02d80dd0b3e0280e/.github/media/screenshot-03.png) -## Requirements -1. Preinstalled`*` `dotnet6`. Download [here](https://dotnet.microsoft.com/download/dotnet/6.0). -2. Supported OS: `win32/win64`, `linux`, `macosx`, `arm/arm64` +# Supported OS: +`win-x86`, `win-x64`, `win-arm64`, `linux-x86`, `linux-x64`, `linux-musl-x64`, `linux-arm`, `linux-arm64`, `linux-bionic-x64`, `osx-x64`, `osx-arm64` -`*` since version `1.0.0.4` application build asstandalone package and do not requre preinstalled `dotnet6`. +------------------- # How to... -## ..bootstrap from scratch + +## ..develop +1. preinstall `dotnet8`. Download [here](https://dotnet.microsoft.com/download/dotnet/8.0). +2. preinstall `VS2022`. Download [here](https://visualstudio.microsoft.com/vs/). +3. `git clone` this repo. +4. `cd` to `/src`. +5. open `*.sln` file +6. ... +7. profit! + +## ..build from scratch 1. `git clone` this repo. 2. `cd` to `/src`. -3.1 execute `dotnet run` in `src` folder. -or -3.2 execute `build.bat(sh)` in `src` folder. -4. by default all data will be downloaded to `src/atlassian` folder and subfolders. +3. execute `build.bat(sh)` in `src` folder. +4. by default all data will be downloaded to `src/Atlassian` folder and subfolders. -## ..install -1. download latest [![Downloads](https://img.shields.io/github/downloads/EpicMorg/atlassian-downloader/total.svg?style=flat-square)](https://github.com/EpicMorg/atlassian-downloader/releases) [![Release](https://img.shields.io/github/v/release/EpicMorg/atlassian-downloader?style=flat-square)](https://github.com/EpicMorg/atlassian-downloader/releases) +## ..use binary versions +1. just download latest [![Downloads](https://img.shields.io/github/downloads/EpicMorg/atlassian-downloader/total.svg?style=flat-square)](https://github.com/EpicMorg/atlassian-downloader/releases) [![Release](https://img.shields.io/github/v/release/EpicMorg/atlassian-downloader?style=flat-square)](https://github.com/EpicMorg/atlassian-downloader/releases) 2. ... 3. profit! -# Intall via Chocolatey +## ..intall via Chocolatey | CLI | Version | Downloads | ------ | ------ | ------ | :computer: `choco install atlassian-downloader` | [![Version](https://img.shields.io/chocolatey/v/atlassian-downloader?label=version&style=for-the-badge)](https://chocolatey.org/packages/atlassian-downloader/) | [![Version](https://img.shields.io/chocolatey/dt/atlassian-downloader?style=for-the-badge)](https://chocolatey.org/packages/atlassian-downloader/) +------------------- # Usage and settings ## CLI args @@ -46,12 +54,13 @@ Usage: atlassian-downloader [options] Options: - --output-dir Override output directory to download [default: atlassian] - --custom-feed Override URIs to import [default: ] - --action Action to perform [default: Download] - --version Show credits banner [default: False] - --product-version Override target version to download some product. Advice: Use it with "customFeed". [default: ] - -?, -h, --help Show help and usage information + --output-dir Override output directory to download + --custom-feed Override URIs to import [] + --action Action to perform [default: Download] + --about Show credits banner [default: False] + --product-version Override target version to download some product. Advice: Use it with "customFeed". [] + --version Show version information + -?, -h, --help Show help and usage information ``` ## Example of usage: @@ -106,6 +115,8 @@ The following built-in themes are available, provided by `Serilog.Sinks.Console` * `AnsiConsoleTheme.Grayscale` - an ANSI 256-color version of the "grayscale" theme * `AnsiConsoleTheme.Code` - an ANSI 256-color Visual Studio Code-inspired theme +------------------- + # Supported products: | Product | Current | Archive | EAP | @@ -125,7 +136,7 @@ The following built-in themes are available, provided by `Serilog.Sinks.Console` * Archive of `Atlassian` jsons available [here](https://github.com/EpicMorg/atlassian-json). ------- +------------------- ## Authors * [@kasthack](https://github.com/kasthack) - code diff --git a/src/Properties/PublishProfiles/linux-arm.pubxml b/src/Properties/PublishProfiles/linux-arm.pubxml new file mode 100644 index 0000000..2c4dbab --- /dev/null +++ b/src/Properties/PublishProfiles/linux-arm.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\linux-arm\publish\ + FileSystem + <_TargetId>Folder + net8.0 + linux-arm + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-arm.user b/src/Properties/PublishProfiles/linux-arm.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/linux-arm.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-arm64.pubxml b/src/Properties/PublishProfiles/linux-arm64.pubxml new file mode 100644 index 0000000..e073a4d --- /dev/null +++ b/src/Properties/PublishProfiles/linux-arm64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\linux-arm64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + linux-arm64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-arm64.user b/src/Properties/PublishProfiles/linux-arm64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/linux-arm64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-bionic-x64.pubxml b/src/Properties/PublishProfiles/linux-bionic-x64.pubxml new file mode 100644 index 0000000..9ca1966 --- /dev/null +++ b/src/Properties/PublishProfiles/linux-bionic-x64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\linux-bionic-x64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + linux-bionic-x64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-bionic-x64.user b/src/Properties/PublishProfiles/linux-bionic-x64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/linux-bionic-x64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-musl-x64.pubxml b/src/Properties/PublishProfiles/linux-musl-x64.pubxml new file mode 100644 index 0000000..54c6439 --- /dev/null +++ b/src/Properties/PublishProfiles/linux-musl-x64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\linux-musl-x64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + linux-musl-x64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-musl-x64.user b/src/Properties/PublishProfiles/linux-musl-x64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/linux-musl-x64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-x64.pubxml b/src/Properties/PublishProfiles/linux-x64.pubxml new file mode 100644 index 0000000..067f676 --- /dev/null +++ b/src/Properties/PublishProfiles/linux-x64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\linux-x64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + linux-x64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/linux-x64.user b/src/Properties/PublishProfiles/linux-x64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/linux-x64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/osx-arm64.pubxml b/src/Properties/PublishProfiles/osx-arm64.pubxml new file mode 100644 index 0000000..ae3c5a2 --- /dev/null +++ b/src/Properties/PublishProfiles/osx-arm64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\osx-arm64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + osx-arm64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/osx-arm64.user b/src/Properties/PublishProfiles/osx-arm64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/osx-arm64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/osx-x64.pubxml b/src/Properties/PublishProfiles/osx-x64.pubxml new file mode 100644 index 0000000..60b5241 --- /dev/null +++ b/src/Properties/PublishProfiles/osx-x64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\osx-x64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + osx-x64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/osx-x64.user b/src/Properties/PublishProfiles/osx-x64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/osx-x64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-arm64.pubxml b/src/Properties/PublishProfiles/win-arm64.pubxml new file mode 100644 index 0000000..2e3d3df --- /dev/null +++ b/src/Properties/PublishProfiles/win-arm64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\win-arm64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + win-arm64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-arm64.user b/src/Properties/PublishProfiles/win-arm64.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/win-arm64.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-x64.pubxml b/src/Properties/PublishProfiles/win-x64.pubxml new file mode 100644 index 0000000..03e2ad2 --- /dev/null +++ b/src/Properties/PublishProfiles/win-x64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + Any CPU + bin\Release\net8.0\win-x64\publish\ + FileSystem + <_TargetId>Folder + net8.0 + win-x64 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-x64.pubxml.user b/src/Properties/PublishProfiles/win-x64.pubxml.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/win-x64.pubxml.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-x86.pubxml b/src/Properties/PublishProfiles/win-x86.pubxml new file mode 100644 index 0000000..03b18a0 --- /dev/null +++ b/src/Properties/PublishProfiles/win-x86.pubxml @@ -0,0 +1,20 @@ + + + + + Release + Any CPU + + bin\Release\net8.0\win-x86\publish\ + FileSystem + <_TargetId>Folder + net8.0 + win-x86 + true + false + false + false + + \ No newline at end of file diff --git a/src/Properties/PublishProfiles/win-x86.pubxml.user b/src/Properties/PublishProfiles/win-x86.pubxml.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/src/Properties/PublishProfiles/win-x86.pubxml.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/build.bat b/src/build.bat index 34b3f42..02857f5 100644 --- a/src/build.bat +++ b/src/build.bat @@ -1,16 +1,16 @@ SET DOTNET_CLI_TELEMETRY_OPTOUT=true SET DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true -dotnet.exe publish --runtime win-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime win-x86 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime win-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet.exe publish --runtime osx-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime osx-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-musl-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-arm --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet.exe publish --runtime linux-bionic-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet.exe publish -p:PublishProfile=win-x64 --force +dotnet.exe publish -p:PublishProfile=win-x86 --force +dotnet.exe publish -p:PublishProfile=win-arm64 --force +dotnet.exe publish -p:PublishProfile=osx-x64 --force +dotnet.exe publish -p:PublishProfile=osx-arm64 --force +dotnet.exe publish -p:PublishProfile=linux-x64 --force +dotnet.exe publish -p:PublishProfile=linux-musl-x64 --force +dotnet.exe publish -p:PublishProfile=linux-arm --force +dotnet.exe publish -p:PublishProfile=linux-arm64 --force +dotnet.exe publish -p:PublishProfile=linux-bionic-x64 --force del /F bin\\Release\\net8.0\\win-x64\\publish\\atlassian-downloader.pdb del /F bin\\Release\\net8.0\\win-x86\\publish\\atlassian-downloader.pdb diff --git a/src/build.sh b/src/build.sh index 679cc95..d21e2e2 100644 --- a/src/build.sh +++ b/src/build.sh @@ -2,16 +2,16 @@ export DOTNET_CLI_TELEMETRY_OPTOUT=true export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true -dotnet publish --runtime win-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet publish --runtime win-x86 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet publish --runtime win-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=true -p:PublishSingleFile=false -p:PublishReadyToRun=true -dotnet publish --runtime osx-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime osx-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime linux-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=fal -dotnet publish --runtime linux-musl-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=falsese -dotnet publish --runtime linux-arm --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime linux-arm64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false -dotnet publish --runtime linux-bionic-x64 --force --self-contained true --framework net8.0 --configuration Release -p:PublishTrimmed=false -p:PublishSingleFile=false -p:PublishReadyToRun=false +dotnet publish -p:PublishProfile=win-x64 --force +dotnet publish -p:PublishProfile=win-x86 --force +dotnet publish -p:PublishProfile=win-arm64 --force +dotnet publish -p:PublishProfile=osx-x64 --force +dotnet publish -p:PublishProfile=osx-arm64 --force +dotnet publish -p:PublishProfile=linux-x64 --force +dotnet publish -p:PublishProfile=linux-musl-x64 --force +dotnet publish -p:PublishProfile=linux-arm --force +dotnet publish -p:PublishProfile=linux-arm64 --force +dotnet publish -p:PublishProfile=linux-bionic-x64 --force rm -rfv ./bin/Release/net8.0/win-x64/publish/atlassian-downloader.pdb rm -rfv ./bin/Release/net8.0/win-x86/publish/atlassian-downloader.pdb From 4f594984829685189d199008136f27e46519d278 Mon Sep 17 00:00:00 2001 From: STAM Date: Fri, 13 Oct 2023 01:30:46 +0300 Subject: [PATCH 5/7] Feature #33: added --skip-file-check flag --- README.md | 2 + src/Core/DownloaderService.cs | 59 ++++++++++++++++++------------ src/Models/DownloaderOptions.cs | 2 +- src/Program.cs | 5 ++- src/Properties/launchSettings.json | 5 ++- 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index df18427..c742f7b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ Options: --action Action to perform [default: Download] --about Show credits banner [default: False] --product-version Override target version to download some product. Advice: Use it with "customFeed". [] + --skip-file-check Skip compare of file sizes if a local file already exists. + Existing file will be skipped to check and redownload. [default: False] --version Show version information -?, -h, --help Show help and usage information ``` diff --git a/src/Core/DownloaderService.cs b/src/Core/DownloaderService.cs index 9e9c10b..b25a863 100644 --- a/src/Core/DownloaderService.cs +++ b/src/Core/DownloaderService.cs @@ -113,6 +113,7 @@ private IReadOnlyList GetFeedUrls() => this.options.CustomFeed != null private async Task DownloadFilesFromFeed(string feedUrl, IDictionary versions, CancellationToken cancellationToken) { + var feedDir = Path.Combine(this.options.OutputDir, feedUrl[(feedUrl.LastIndexOf('/') + 1)..feedUrl.LastIndexOf('.')]); this.logger.LogInformation("Download from JSON \"{feedUrl}\" started", feedUrl); foreach (var version in versions) @@ -141,6 +142,8 @@ private async Task DownloadFilesFromFeed(string feedUrl, IDictionaryOverride URIs to import /// Show credits banner /// Override target version to download some product. Advice: Use it with "customFeed". - static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction action = DownloadAction.Download, bool about = false, string productVersion = null) => await + /// Skip compare of file sizes if a local file already exists. Existing file will be skipped to check and redownload. + static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction action = DownloadAction.Download, bool about = false, string productVersion = null, bool skipFileCheck = false) => await Host .CreateDefaultBuilder() .ConfigureHostConfiguration(configHost => configHost.AddEnvironmentVariables()) @@ -44,7 +45,7 @@ static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction .AddSerilog(dispose: true); }) .AddHostedService() - .AddSingleton(new DownloaderOptions(outputDir, customFeed, action, about, productVersion)) + .AddSingleton(new DownloaderOptions(outputDir, customFeed, action, about, productVersion, skipFileCheck)) .AddHttpClient()) .RunConsoleAsync() .ConfigureAwait(false); diff --git a/src/Properties/launchSettings.json b/src/Properties/launchSettings.json index 874b865..fd271c9 100644 --- a/src/Properties/launchSettings.json +++ b/src/Properties/launchSettings.json @@ -2,8 +2,9 @@ "profiles": { "atlassian-downloader": { "commandName": "Project", - //"commandLineArgs": "--help" - "commandLineArgs": "--action=ShowRawJson --output-dir=F:\\temp\\atlassian\\test1" + //"commandLineArgs": "--version" + "commandLineArgs": "--help" + // "commandLineArgs": "--action=ShowRawJson --output-dir=F:\\temp\\atlassian\\test1" } } } \ No newline at end of file From b96d87ca333d9bd6658c2898477c46d8d0ed797c Mon Sep 17 00:00:00 2001 From: STAM Date: Fri, 13 Oct 2023 01:46:09 +0300 Subject: [PATCH 6/7] Feature #39: added --user-agent flag --- README.md | 9 +++++++-- src/Core/DownloaderService.cs | 11 ++++++----- src/GlobalSuppressions.cs | 12 ++++++++++++ src/Models/DownloaderOptions.cs | 2 +- src/Program.cs | 5 +++-- 5 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/GlobalSuppressions.cs diff --git a/README.md b/README.md index c742f7b..e59db5c 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,14 @@ Options: --custom-feed Override URIs to import [] --action Action to perform [default: Download] --about Show credits banner [default: False] - --product-version Override target version to download some product. Advice: Use it with "customFeed". [] + --product-version Override target version to download some product. Advice: Use + it with "customFeed". [] --skip-file-check Skip compare of file sizes if a local file already exists. - Existing file will be skipped to check and redownload. [default: False] + Existing file will be skipped to check and redownload. + [default: False] + --user-agent Set custom user agent via this feature flag. [default: + Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) + Gecko/20100101 Firefox/101.0] --version Show version information -?, -h, --help Show help and usage information ``` diff --git a/src/Core/DownloaderService.cs b/src/Core/DownloaderService.cs index b25a863..42cf0f9 100644 --- a/src/Core/DownloaderService.cs +++ b/src/Core/DownloaderService.cs @@ -16,18 +16,17 @@ namespace EpicMorg.Atlassian.Downloader.Core; internal class DownloaderService : IHostedService { - private readonly string UserAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0"; - private readonly ILogger logger; private readonly DownloaderOptions options; private readonly HttpClient client; private readonly IHostApplicationLifetime hostApplicationLifetime; + public DownloaderService(IHostApplicationLifetime hostApplicationLifetime, ILogger logger, HttpClient client, DownloaderOptions options) { this.logger = logger; this.client = client; - client.DefaultRequestHeaders.Add("User-Agent", this.UserAgentString); + client.DefaultRequestHeaders.Add("User-Agent", options.UserAgent); this.options = options; this.hostApplicationLifetime = hostApplicationLifetime; } @@ -92,7 +91,7 @@ public async Task StartAsync(CancellationToken cancellationToken) { var atlassianJson = await this.client.GetStringAsync(feedUrl, cancellationToken).ConfigureAwait(false); var json = atlassianJson.Trim()["downloads(".Length..^1]; - this.logger.LogTrace("Downloaded json: {0}", json); + this.logger.LogTrace($"Downloaded json: {0}", json); var parsed = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true @@ -160,7 +159,7 @@ private async Task DownloadFilesFromFeed(string feedUrl, IDictionaryShow credits banner /// Override target version to download some product. Advice: Use it with "customFeed". /// Skip compare of file sizes if a local file already exists. Existing file will be skipped to check and redownload. - static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction action = DownloadAction.Download, bool about = false, string productVersion = null, bool skipFileCheck = false) => await + /// Set custom user agent via this feature flag. + static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction action = DownloadAction.Download, bool about = false, string productVersion = null, bool skipFileCheck = false, string userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0") => await Host .CreateDefaultBuilder() .ConfigureHostConfiguration(configHost => configHost.AddEnvironmentVariables()) @@ -45,7 +46,7 @@ static async Task Main(string outputDir, Uri[] customFeed = null, DownloadAction .AddSerilog(dispose: true); }) .AddHostedService() - .AddSingleton(new DownloaderOptions(outputDir, customFeed, action, about, productVersion, skipFileCheck)) + .AddSingleton(new DownloaderOptions(outputDir, customFeed, action, about, productVersion, skipFileCheck, userAgent)) .AddHttpClient()) .RunConsoleAsync() .ConfigureAwait(false); From 46ddd7ae5464a1467ac71403e90ebd6aee0cbbe1 Mon Sep 17 00:00:00 2001 From: STAM Date: Fri, 13 Oct 2023 02:05:17 +0300 Subject: [PATCH 7/7] 2.0.0.0 --- src/Core/BellsAndWhistles.cs | 2 +- src/GlobalSuppressions.cs | 12 ------------ src/atlassian-downloader.csproj | 6 +++--- 3 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 src/GlobalSuppressions.cs diff --git a/src/Core/BellsAndWhistles.cs b/src/Core/BellsAndWhistles.cs index e3619c2..7c6fde4 100644 --- a/src/Core/BellsAndWhistles.cs +++ b/src/Core/BellsAndWhistles.cs @@ -13,7 +13,7 @@ internal class BellsAndWhistles private static readonly Assembly entryAssembly = Assembly.GetEntryAssembly(); - private static readonly string assemblyVersion = entryAssembly.GetCustomAttribute().InformationalVersion; + private static readonly string assemblyVersion = entryAssembly.GetName().Version.ToString(); private static readonly string fileVersion = entryAssembly.GetCustomAttribute().Version; diff --git a/src/GlobalSuppressions.cs b/src/GlobalSuppressions.cs deleted file mode 100644 index 10b25b1..0000000 --- a/src/GlobalSuppressions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "", Scope = "member", Target = "~M:EpicMorg.Atlassian.Downloader.Core.DownloaderService.GetJson(System.String,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.ValueTuple{System.String,System.Collections.Generic.IDictionary{System.String,EpicMorg.Atlassian.Downloader.ResponseItem[]}}}")] -[assembly: SuppressMessage("Performance", "CA1869:Cache and reuse 'JsonSerializerOptions' instances", Justification = "", Scope = "member", Target = "~M:EpicMorg.Atlassian.Downloader.Core.DownloaderService.GetJson(System.String,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.ValueTuple{System.String,System.Collections.Generic.IDictionary{System.String,EpicMorg.Atlassian.Downloader.ResponseItem[]}}}")] -[assembly: SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "", Scope = "member", Target = "~M:EpicMorg.Atlassian.Downloader.Core.DownloaderService.DownloadFilesFromFeed(System.String,System.Collections.Generic.IDictionary{System.String,EpicMorg.Atlassian.Downloader.ResponseItem[]},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] -[assembly: SuppressMessage("Reliability", "CA2016:Forward the 'CancellationToken' parameter to methods", Justification = "", Scope = "member", Target = "~M:EpicMorg.Atlassian.Downloader.Core.DownloaderService.DownloadFilesFromFeed(System.String,System.Collections.Generic.IDictionary{System.String,EpicMorg.Atlassian.Downloader.ResponseItem[]},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] -[assembly: SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "", Scope = "member", Target = "~M:EpicMorg.Atlassian.Downloader.Core.DownloaderService.DownloadFile(EpicMorg.Atlassian.Downloader.ResponseItem,System.String,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] diff --git a/src/atlassian-downloader.csproj b/src/atlassian-downloader.csproj index cfd5065..5f4e8ea 100644 --- a/src/atlassian-downloader.csproj +++ b/src/atlassian-downloader.csproj @@ -25,9 +25,9 @@ git https://github.com/EpicMorg/atlassian-downloader atlassian, donwloader, epicmorg - 1.1.0.0 - 1.1.0.0 - 1.1.0.0 + 2.0.0.0 + 2.0.0.0 + 2.0.0.0 EpicMorg 2023 Atlassian Downloader EpicMorg