diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..2c93b88
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,114 @@
+name: CI
+
+on:
+ push:
+ tags-ignore:
+ - 'v*'
+ pull_request:
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+env:
+ DOTNET_NOLOGO: true
+ CARGO_TERM_COLOR: always
+
+jobs:
+ rust-lint:
+ name: Rust Lint
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Setup Rust
+ shell: bash
+ run: |
+ rustup toolchain install stable --profile minimal
+ rustup component add rustfmt clippy --toolchain stable
+ rustup default stable
+
+ - name: Check formatting
+ run: cargo fmt --manifest-path rust/Cargo.toml --all --check
+
+ - name: Run clippy
+ run: cargo clippy -q --manifest-path rust/Cargo.toml --workspace --tests -- -D warnings
+
+ rust-build:
+ name: Rust Build (${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-latest
+ - windows-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Setup Rust on Linux
+ if: runner.os != 'Windows'
+ shell: bash
+ run: |
+ rustup toolchain install stable --profile minimal
+ rustup default stable
+
+ - name: Setup Rust on Windows
+ if: runner.os == 'Windows'
+ shell: pwsh
+ run: |
+ rustup toolchain install stable --profile minimal
+ rustup default stable
+
+ - name: Test pinget-core
+ run: cargo test -p pinget-core --manifest-path rust/Cargo.toml
+
+ - name: Test pinget-cli
+ run: cargo test -p pinget-cli --manifest-path rust/Cargo.toml
+
+ - name: Build pinget-cli
+ run: cargo build -p pinget-cli --manifest-path rust/Cargo.toml
+
+ dotnet:
+ name: Dotnet Build
+ runs-on: windows-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Install Pester
+ shell: pwsh
+ run: |
+ Set-PSRepository PSGallery -InstallationPolicy Trusted
+ Install-Module Pester -Scope CurrentUser -Force -SkipPublisherCheck
+
+ - name: Restore solution
+ run: dotnet restore dotnet/Devolutions.Pinget.slnx
+
+ - name: Build solution
+ run: dotnet build dotnet/Devolutions.Pinget.slnx -c Release --no-restore
+
+ - name: Run core tests
+ run: dotnet test dotnet/src/Devolutions.Pinget.Core.Tests/Devolutions.Pinget.Core.Tests.csproj -c Release --no-build
+
+ - name: Run PowerShell tests
+ shell: pwsh
+ run: pwsh -NoLogo -NoProfile -File (Resolve-Path 'dotnet/tests/RunTests.ps1')
+
+ - name: Validate NuGet packing
+ shell: pwsh
+ run: |
+ New-Item -Path artifacts/ci-nuget -ItemType Directory -Force | Out-Null
+ dotnet pack dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj -c Release --no-build -o artifacts/ci-nuget
+ dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj -c Release --no-build -o artifacts/ci-nuget
+ dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj -c Release --no-build -o artifacts/ci-nuget
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..6d8308f
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,394 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - master
+ workflow_dispatch:
+ inputs:
+ version:
+ description: Package version to release. Defaults to the version detected from source files.
+ required: false
+ type: string
+ dry-run:
+ description: Build and package only; skip tag creation, GitHub release, and NuGet publication.
+ required: false
+ default: true
+ type: boolean
+ publish-nuget:
+ description: Publish packages to NuGet.org during a manual release.
+ required: false
+ default: false
+ type: boolean
+
+permissions:
+ contents: write
+
+env:
+ DOTNET_NOLOGO: true
+ CARGO_TERM_COLOR: always
+
+jobs:
+ preflight:
+ name: Preflight
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.info.outputs.version }}
+ tag-name: ${{ steps.info.outputs.tag-name }}
+ dry-run: ${{ steps.info.outputs.dry-run }}
+ publish-nuget: ${{ steps.info.outputs.publish-nuget }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Package information
+ id: info
+ shell: pwsh
+ run: |
+ $IsMasterBranch = ('${{ github.ref_name }}' -eq 'master')
+ $IsWorkflowDispatch = ('${{ github.event_name }}' -eq 'workflow_dispatch')
+
+ $DryRun = $false
+ $PublishNuget = $true
+
+ if ($IsWorkflowDispatch) {
+ try { $DryRun = [System.Boolean]::Parse('${{ inputs['dry-run'] }}') } catch { $DryRun = $true }
+ try { $PublishNuget = [System.Boolean]::Parse('${{ inputs['publish-nuget'] }}') } catch { $PublishNuget = $false }
+ }
+
+ if (-not $IsMasterBranch) {
+ $DryRun = $true
+ $PublishNuget = $false
+ }
+
+ if ($DryRun) {
+ $PublishNuget = $false
+ }
+
+ $Version = '${{ inputs.version }}'
+ if ([string]::IsNullOrWhiteSpace($Version)) {
+ $coreVersion = Select-String -Path 'rust/crates/pinget-core/Cargo.toml' -Pattern '^version = "([^"]+)"$' | Select-Object -First 1
+ $cliVersion = Select-String -Path 'rust/crates/pinget-cli/Cargo.toml' -Pattern '^version = "([^"]+)"$' | Select-Object -First 1
+ $dotnetVersion = Select-String -Path 'dotnet/src/Devolutions.Pinget.Cli/Program.cs' -Pattern '^const string Version = "([^"]+)";$' | Select-Object -First 1
+
+ if (($null -eq $coreVersion) -or ($null -eq $cliVersion) -or ($null -eq $dotnetVersion)) {
+ throw 'Unable to detect version from source files'
+ }
+
+ $coreVersionValue = $coreVersion.Matches[0].Groups[1].Value
+ $cliVersionValue = $cliVersion.Matches[0].Groups[1].Value
+ $dotnetVersionValue = $dotnetVersion.Matches[0].Groups[1].Value
+
+ if (($coreVersionValue -ne $cliVersionValue) -or ($coreVersionValue -ne $dotnetVersionValue)) {
+ throw "Version mismatch detected: pinget-core=$coreVersionValue pinget-cli=$cliVersionValue dotnet=$dotnetVersionValue"
+ }
+
+ $Version = $coreVersionValue
+ }
+
+ if ([string]::IsNullOrWhiteSpace($Version)) {
+ throw 'Package version is empty'
+ }
+
+ $TagName = "v$Version"
+
+ "version=$Version" >> $Env:GITHUB_OUTPUT
+ "tag-name=$TagName" >> $Env:GITHUB_OUTPUT
+ "dry-run=$($DryRun.ToString().ToLower())" >> $Env:GITHUB_OUTPUT
+ "publish-nuget=$($PublishNuget.ToString().ToLower())" >> $Env:GITHUB_OUTPUT
+
+ Write-Host "::notice::Version: $Version"
+ Write-Host "::notice::Tag: $TagName"
+ Write-Host "::notice::DryRun: $DryRun"
+ Write-Host "::notice::PublishNuget: $PublishNuget"
+
+ rust-artifacts:
+ name: Rust Artifacts (${{ matrix.name }})
+ runs-on: ${{ matrix.os }}
+ needs: preflight
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: linux-x64
+ os: ubuntu-latest
+ target: x86_64-unknown-linux-gnu
+ archive_name: pinget-linux-x64.zip
+ binary_name: pinget
+ - name: linux-arm64
+ os: ubuntu-latest
+ target: aarch64-unknown-linux-gnu
+ archive_name: pinget-linux-arm64.zip
+ binary_name: pinget
+ - name: windows-x64
+ os: windows-latest
+ target: x86_64-pc-windows-msvc
+ archive_name: pinget-windows-x64.zip
+ binary_name: pinget.exe
+ - name: windows-arm64
+ os: windows-latest
+ target: aarch64-pc-windows-msvc
+ archive_name: pinget-windows-arm64.zip
+ binary_name: pinget.exe
+ - name: macos-x64
+ os: macos-14
+ target: x86_64-apple-darwin
+ archive_name: pinget-macos-x64.zip
+ binary_name: pinget
+ - name: macos-arm64
+ os: macos-14
+ target: aarch64-apple-darwin
+ archive_name: pinget-macos-arm64.zip
+ binary_name: pinget
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Install Rust toolchain
+ shell: pwsh
+ run: |
+ rustup toolchain install stable --profile minimal --target "${{ matrix.target }}"
+ rustup default stable
+
+ - name: Install Linux ARM64 linker
+ if: matrix.target == 'aarch64-unknown-linux-gnu'
+ shell: bash
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y gcc-aarch64-linux-gnu
+
+ - name: Configure static MSVC runtime
+ if: contains(matrix.target, 'windows-msvc')
+ shell: pwsh
+ run: |
+ "RUSTFLAGS=-C target-feature=+crt-static" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
+
+ - name: Build release binary
+ shell: pwsh
+ env:
+ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
+ run: |
+ cargo build --release --package pinget-cli --bin pinget --manifest-path rust/Cargo.toml --target "${{ matrix.target }}"
+
+ - name: Package artifacts
+ shell: pwsh
+ env:
+ TARGET: ${{ matrix.target }}
+ PINGET_BIN_NAME: ${{ matrix.binary_name }}
+ PINGET_ARCHIVE_NAME: ${{ matrix.archive_name }}
+ run: |
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
+
+ $target = $env:TARGET
+ $binaryName = $env:PINGET_BIN_NAME
+ $archiveName = $env:PINGET_ARCHIVE_NAME
+ $binaryPath = [System.IO.Path]::Combine('rust', 'target', $target, 'release', $binaryName)
+
+ if (-not (Test-Path -Path $binaryPath)) {
+ throw "Binary not found: $binaryPath"
+ }
+
+ if (Test-Path -Path $archiveName) {
+ Remove-Item -Path $archiveName -Force
+ }
+
+ $archive = [System.IO.Compression.ZipFile]::Open($archiveName, [System.IO.Compression.ZipArchiveMode]::Create)
+ try {
+ [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
+ $archive,
+ $binaryPath,
+ $binaryName,
+ [System.IO.Compression.CompressionLevel]::Optimal
+ ) | Out-Null
+ }
+ finally {
+ $archive.Dispose()
+ }
+
+ Write-Host "Created $archiveName"
+
+ - name: Upload Rust artifact
+ uses: actions/upload-artifact@v7
+ with:
+ name: ${{ matrix.archive_name }}
+ path: ${{ matrix.archive_name }}
+ if-no-files-found: error
+
+ csharp-packages:
+ name: C# Packages
+ runs-on: windows-latest
+ needs: preflight
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Install Pester
+ shell: pwsh
+ run: |
+ Set-PSRepository PSGallery -InstallationPolicy Trusted
+ Install-Module Pester -Scope CurrentUser -Force -SkipPublisherCheck
+
+ - name: Restore solution
+ run: dotnet restore dotnet/Devolutions.Pinget.slnx
+
+ - name: Build solution
+ run: dotnet build dotnet/Devolutions.Pinget.slnx -c Release --no-restore
+
+ - name: Run core tests
+ run: dotnet test dotnet/src/Devolutions.Pinget.Core.Tests/Devolutions.Pinget.Core.Tests.csproj -c Release --no-build
+
+ - name: Run PowerShell tests
+ shell: pwsh
+ run: pwsh -NoLogo -NoProfile -File (Resolve-Path 'dotnet/tests/RunTests.ps1')
+
+ - name: Pack NuGet packages
+ shell: pwsh
+ env:
+ PACKAGE_VERSION: ${{ needs.preflight.outputs.version }}
+ run: |
+ New-Item -Path dist/nuget -ItemType Directory -Force | Out-Null
+ $packArgs = @('-c', 'Release', '--no-build', '-p:ContinuousIntegrationBuild=true', "-p:Version=$env:PACKAGE_VERSION", '-p:IncludeSymbols=true', '-p:SymbolPackageFormat=snupkg', '-o', 'dist/nuget')
+ dotnet pack dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj @packArgs
+ dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj @packArgs
+ dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj @packArgs
+
+ - name: Package PowerShell module
+ shell: pwsh
+ env:
+ PACKAGE_VERSION: ${{ needs.preflight.outputs.version }}
+ run: |
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
+
+ $moduleName = 'Pinget'
+ $moduleVersion = $env:PACKAGE_VERSION
+ $moduleOutput = Join-Path 'dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/bin/Release' 'net8.0'
+ $stagingRoot = Join-Path 'dist' 'powershell-module'
+ $moduleRoot = Join-Path $stagingRoot $moduleName
+ $archivePath = Join-Path 'dist' ("pinget-powershell-module-$moduleVersion.zip")
+
+ if (-not (Test-Path -Path (Join-Path $moduleOutput 'Pinget.psd1'))) {
+ throw "PowerShell module manifest not found in $moduleOutput"
+ }
+
+ if (Test-Path -Path $stagingRoot) {
+ Remove-Item -Path $stagingRoot -Recurse -Force
+ }
+
+ if (Test-Path -Path $archivePath) {
+ Remove-Item -Path $archivePath -Force
+ }
+
+ New-Item -Path $moduleRoot -ItemType Directory -Force | Out-Null
+ Copy-Item -Path (Join-Path $moduleOutput '*') -Destination $moduleRoot -Recurse -Force
+ [System.IO.Compression.ZipFile]::CreateFromDirectory($stagingRoot, $archivePath, [System.IO.Compression.CompressionLevel]::Optimal, $false)
+
+ Write-Host "Created $archivePath"
+
+ - name: Upload package artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: csharp-nuget
+ path: |
+ dist/nuget/*.nupkg
+ dist/nuget/*.snupkg
+ if-no-files-found: error
+
+ - name: Upload PowerShell module artifact
+ uses: actions/upload-artifact@v7
+ with:
+ name: powershell-module
+ path: dist/pinget-powershell-module-*.zip
+ if-no-files-found: error
+
+ create-tag:
+ name: Create Tag
+ runs-on: ubuntu-latest
+ needs:
+ - preflight
+ - rust-artifacts
+ - csharp-packages
+ if: ${{ fromJSON(needs.preflight.outputs.dry-run) == false }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Ensure tag does not already exist
+ shell: bash
+ run: |
+ if git ls-remote --exit-code --tags origin "refs/tags/${{ needs.preflight.outputs.tag-name }}" >/dev/null 2>&1; then
+ echo "Tag ${{ needs.preflight.outputs.tag-name }} already exists on origin" >&2
+ exit 1
+ fi
+
+ - name: Create and push tag
+ shell: bash
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git tag -a "${{ needs.preflight.outputs.tag-name }}" "${GITHUB_SHA}" -m "Release ${{ needs.preflight.outputs.tag-name }}"
+ git push origin "${{ needs.preflight.outputs.tag-name }}"
+
+ github-release:
+ name: GitHub Release
+ runs-on: ubuntu-latest
+ needs:
+ - preflight
+ - create-tag
+ - rust-artifacts
+ - csharp-packages
+ if: ${{ fromJSON(needs.preflight.outputs.dry-run) == false }}
+
+ steps:
+ - name: Download all artifacts
+ uses: actions/download-artifact@v8
+ with:
+ path: dist/release
+ merge-multiple: true
+
+ - name: Create GitHub release
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release create "${{ needs.preflight.outputs.tag-name }}" dist/release/*.zip dist/release/*.nupkg dist/release/*.snupkg --generate-notes
+
+ publish-nuget:
+ name: Publish NuGet
+ runs-on: ubuntu-latest
+ needs:
+ - preflight
+ - csharp-packages
+ - create-tag
+ - github-release
+ if: ${{ fromJSON(needs.preflight.outputs.dry-run) == false && fromJSON(needs.preflight.outputs.publish-nuget) == true }}
+
+ steps:
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Download package artifacts
+ uses: actions/download-artifact@v8
+ with:
+ name: csharp-nuget
+ path: dist/nuget
+
+ - name: Push packages to NuGet.org
+ if: env.NUGET_API_KEY != ''
+ shell: bash
+ env:
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ run: |
+ dotnet nuget push dist/nuget/*.nupkg --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push dist/nuget/*.snupkg --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate
\ No newline at end of file
diff --git a/dotnet/Directory.Build.props b/dotnet/Directory.Build.props
new file mode 100644
index 0000000..6d59fcf
--- /dev/null
+++ b/dotnet/Directory.Build.props
@@ -0,0 +1,15 @@
+
+
+ Devolutions
+ Devolutions Inc.
+ MIT
+ https://github.com/Devolutions/pinget
+ https://github.com/Devolutions/pinget.git
+ git
+ true
+ false
+ pinget;winget;package-manager;powershell;dotnet
+ See the repository changelog and release notes for details.
+ Copyright 2021-2026 Devolutions Inc.
+
+
\ No newline at end of file
diff --git a/dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj b/dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj
index 418431a..62a8689 100644
--- a/dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj
+++ b/dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj
@@ -1,7 +1,7 @@
- net10.0
+ net8.0;net10.0
enable
enable
true
diff --git a/dotnet/src/Devolutions.Pinget.Core/Repository.cs b/dotnet/src/Devolutions.Pinget.Core/Repository.cs
index d4c2ebe..c91199a 100644
--- a/dotnet/src/Devolutions.Pinget.Core/Repository.cs
+++ b/dotnet/src/Devolutions.Pinget.Core/Repository.cs
@@ -2019,7 +2019,7 @@ private static bool SearchMatchHasUnknownVersion(SearchMatch match) =>
private static string Sha256Hex(byte[] data)
{
var hash = SHA256.HashData(data);
- return Convert.ToHexStringLower(hash);
+ return Convert.ToHexString(hash).ToLowerInvariant();
}
private class VersionComparer : IComparer
diff --git a/dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj b/dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj
index d404b77..cb24ffd 100644
--- a/dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj
+++ b/dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/Devolutions.Pinget.PowerShell.Cmdlets.csproj
@@ -8,17 +8,26 @@
- net10.0
+ net8.0;net10.0
enable
enable
true
true
+ $(TargetsForTfmSpecificContentInPackage);AddPowerShellModuleFilesToPackage
Devolutions.Pinget.PowerShell.Cmdlets
Devolutions.Pinget.PowerShell.Cmdlets
Devolutions.Pinget.PowerShell.Cmdlets
PowerShell cmdlets for Pinget.
+
+
+
+ lib\$(TargetFramework)\%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+
diff --git a/dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj b/dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj
index 7c17438..9edeba9 100644
--- a/dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj
+++ b/dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj
@@ -4,7 +4,7 @@
- net10.0
+ net8.0;net10.0
enable
enable
true
diff --git a/dotnet/tests/RunTests.ps1 b/dotnet/tests/RunTests.ps1
index 8dc787d..601dafe 100644
--- a/dotnet/tests/RunTests.ps1
+++ b/dotnet/tests/RunTests.ps1
@@ -1,6 +1,6 @@
[CmdletBinding()]
param(
- [string]$ModulePath = (Join-Path $PSScriptRoot '..\src\Devolutions.Pinget.PowerShell.Cmdlets\bin\Release\net10.0\Pinget.psd1'),
+ [string]$ModulePath = (Join-Path $PSScriptRoot '..\src\Devolutions.Pinget.PowerShell.Cmdlets\bin\Release\net8.0\Pinget.psd1'),
[string]$SourceArgument = 'https://api.winget.pro/4259fd23-6fcd-46bf-9287-be8833cfbdd5'
)
diff --git a/rust/crates/pinget-cli/Cargo.toml b/rust/crates/pinget-cli/Cargo.toml
index 24063c6..e23a013 100644
--- a/rust/crates/pinget-cli/Cargo.toml
+++ b/rust/crates/pinget-cli/Cargo.toml
@@ -17,7 +17,7 @@ pinget-core = { version = "0.1.0", path = "../pinget-core" }
chrono = "0.4.44"
dirs = "6.0"
jsonschema = "0.30"
-reqwest = { version = "0.12", features = ["blocking"] }
+reqwest = { version = "0.12", default-features = false, features = ["blocking", "rustls-tls"] }
rusqlite = { version = "0.39", features = ["bundled"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.149"
diff --git a/rust/crates/pinget-core/src/lib.rs b/rust/crates/pinget-core/src/lib.rs
index 045432b..10bb561 100644
--- a/rust/crates/pinget-core/src/lib.rs
+++ b/rust/crates/pinget-core/src/lib.rs
@@ -2022,7 +2022,7 @@ impl Repository {
.headers()
.get("x-ms-meta-sourceversion")
.and_then(|value| value.to_str().ok())
- .map(str::to_string);
+ .map(str::to_owned);
let bytes = response.bytes().context("failed to read preindexed package bytes")?;
let payload = bytes.to_vec();
let index_bytes = extract_zip_member(&payload, "Public/index.db")
@@ -2055,7 +2055,7 @@ impl Repository {
source.identifier = info.source_identifier.clone();
}
source.last_update = Some(Utc::now());
- source.source_version = choose_contract(&info.server_supported_versions).map(str::to_string);
+ source.source_version = choose_contract(&info.server_supported_versions).map(str::to_owned);
Ok("refreshed information cache".to_owned())
}
@@ -4467,7 +4467,7 @@ fn yaml_scalar_string(value: &YamlValue) -> Option {
fn yaml_string_list(root: &YamlMapping, key: &str) -> Vec {
root.get(YamlValue::from(key))
.and_then(YamlValue::as_sequence)
- .map(|items| items.iter().filter_map(YamlValue::as_str).map(str::to_string).collect())
+ .map(|items| items.iter().filter_map(YamlValue::as_str).map(str::to_owned).collect())
.unwrap_or_default()
}
@@ -4523,14 +4523,14 @@ fn yaml_package_dependencies(root: &YamlMapping) -> Vec {
}
fn json_string(value: &JsonValue, key: &str) -> Option {
- value.get(key).and_then(JsonValue::as_str).map(str::to_string)
+ value.get(key).and_then(JsonValue::as_str).map(str::to_owned)
}
fn json_string_list(value: &JsonValue, key: &str) -> Vec {
value
.get(key)
.and_then(JsonValue::as_array)
- .map(|items| items.iter().filter_map(JsonValue::as_str).map(str::to_string).collect())
+ .map(|items| items.iter().filter_map(JsonValue::as_str).map(str::to_owned).collect())
.unwrap_or_default()
}
@@ -4595,7 +4595,7 @@ fn json_installer_switches(value: &JsonValue) -> InstallerSwitches {
switches
.and_then(|switches| switches.get(key))
.and_then(JsonValue::as_str)
- .map(str::to_string)
+ .map(str::to_owned)
};
InstallerSwitches {
@@ -6199,13 +6199,8 @@ Installers:
#[test]
fn parses_fixture_manifest() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
- .join("..")
- .join("..")
- .join("..")
- .join("..")
- .join("src")
- .join("AppInstallerCLITests")
- .join("TestData")
+ .join("tests")
+ .join("fixtures")
.join("ManifestV1_28-Singleton.yaml");
let bytes = fs::read(root).expect("fixture bytes");
let manifest = parse_yaml_manifest(&bytes).expect("manifest");
diff --git a/rust/crates/pinget-core/tests/fixtures/ManifestV1_28-Singleton.yaml b/rust/crates/pinget-core/tests/fixtures/ManifestV1_28-Singleton.yaml
new file mode 100644
index 0000000..24d2cba
--- /dev/null
+++ b/rust/crates/pinget-core/tests/fixtures/ManifestV1_28-Singleton.yaml
@@ -0,0 +1,13 @@
+PackageIdentifier: microsoft.msixsdk
+PackageVersion: 1.7.32
+PackageLocale: en-US
+PackageName: MSIX SDK
+Publisher: Microsoft
+ShortDescription: Test fixture manifest for pinget-core parsing.
+ManifestType: singleton
+ManifestVersion: 1.10.0
+Installers:
+ - Architecture: x64
+ InstallerType: exe
+ InstallerUrl: https://example.test/msixsdk-x64.exe
+ InstallerSha256: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
\ No newline at end of file