diff --git a/.github/csharp.instructions.md b/.github/instructions/csharp.instructions.md similarity index 100% rename from .github/csharp.instructions.md rename to .github/instructions/csharp.instructions.md diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 0000000..52d090d --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,35 @@ +name: integration + +on: + push: + branches: + - 'feature/**' + +jobs: + macos-latest: + name: macos-latest + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: 'Cache: ~/.nuget/packages' + uses: actions/cache@v4 + with: + path: | + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }} + - name: 'Build with target: NuGetPush, Publish, CreateDistPackages' + env: + NUGET_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ./build.cmd -t nugetpush -t publish -t createdistpackages + - name: 'Publish: coverage_report' + uses: actions/upload-artifact@v4 + with: + name: coverage-report-macos + path: .tests/coverage-report + - name: 'Publish: cli dist package' + uses: actions/upload-artifact@v4 + with: + name: MacSynkker.Cli + path: .artifacts/dist/MacSynkker.Cli.tar.gz diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..5b207ce --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,35 @@ +name: main + +on: + push: + branches: + - main + +jobs: + macos-latest: + name: macos-latest + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: 'Cache: ~/.nuget/packages' + uses: actions/cache@v4 + with: + path: | + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }} + - name: 'Build with target: NuGetPush, Publish, CreateDistPackages, CreateGitHubRelease' + env: + NUGET_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ./build.cmd -t nugetpush -t publish -t createdistpackages -t creategithubrelease + - name: 'Publish: coverage_report' + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: .tests/coverage-report + - name: 'Publish: cli dist package' + uses: actions/upload-artifact@v4 + with: + name: MacSynkker.Cli + path: .artifacts/dist/MacSynkker.Cli.tar.gz diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..96dcf1a --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,28 @@ +name: pull-request + +on: + pull_request: + branches: + - main + +jobs: + macos-latest: + name: macos-latest + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: 'Cache: ~/.nuget/packages' + uses: actions/cache@v4 + with: + path: | + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }} + - name: 'Build with target: Pack' + run: ./build.cmd -t pack + - name: 'Publish: coverage_report' + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: .tests/coverage-report diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4d8c090 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: release + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +on: + push: + tags: + - 'v**' + +jobs: + macos-latest: + name: macos-latest + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: 'Cache: ~/.nuget/packages' + uses: actions/cache@v4 + with: + path: | + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }} + - name: 'Build with target: NuGetPush, Publish, CreateDistPackages, CreateGitHubRelease' + run: ./build.cmd -t nugetpush -t publish -t createdistpackages -t creategithubrelease + env: + NUGET_TOKEN: ${{ secrets.NUGET_ORG_TOKEN }} + - name: 'Publish: coverage_report' + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: .tests/coverage-report + - name: 'Publish: cli dist package' + uses: actions/upload-artifact@v4 + with: + name: MacSynkker.Cli + path: .artifacts/dist/MacSynkker.Cli.tar.gz diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000..acef5c9 --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,55 @@ +assembly-versioning-scheme: MajorMinorPatch +assembly-file-versioning-scheme: MajorMinorPatchTag +tag-prefix: '^v?' +semantic-version-format: Loose +major-version-bump-message: '\+semver:\s?(breaking|major)' +minor-version-bump-message: '\+semver:\s?(feature|minor)' +patch-version-bump-message: '\+semver:\s?(fix|patch)' +no-bump-message: '\+semver:\s?(none|skip)' +mode: ContinuousDeployment +branches: + feature: + mode: ContinuousDelivery + label: feature.{BranchName} + increment: Minor + track-merge-target: false + regex: ^features?[\/-](?.+) + prevent-increment: + when-current-commit-tagged: false + source-branches: + - main + tracks-release-branches: false + is-release-branch: false + is-main-branch: false + pre-release-weight: 30000 + main: + mode: ContinuousDelivery + label: 'ci' + increment: Patch + track-merge-target: false + regex: ^master$|^main$ + prevent-increment: + when-current-commit-tagged: true + source-branches: + - develop + - release + tracks-release-branches: false + is-release-branch: false + pre-release-weight: 55000 + pull-request: + mode: ContinuousDelivery + label: PR-{PullRequestName} + increment: Inherit + track-merge-target: false + regex: ^(pull|pull\-requests|pr)[/-](?.+) + prevent-increment: + when-current-commit-tagged: false + source-branches: + - main + - feature + tracks-release-branches: false + is-release-branch: false + pre-release-weight: 30000 +ignore: + sha: [ ] +merge-message-formats: { } diff --git a/build.cmd b/build.cmd new file mode 100755 index 0000000..b08cc59 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +:; set -eo pipefail +:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +:; ${SCRIPT_DIR}/build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..1b91f63 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,45 @@ +[CmdletBinding()] +Param( + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$BuildArguments +) + +Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" + +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + +########################################################################### +# CONFIGURATION +########################################################################### + +$BuildProjectFile = "$PSScriptRoot\build\Build.csproj" +$DotNetGlobalFile = "$PSScriptRoot\\global.json" + +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 +$env:DOTNET_NOLOGO = 1 + +########################################################################### +# EXECUTION +########################################################################### + +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` + $(dotnet --version) -and $LASTEXITCODE -eq 0) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path +} +else { + Write-Host "No matching dotnet version found" + + exit 1 +} + +Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" + +ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..35eaaba --- /dev/null +++ b/build.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +bash --version 2>&1 | head -n 1 + +set -e +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) + +########################################################################### +# CONFIGURATION +########################################################################### + +BUILD_PROJECT_FILE="$SCRIPT_DIR/build/Build.csproj" +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" + +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_NOLOGO=1 + +########################################################################### +# EXECUTION +########################################################################### + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then + export DOTNET_EXE="$(command -v dotnet)" +else + echo "No matching dotnet version found" + exit 1 +fi + +echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" + +"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/build/Build.csproj b/build/Build.csproj new file mode 100644 index 0000000..caf68a7 --- /dev/null +++ b/build/Build.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/build/BuildContext.cs b/build/BuildContext.cs new file mode 100644 index 0000000..af1ac2c --- /dev/null +++ b/build/BuildContext.cs @@ -0,0 +1,71 @@ +using Cake.Common.Build; +using Cake.Core; +using Cake.Core.IO; +using CreativeCoders.CakeBuild; +using CreativeCoders.CakeBuild.Tasks.Defaults; +using CreativeCoders.CakeBuild.Tasks.Templates.Settings; +using CreativeCoders.Core; +using CreativeCoders.Core.Collections; +using CreativeCoders.Core.IO; +using JetBrains.Annotations; + +namespace Build; + +[UsedImplicitly] +public class BuildContext(ICakeContext context) + : CakeBuildContext(context), IDefaultTaskSettings, ICreateDistPackagesTaskSettings, ICreateGitHubReleaseTaskSettings +{ + public IList DirectoriesToClean => this.CastAs() + .GetDefaultDirectoriesToClean().AddRange(RootDir.Combine(".tests")); + + + public string Copyright => $"{DateTime.Now.Year} CreativeCoders"; + + public string PackageProjectUrl => "https://github.com/CreativeCodersTeam/macsynkker"; + + public string PackageLicenseExpression => PackageLicenseExpressions.ApacheLicense20; + + public string NuGetFeedUrl => this.GitHubActions().Environment.Workflow.Workflow == "release" + ? "nuget.org" + : "https://nuget.pkg.github.com/CreativeCodersTeam/index.json"; + + public bool SkipPush => this.BuildSystem().IsPullRequest || + this.BuildSystem().IsLocalBuild; + + public DirectoryPath PublishOutputDir => ArtifactsDir.Combine("published"); + + private const string CliPath = "source/CreativeCoders.MacSynkker.Cli"; + + private const string CliProjectFile = "CreativeCoders.MacSynkker.Cli.csproj"; + + public IEnumerable PublishingItems => + [ + new PublishingItem( + RootDir + .Combine(CliPath) + .CombineWithFilePath(CliProjectFile), + PublishOutputDir.Combine("cli")) + ]; + + private const string DistPackageName = "MacSynkker.Cli"; + + public IEnumerable DistPackages => + [ + new DistPackage(DistPackageName, PublishOutputDir.Combine("cli")) + ]; + + public string ReleaseName => $"v{Version.FullSemVer}"; + + public string ReleaseVersion => $"v{Version.FullSemVer}"; + + public string ReleaseBody => "MacSynkker Release"; + + public bool IsPreRelease => !string.IsNullOrWhiteSpace(Version.PreReleaseTag); + + public IEnumerable ReleaseAssets => + [ + new GitHubReleaseFileAsset( + GetRequiredSettings().DistOutputPath + .CombineWithFilePath(DistPackageName + ".tar.gz").FullPath, null) + ]; +} diff --git a/build/Program.cs b/build/Program.cs new file mode 100644 index 0000000..34637f1 --- /dev/null +++ b/build/Program.cs @@ -0,0 +1,19 @@ +using CreativeCoders.CakeBuild; + +namespace Build; + +internal static class Program +{ + internal static int Main(string[] args) + { + return CakeHostBuilder.Create() + .UseBuildContext() + .AddDefaultTasks() + .AddBuildServerIntegration() + .InstallTools( + new DotNetToolInstallation("GitVersion.Tool", "6.5.1"), + new DotNetToolInstallation("dotnet-reportgenerator-globaltool", "5.5.1")) + .Build() + .Run(args); + } +} diff --git a/macSynkker.sln b/macSynkker.sln index 21ae6c3..795fadb 100644 --- a/macSynkker.sln +++ b/macSynkker.sln @@ -1,8 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D3F213BB-A6EC-4DDA-9C43-59094DF2FD09}" + ProjectSection(SolutionItems) = preProject + tests\Directory.Build.props = tests\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "source", "source", "{A9CE4FEF-F010-408C-9B5E-F00DC960A792}" + ProjectSection(SolutionItems) = preProject + source\Directory.Build.props = source\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__ai", "__ai", "{3CA6C44F-1F49-4D5D-A26F-92046B51B4F5}" EndProject @@ -14,6 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "__global", "__global", "{BF global.json = global.json LICENSE = LICENSE README.md = README.md + GitVersion.yml = GitVersion.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{C033DF64-285B-4C44-AFFC-400878C92C73}" @@ -23,9 +30,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreativeCoders.MacSynkker.Cli", "source\CreativeCoders.MacSynkker.Cli\CreativeCoders.MacSynkker.Cli.csproj", "{4B29C32B-9BAF-471E-B83A-D7F5735F27B8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "copilot", "copilot", "{083C21F2-8C37-4E30-9CA8-82AAD4F77DD9}" - ProjectSection(SolutionItems) = preProject - .github\csharp.instructions.md = .github\csharp.instructions.md - EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "junie", "junie", "{16659358-8B04-4FAD-80A0-467982B00A9D}" ProjectSection(SolutionItems) = preProject @@ -39,11 +43,38 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreativeCoders.MacOS.Core", "source\CreativeCoders.MacOS.Core\CreativeCoders.MacOS.Core.csproj", "{6C7AB20D-847C-48A0-92EF-C45C621E11F0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{215614E0-F85F-460E-BCAA-13368AE1E3BD}" + ProjectSection(SolutionItems) = preProject + samples\Directory.Build.props = samples\Directory.Build.props + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleConsoleApp", "samples\SampleConsoleApp\SampleConsoleApp.csproj", "{75784FD0-11AA-4DB2-95AE-92DA3C3B793D}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreativeCoders.MacOS.UserDefaults.Tests", "tests\CreativeCoders.MacOS.UserDefaults.Tests\CreativeCoders.MacOS.UserDefaults.Tests.csproj", "{BF53FB30-8068-426D-BC06-B692E45CE94D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{9A2D709F-395D-4373-9B73-FDAE4E606B64}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "build\Build.csproj", "{5D00B0B9-E9B4-423C-AFCF-0F7CB21B2A78}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ci", "ci", "{076341D1-E2B7-47A8-AB79-78BFD7DBA646}" + ProjectSection(SolutionItems) = preProject + .github\workflows\main.yml = .github\workflows\main.yml + .github\workflows\pull-request.yml = .github\workflows\pull-request.yml + .github\workflows\integration.yml = .github\workflows\integration.yml + .github\workflows\release.yml = .github\workflows\release.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "instructions", "instructions", "{3CAC9757-F7D3-4A37-9820-B8755EF7FF3F}" + ProjectSection(SolutionItems) = preProject + .github\instructions\csharp.instructions.md = .github\instructions\csharp.instructions.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1A70000D-DAC9-4D34-9306-7914CC837B05}" + ProjectSection(SolutionItems) = preProject + build.sh = build.sh + build.ps1 = build.ps1 + build.cmd = build.cmd + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -60,6 +91,10 @@ Global {6C7AB20D-847C-48A0-92EF-C45C621E11F0} = {A9CE4FEF-F010-408C-9B5E-F00DC960A792} {75784FD0-11AA-4DB2-95AE-92DA3C3B793D} = {215614E0-F85F-460E-BCAA-13368AE1E3BD} {BF53FB30-8068-426D-BC06-B692E45CE94D} = {D3F213BB-A6EC-4DDA-9C43-59094DF2FD09} + {5D00B0B9-E9B4-423C-AFCF-0F7CB21B2A78} = {9A2D709F-395D-4373-9B73-FDAE4E606B64} + {076341D1-E2B7-47A8-AB79-78BFD7DBA646} = {BF2B8E40-4D03-41A1-8ABD-7AD1A33D5B53} + {3CAC9757-F7D3-4A37-9820-B8755EF7FF3F} = {083C21F2-8C37-4E30-9CA8-82AAD4F77DD9} + {1A70000D-DAC9-4D34-9306-7914CC837B05} = {BF2B8E40-4D03-41A1-8ABD-7AD1A33D5B53} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4B29C32B-9BAF-471E-B83A-D7F5735F27B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -86,5 +121,7 @@ Global {BF53FB30-8068-426D-BC06-B692E45CE94D}.Debug|Any CPU.Build.0 = Debug|Any CPU {BF53FB30-8068-426D-BC06-B692E45CE94D}.Release|Any CPU.ActiveCfg = Release|Any CPU {BF53FB30-8068-426D-BC06-B692E45CE94D}.Release|Any CPU.Build.0 = Release|Any CPU + {5D00B0B9-E9B4-423C-AFCF-0F7CB21B2A78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D00B0B9-E9B4-423C-AFCF-0F7CB21B2A78}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection EndGlobal diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props new file mode 100644 index 0000000..df8fb07 --- /dev/null +++ b/samples/Directory.Build.props @@ -0,0 +1,8 @@ + + + net10.0 + CreativeCoders + False + $(NoWarn);IDE0079 + + \ No newline at end of file diff --git a/samples/SampleConsoleApp/SampleConsoleApp.csproj b/samples/SampleConsoleApp/SampleConsoleApp.csproj index 19b7bd3..ca4755a 100644 --- a/samples/SampleConsoleApp/SampleConsoleApp.csproj +++ b/samples/SampleConsoleApp/SampleConsoleApp.csproj @@ -2,18 +2,17 @@ Exe - net10.0 enable enable - - + + - + diff --git a/source/CreativeCoders.MacOS.Core/CreativeCoders.MacOS.Core.csproj b/source/CreativeCoders.MacOS.Core/CreativeCoders.MacOS.Core.csproj index 3d426e1..c8062ca 100644 --- a/source/CreativeCoders.MacOS.Core/CreativeCoders.MacOS.Core.csproj +++ b/source/CreativeCoders.MacOS.Core/CreativeCoders.MacOS.Core.csproj @@ -1,14 +1,13 @@  - net10.0 enable enable - - + + diff --git a/source/CreativeCoders.MacOS.HomeBrew/BrewInstalledModelExtensions.cs b/source/CreativeCoders.MacOS.HomeBrew/BrewInstalledModelExtensions.cs index 2fae4a9..571518e 100644 --- a/source/CreativeCoders.MacOS.HomeBrew/BrewInstalledModelExtensions.cs +++ b/source/CreativeCoders.MacOS.HomeBrew/BrewInstalledModelExtensions.cs @@ -23,10 +23,25 @@ public static BrewCaskModel[] GetCasks(this BrewInstalledModel installedModel, b public static BrewFormulaModel[] GetOutdatedFormulae(this BrewInstalledModel installedModel) { return installedModel.Formulae - .Where(x => x.Installed?.Any(y => y.Version != x.Versions?.Stable) == true) + .Where(IsFormulaOutdated) .ToArray(); } + private static bool IsFormulaOutdated(BrewFormulaModel formula) + { + return formula.Installed?.Any(y => !FormulaeVersionsAreEqual(y.Version, formula.Versions?.Stable)) == true; + } + + private static bool FormulaeVersionsAreEqual(string? installedVersion, string? availableVersion) + { + if (installedVersion == null || availableVersion == null) + { + return installedVersion == availableVersion; + } + + return installedVersion == availableVersion || installedVersion.StartsWith($"{availableVersion}_"); + } + public static BrewFormulaModel[] GetFormulae(this BrewInstalledModel installedModel, bool onlyOutdated) { return onlyOutdated diff --git a/source/CreativeCoders.MacOS.HomeBrew/CreativeCoders.MacOS.HomeBrew.csproj b/source/CreativeCoders.MacOS.HomeBrew/CreativeCoders.MacOS.HomeBrew.csproj index afbd525..88ece31 100644 --- a/source/CreativeCoders.MacOS.HomeBrew/CreativeCoders.MacOS.HomeBrew.csproj +++ b/source/CreativeCoders.MacOS.HomeBrew/CreativeCoders.MacOS.HomeBrew.csproj @@ -1,7 +1,6 @@  - net10.0 enable enable @@ -11,8 +10,8 @@ - - + + diff --git a/source/CreativeCoders.MacOS.UserDefaults/CreativeCoders.MacOS.UserDefaults.csproj b/source/CreativeCoders.MacOS.UserDefaults/CreativeCoders.MacOS.UserDefaults.csproj index 1bd42c7..b565cbc 100644 --- a/source/CreativeCoders.MacOS.UserDefaults/CreativeCoders.MacOS.UserDefaults.csproj +++ b/source/CreativeCoders.MacOS.UserDefaults/CreativeCoders.MacOS.UserDefaults.csproj @@ -1,15 +1,14 @@  - net10.0 enable enable - - - + + + diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeOptions.cs deleted file mode 100644 index 130da76..0000000 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using CreativeCoders.SysConsole.Cli.Parsing; -using JetBrains.Annotations; - -namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; - -[UsedImplicitly] -public class BrewUpgradeOptions -{ - [OptionValue(0)] public string AppName { get; set; } = string.Empty; - - [OptionParameter('o', "outdated", HelpText = "Upgrade all outdated software")] - public bool UpgradeOutdated { get; set; } - - [OptionParameter('f', "force", HelpText = "Force upgrade of software")] - public bool Force { get; set; } - - [OptionParameter('h', "haltonerror", HelpText = "Halt on error upgrading an app")] - public bool HaltOnError { get; set; } -} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/HomebrewCommandGroup.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/HomebrewCommandGroup.cs new file mode 100644 index 0000000..df4bb79 --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/HomebrewCommandGroup.cs @@ -0,0 +1,11 @@ +using CreativeCoders.Cli.Core; +using CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; + +[assembly: CliCommandGroup([HomebrewCommandGroup.Name], "Commands for managing Homebrew packages")] + +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; + +public static class HomebrewCommandGroup +{ + public const string Name = "brew"; +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewInfoCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Info/BrewInfoCommand.cs similarity index 85% rename from source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewInfoCommand.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Info/BrewInfoCommand.cs index 23a2881..fa96fb2 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewInfoCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Info/BrewInfoCommand.cs @@ -4,9 +4,10 @@ using JetBrains.Annotations; using Spectre.Console; -namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew.Info; -[CliCommand(["brew", "info"])] +[UsedImplicitly] +[CliCommand([HomebrewCommandGroup.Name, "info"], Description = "Shows Homebrew info")] public class BrewInfoCommand(IAnsiConsole ansiConsole, IBrewInfo brewInfo) : ICliCommand { private readonly IBrewInfo _brewInfo = Ensure.NotNull(brewInfo); diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareCommand.cs similarity index 92% rename from source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareCommand.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareCommand.cs index d736349..9620654 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareCommand.cs @@ -7,10 +7,10 @@ using JetBrains.Annotations; using Spectre.Console; -namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew.List; [UsedImplicitly] -[CliCommand(["brew", "list"])] +[CliCommand([HomebrewCommandGroup.Name, "list"], Description = "Shows Homebrew installed software")] public class BrewListInstalledSoftwareCommand(IAnsiConsole ansiConsole, IBrewInstalledSoftware brewInstalledSoftware) : ICliCommand { @@ -32,6 +32,8 @@ public async Task ExecuteAsync(BrewListInstalledSoftwareOptions o if ((!options.Casks.HasValue && !options.Formulae.HasValue) || options.Casks == true) { PrintCasks(installedSoftware.GetCasks(options.ShowOnlyOutdated), options.ShowAsListView); + + _ansiConsole.WriteLine(); } if ((!options.Casks.HasValue && !options.Formulae.HasValue) || options.Formulae == true) @@ -44,8 +46,7 @@ public async Task ExecuteAsync(BrewListInstalledSoftwareOptions o private void PrintFormulae(BrewFormulaModel[] installedSoftwareFormulae, bool optionsShowAsListView) { - _ansiConsole.WriteLine("Installed HomeBrew formulae:"); - _ansiConsole.WriteLine(); + _ansiConsole.WriteLines("Installed HomeBrew formulae:", string.Empty); if (optionsShowAsListView) { @@ -64,14 +65,11 @@ private void PrintFormulae(BrewFormulaModel[] installedSoftwareFormulae, bool op $"- {installedSoftwareFormula.Name} ({installedSoftwareFormula.Versions?.Stable})"); } } - - _ansiConsole.WriteLine(); } private void PrintCasks(BrewCaskModel[] installedSoftwareCasks, bool optionsShowAsListView) { - _ansiConsole.WriteLine("Installed HomeBrew casks:"); - _ansiConsole.WriteLine(); + _ansiConsole.WriteLines("Installed HomeBrew casks:", string.Empty); if (optionsShowAsListView) { @@ -92,8 +90,6 @@ private void PrintCasks(BrewCaskModel[] installedSoftwareCasks, bool optionsShow $"- {installedSoftwareCask.Name?.FirstOrDefault() ?? "unknown"} ({ExtractCaskVersion(installedSoftwareCask.Installed)}) [{installedSoftwareCask.Installed}]"); } } - - _ansiConsole.WriteLine(); } private static string ExtractCaskVersion(string? versionString) diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareOptions.cs similarity index 89% rename from source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareOptions.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareOptions.cs index 699af11..43559ff 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewListInstalledSoftwareOptions.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/List/BrewListInstalledSoftwareOptions.cs @@ -1,7 +1,7 @@ using CreativeCoders.SysConsole.Cli.Parsing; using JetBrains.Annotations; -namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew.List; [UsedImplicitly] public class BrewListInstalledSoftwareOptions diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeCommand.cs similarity index 77% rename from source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeCommand.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeCommand.cs index f30966c..7e48206 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/BrewUpgradeCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeCommand.cs @@ -1,13 +1,14 @@ using CreativeCoders.Cli.Core; using CreativeCoders.Core; using CreativeCoders.MacOS.HomeBrew; +using CreativeCoders.SysConsole.Core; using JetBrains.Annotations; using Spectre.Console; -namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew; +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew.Upgrade; [UsedImplicitly] -[CliCommand(["brew", "upgrade"])] +[CliCommand([HomebrewCommandGroup.Name, "upgrade"], Description = "Upgrade Homebrew installed software")] public class BrewUpgradeCommand( IBrewUpgrader brewUpgrader, IBrewInstalledSoftware brewInstalledSoftware, @@ -26,7 +27,7 @@ public async Task ExecuteAsync(BrewUpgradeOptions options) if (!string.IsNullOrWhiteSpace(options.AppName)) { - await _brewUpgrader.UpgradeSoftwareAsync(options.AppName).ConfigureAwait(false); + await UpgradeSoftwareCoreAsync(options.AppName).ConfigureAwait(false); } else if (options.UpgradeOutdated) { @@ -36,6 +37,20 @@ public async Task ExecuteAsync(BrewUpgradeOptions options) return CommandResult.Success; } + private Task UpgradeSoftwareCoreAsync(string appName) + { + if (!appName.StartsWith("dotnet-", StringComparison.OrdinalIgnoreCase)) + { + return _brewUpgrader.UpgradeSoftwareAsync(appName); + } + + _ansiConsole.MarkupLine( + "Skipping upgrade of a dotnet part cause its possible, that its needed by this app" + .ToWarningMarkup()); + + return Task.CompletedTask; + } + private async Task UpgradeAllOutdatedAsync(BrewUpgradeOptions options) { var installedSoftware = await _brewInstalledSoftware.GetInstalledSoftwareAsync().ConfigureAwait(false); @@ -77,7 +92,7 @@ private async Task UpgradeSoftwareAsync(string appName, bool cask) try { - await _brewUpgrader.UpgradeSoftwareAsync(appName).ConfigureAwait(false); + await UpgradeSoftwareCoreAsync(appName).ConfigureAwait(false); _ansiConsole.MarkupLine("[green]Done[/]"); diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeOptions.cs new file mode 100644 index 0000000..06d61f4 --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Upgrade/BrewUpgradeOptions.cs @@ -0,0 +1,39 @@ +using CreativeCoders.Cli.Core; +using CreativeCoders.SysConsole.Cli.Parsing; +using JetBrains.Annotations; + +namespace CreativeCoders.MacSynkker.Cli.Commands.HomeBrew.Upgrade; + +[UsedImplicitly] +public class BrewUpgradeOptions : IOptionsValidation +{ + [OptionValue(0, HelpText = "App name to upgrade. If specified, upgrade outdated option is not allowed.")] + public string AppName { get; set; } = string.Empty; + + [OptionParameter('o', "outdated", + HelpText = "Upgrade all outdated software. If specified, app name option is not allowed.")] + public bool UpgradeOutdated { get; set; } + + [OptionParameter('f', "force", HelpText = "Force upgrade of software")] + public bool Force { get; set; } + + [OptionParameter('h', "haltonerror", HelpText = "Halt on error upgrading an app")] + public bool HaltOnError { get; set; } + + public Task ValidateAsync() + { + if (string.IsNullOrWhiteSpace(AppName) && !UpgradeOutdated) + { + return Task.FromResult( + OptionsValidationResult.Invalid(["Either app name or upgrade outdated option must be specified"])); + } + + if (!string.IsNullOrWhiteSpace(AppName) && UpgradeOutdated) + { + return Task.FromResult( + OptionsValidationResult.Invalid(["App name and upgrade outdated option are mutually exclusive"])); + } + + return Task.FromResult(OptionsValidationResult.Valid()); + } +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainCommand.cs similarity index 82% rename from source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainCommand.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainCommand.cs index 7949071..a2e0a7c 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainCommand.cs @@ -8,10 +8,11 @@ using JetBrains.Annotations; using Spectre.Console; -namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ExportDomain; [UsedImplicitly] -[CliCommand(["defaults", "domains", "export"])] +[CliCommand([UserDefaultsCommandGroup.Name, UserDefaultsDomainsCommandGroup.Name, "export"], + Description = "Exports a MacOS user defaults domain to a plist file")] public class ExportDomainCommand( IUserDefaultsExporter userDefaultsExporter, IUserDefaultsEnumerator userDefaultsEnumerator, @@ -41,17 +42,14 @@ public async Task ExecuteAsync(ExportDomainOptions options) await _userDefaultsExporter.ExportDomainAsync(options.DomainName, options.OutputPath, options.PlistFormat) .ConfigureAwait(false); - _ansiConsole.MarkupLine("[green]Done[/]"); - _ansiConsole.WriteLine(); + _ansiConsole.MarkupLines("[green]Done[/]", string.Empty); return CommandResult.Success; } private async Task ExportAllDomainsAsync(ExportDomainOptions options) { - _ansiConsole.PrintBlock() - .WriteLine($"Export all domains to '{options.OutputPath}'") - .WriteLine(); + _ansiConsole.WriteLines($"Export all domains to '{options.OutputPath}'", string.Empty); _fileSystem.Directory.EnsureDirectoryExists(options.OutputPath); @@ -77,8 +75,7 @@ await _userDefaultsExporter.ExportDomainAsync(domainName, outputFileName, option _ansiConsole.MarkupLine("[green]Done[/]"); } - _ansiConsole.WriteLine(); - _ansiConsole.WriteLine($"Exported {domainNames.Length} domains to '{options.OutputPath}'"); + _ansiConsole.WriteLines(string.Empty, $"Exported {domainNames.Length} domains to '{options.OutputPath}'"); return new CommandResult(); } diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainOptions.cs similarity index 95% rename from source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainOptions.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainOptions.cs index 94b589e..f0221b9 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ExportDomainOptions.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ExportDomain/ExportDomainOptions.cs @@ -4,7 +4,7 @@ using CreativeCoders.SysConsole.Cli.Parsing; using JetBrains.Annotations; -namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ExportDomain; [UsedImplicitly] public class ExportDomainOptions : IOptionsValidation diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainCommand.cs similarity index 87% rename from source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainCommand.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainCommand.cs index eb706e7..0b26c8b 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainCommand.cs @@ -2,11 +2,14 @@ using CreativeCoders.Cli.Core; using CreativeCoders.Core; using CreativeCoders.MacOS.UserDefaults; +using JetBrains.Annotations; using Spectre.Console; -namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ImportDomain; -[CliCommand(["defaults", "domains", "import"])] +[UsedImplicitly] +[CliCommand([UserDefaultsCommandGroup.Name, UserDefaultsDomainsCommandGroup.Name, "import"], + Description = "Imports a MacOS user defaults domain from a plist file")] public class ImportDomainCommand( IFileSystem fileSystem, IAnsiConsole ansiConsole, diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainOptions.cs similarity index 85% rename from source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainOptions.cs rename to source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainOptions.cs index 0768885..98cbfdb 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ImportDomainOptions.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ImportDomain/ImportDomainOptions.cs @@ -1,7 +1,7 @@ using CreativeCoders.SysConsole.Cli.Parsing; using JetBrains.Annotations; -namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ImportDomain; [UsedImplicitly] public class ImportDomainOptions diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsCommand.cs new file mode 100644 index 0000000..3e72f9f --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsCommand.cs @@ -0,0 +1,36 @@ +using CreativeCoders.Cli.Core; +using CreativeCoders.Core; +using CreativeCoders.Core.Text; +using CreativeCoders.MacOS.UserDefaults; +using CreativeCoders.SysConsole.Core; +using JetBrains.Annotations; +using Spectre.Console; + +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ListDomains; + +[UsedImplicitly] +[CliCommand([UserDefaultsCommandGroup.Name, UserDefaultsDomainsCommandGroup.Name, "list"], + Description = "Lists all domains for user defaults")] +public class ListDomainsCommand(IAnsiConsole ansiConsole, IUserDefaultsEnumerator userDefaultsEnumerator) + : ICliCommand +{ + private readonly IUserDefaultsEnumerator _userDefaultsEnumerator = Ensure.NotNull(userDefaultsEnumerator); + + private readonly IAnsiConsole _ansiConsole = Ensure.NotNull(ansiConsole); + + public async Task ExecuteAsync(ListDomainsOptions options) + { + _ansiConsole.WriteLines("Show all user defaults domains", string.Empty); + + var domains = await _userDefaultsEnumerator.GetDomainNamesAsync().ConfigureAwait(false); + + if (!string.IsNullOrWhiteSpace(options.FilterPattern)) + { + domains = domains.Where(x => PatternMatcher.MatchesPattern(x, options.FilterPattern)).ToArray(); + } + + _ansiConsole.WriteLines(domains.OrderBy(x => x).Select(x => $"- {x}").ToArray()); + + return new CommandResult(); + } +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsOptions.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsOptions.cs new file mode 100644 index 0000000..a42fcf6 --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/ListDomains/ListDomainsOptions.cs @@ -0,0 +1,11 @@ +using CreativeCoders.SysConsole.Cli.Parsing; +using JetBrains.Annotations; + +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains.ListDomains; + +[UsedImplicitly] +public class ListDomainsOptions +{ + [OptionParameter('f', "filter", HelpText = "Filter domains by name pattern.")] + public string FilterPattern { get; set; } = string.Empty; +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/UserDefaultsDomainsCommandGroup.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/UserDefaultsDomainsCommandGroup.cs new file mode 100644 index 0000000..7b53494 --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/Domains/UserDefaultsDomainsCommandGroup.cs @@ -0,0 +1,13 @@ +using CreativeCoders.Cli.Core; +using CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; +using CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains; + +[assembly: CliCommandGroup([UserDefaultsCommandGroup.Name, UserDefaultsDomainsCommandGroup.Name], + "Commands for managing MacOS user defaults domains")] + +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults.Domains; + +public static class UserDefaultsDomainsCommandGroup +{ + public const string Name = "domains"; +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ListDomainsCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ListDomainsCommand.cs deleted file mode 100644 index be0dd09..0000000 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/ListDomainsCommand.cs +++ /dev/null @@ -1,32 +0,0 @@ -using CreativeCoders.Cli.Core; -using CreativeCoders.Core; -using CreativeCoders.Core.Collections; -using CreativeCoders.MacOS.UserDefaults; -using CreativeCoders.SysConsole.Core; -using JetBrains.Annotations; -using Spectre.Console; - -namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; - -[UsedImplicitly] -[CliCommand(["defaults", "domains", "list"], Description = "Lists all domains for user defaults")] -public class ListDomainsCommand(IAnsiConsole ansiConsole, IUserDefaultsEnumerator userDefaultsEnumerator) : ICliCommand -{ - private readonly IUserDefaultsEnumerator _userDefaultsEnumerator = Ensure.NotNull(userDefaultsEnumerator); - - private readonly IAnsiConsole _ansiConsole = Ensure.NotNull(ansiConsole); - - public async Task ExecuteAsync() - { - _ansiConsole.PrintBlock() - .WriteLine("Show all user defaults domains") - .WriteLine(); - - var domains = await _userDefaultsEnumerator.GetDomainNamesAsync().ConfigureAwait(false); - - domains.OrderBy(x => x).ForEach(x => - _ansiConsole.WriteLine(x)); - - return new CommandResult(); - } -} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/UserDefaultsCommandGroup.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/UserDefaultsCommandGroup.cs new file mode 100644 index 0000000..1b690fc --- /dev/null +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/UserDefaults/UserDefaultsCommandGroup.cs @@ -0,0 +1,11 @@ +using CreativeCoders.Cli.Core; +using CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; + +[assembly: CliCommandGroup([UserDefaultsCommandGroup.Name], "Commands for managing MacOS user defaults")] + +namespace CreativeCoders.MacSynkker.Cli.Commands.UserDefaults; + +public static class UserDefaultsCommandGroup +{ + public const string Name = "defaults"; +} diff --git a/source/CreativeCoders.MacSynkker.Cli/CreativeCoders.MacSynkker.Cli.csproj b/source/CreativeCoders.MacSynkker.Cli/CreativeCoders.MacSynkker.Cli.csproj index e9a676a..f714cb2 100644 --- a/source/CreativeCoders.MacSynkker.Cli/CreativeCoders.MacSynkker.Cli.csproj +++ b/source/CreativeCoders.MacSynkker.Cli/CreativeCoders.MacSynkker.Cli.csproj @@ -2,10 +2,13 @@ Exe - net10.0 enable enable - msc + mcs + true + true + mcs + CreativeCoders.MacSynkker.Cli @@ -13,8 +16,8 @@ - - + + diff --git a/source/CreativeCoders.MacSynkker.Cli/Program.cs b/source/CreativeCoders.MacSynkker.Cli/Program.cs index 5ac57e8..5ef990d 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Program.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Program.cs @@ -25,7 +25,9 @@ public static async Task Main(string[] args) x.AddMacOSUserDefaults(true); x.AddHomeBrew(); }) - .EnableHelp(HelpCommandKind.CommandOrArgument) + .UseValidation() + .PrintFooterText([""]) + .EnableHelp(HelpCommandKind.CommandOrArgument, HelpCommandKind.EmptyArgs) .Build() .RunAsync(args).ConfigureAwait(false); diff --git a/source/Directory.Build.props b/source/Directory.Build.props new file mode 100644 index 0000000..df8fb07 --- /dev/null +++ b/source/Directory.Build.props @@ -0,0 +1,8 @@ + + + net10.0 + CreativeCoders + False + $(NoWarn);IDE0079 + + \ No newline at end of file diff --git a/tests/CreativeCoders.MacOS.UserDefaults.Tests/CreativeCoders.MacOS.UserDefaults.Tests.csproj b/tests/CreativeCoders.MacOS.UserDefaults.Tests/CreativeCoders.MacOS.UserDefaults.Tests.csproj index ec85901..e02dfbc 100644 --- a/tests/CreativeCoders.MacOS.UserDefaults.Tests/CreativeCoders.MacOS.UserDefaults.Tests.csproj +++ b/tests/CreativeCoders.MacOS.UserDefaults.Tests/CreativeCoders.MacOS.UserDefaults.Tests.csproj @@ -1,13 +1,12 @@  - net10.0 enable enable - + @@ -18,11 +17,11 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props new file mode 100644 index 0000000..df8fb07 --- /dev/null +++ b/tests/Directory.Build.props @@ -0,0 +1,8 @@ + + + net10.0 + CreativeCoders + False + $(NoWarn);IDE0079 + + \ No newline at end of file