mirror of
https://github.com/Smaug123/WoofWare.DotnetRuntimeLocator
synced 2025-10-06 07:48:39 +00:00
Compare commits
68 Commits
WoofWare.D
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
c380f95ea5 | ||
|
1895f28c7b | ||
|
f6ff717135 | ||
|
2111177d4f | ||
|
cf249fd556 | ||
|
4704c471bc | ||
|
0f6ab4345c | ||
|
04caa77a2d | ||
|
2fd85399f4 | ||
|
7bccc10aab | ||
|
3492eec8d1 | ||
|
17a179309d | ||
|
72ba1a73f2 | ||
|
d7425bd959 | ||
|
c6c8da38b1 | ||
|
8c47fb5d0c | ||
|
1f4691d040 | ||
|
746389cbb5 | ||
|
9f0013e771 | ||
|
6dbc283237 | ||
|
548a8f9d6a | ||
|
6f24a09daf | ||
|
9668acb5ff | ||
|
b4fa714249 | ||
|
75cfe6d55e | ||
|
8ae289665c | ||
|
23158bc07d | ||
|
785b1f28be | ||
|
5dcd188f40 | ||
|
b1cae0acb7 | ||
|
5a7eb63590 | ||
|
1b534018e9 | ||
|
a013fc415e | ||
|
bbdabd8206 | ||
|
787ebffc21 | ||
|
ffbc46dad5 | ||
|
e67c1f2f4e | ||
|
4dc5d06082 | ||
|
16c8999b50 | ||
|
074fee4cd6 | ||
|
1b4f69df96 | ||
|
4a498a9729 | ||
|
84feacc7aa | ||
|
d317109c93 | ||
|
91873c8d0e | ||
|
b41d221acf | ||
|
a968e43ea5 | ||
|
ea34dd0447 | ||
|
bc5cf83a23 | ||
|
a5718e9816 | ||
|
59e9866a4c | ||
|
ea8db204c2 | ||
|
4cafe1268d | ||
|
cb9ca1dab9 | ||
|
3e6f9a0e14 | ||
|
71d222962a | ||
|
9dc3abcff4 | ||
|
3a4339043d | ||
|
8e59918cee | ||
|
8adcc54d4d | ||
|
57a6708318 | ||
|
76d466cb16 | ||
|
c2bdaf0623 | ||
|
71640cf4ca | ||
|
b598a51b29 | ||
|
afca66ef4f | ||
|
64f8913624 | ||
|
c75ec6aff9 |
22
.envrc
22
.envrc
@@ -1 +1,23 @@
|
||||
use flake
|
||||
DOTNET_PATH=$(readlink "$(which dotnet)")
|
||||
SETTINGS_FILE=$(find . -maxdepth 1 -type f -name '*.sln.DotSettings.user')
|
||||
MSBUILD=$(realpath "$(find "$(dirname "$DOTNET_PATH")/../share/dotnet/sdk" -maxdepth 2 -type f -name MSBuild.dll)")
|
||||
if [ -f "$SETTINGS_FILE" ] ; then
|
||||
xmlstarlet ed --inplace \
|
||||
-N wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" \
|
||||
-N x="http://schemas.microsoft.com/winfx/2006/xaml" \
|
||||
-N s="clr-namespace:System;assembly=mscorlib" \
|
||||
-N ss="urn:shemas-jetbrains-com:settings-storage-xaml" \
|
||||
--update "//s:String[@x:Key='/Default/Environment/Hierarchy/Build/BuildTool/DotNetCliExePath/@EntryValue']" \
|
||||
--value "$(realpath "$(dirname "$DOTNET_PATH")/../share/dotnet/dotnet")" \
|
||||
"$SETTINGS_FILE"
|
||||
|
||||
xmlstarlet ed --inplace \
|
||||
-N wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" \
|
||||
-N x="http://schemas.microsoft.com/winfx/2006/xaml" \
|
||||
-N s="clr-namespace:System;assembly=mscorlib" \
|
||||
-N ss="urn:shemas-jetbrains-com:settings-storage-xaml" \
|
||||
--update "//s:String[@x:Key='/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue']" \
|
||||
--value "$MSBUILD" \
|
||||
"$SETTINGS_FILE"
|
||||
fi
|
||||
|
107
.github/workflows/dotnet.yaml
vendored
107
.github/workflows/dotnet.yaml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- uses: actions/setup-dotnet@v4
|
||||
- uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Restore dependencies
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Publish
|
||||
run: dotnet publish Example
|
||||
- name: Run example
|
||||
run: ".\\Example\\bin\\Release\\net8.0\\win-x64\\Example.exe"
|
||||
run: ".\\Example\\bin\\Release\\net8.0\\Example.exe"
|
||||
|
||||
build:
|
||||
strategy:
|
||||
@@ -43,11 +43,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -57,18 +57,22 @@ jobs:
|
||||
run: nix develop --command dotnet build --no-restore --configuration ${{matrix.config}}
|
||||
- name: Test
|
||||
run: nix develop --command dotnet test --no-build --verbosity normal --configuration ${{matrix.config}}
|
||||
- name: Publish example
|
||||
run: nix develop --command dotnet publish --no-build --verbosity normal --configuration ${{matrix.config}} Example
|
||||
- name: Publish example self-contained
|
||||
run: nix develop --command dotnet publish --self-contained --runtime linux-x64 --verbosity normal --configuration ${{matrix.config}} Example
|
||||
- name: Run example self-contained
|
||||
run: "./Example/bin/${{matrix.config}}/*/*/Example"
|
||||
run: "./Example/bin/${{matrix.config}}/net*/*-*/Example"
|
||||
- name: Publish example non-self-contained
|
||||
run: nix develop --command dotnet publish --verbosity normal --configuration ${{matrix.config}} Example
|
||||
- name: Run example non-self-contained
|
||||
run: "./Example/bin/${{matrix.config}}/net*/Example"
|
||||
|
||||
build-nix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -81,9 +85,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -94,9 +98,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -109,7 +113,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -122,7 +126,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -132,11 +136,11 @@ jobs:
|
||||
nuget-pack:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -157,7 +161,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: nuget-package
|
||||
path: packed
|
||||
@@ -166,19 +170,31 @@ jobs:
|
||||
run: if [[ $(find packed -maxdepth 1 -name 'WoofWare.DotnetRuntimeLocator.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
|
||||
|
||||
github-release-dry-run:
|
||||
needs: [nuget-pack]
|
||||
runs-on: ubuntu-latest
|
||||
needs: [nuget-pack]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Download NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: nuget-package
|
||||
- name: Tag and release
|
||||
- name: Compute package path
|
||||
id: compute-path
|
||||
run: |
|
||||
find . -maxdepth 1 -type f -name 'WoofWare.DotnetRuntimeLocator.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||
- name: Compute tag name
|
||||
id: compute-tag
|
||||
env:
|
||||
DRY_RUN: 1
|
||||
GITHUB_TOKEN: mock-token
|
||||
run: sh .github/workflows/tag.sh
|
||||
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||
- name: Tag and release
|
||||
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-commitish: ${{ github.sha }}
|
||||
tag: ${{ steps.compute-tag.outputs.output }}
|
||||
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||
dry-run: true
|
||||
|
||||
all-required-checks-complete:
|
||||
if: ${{ always() }}
|
||||
@@ -199,12 +215,12 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Download NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: nuget-package
|
||||
path: packed
|
||||
- name: Attest Build Provenance
|
||||
uses: actions/attest-build-provenance@ef244123eb79f2f7a7e75d99086184180e6d0018 # v1.4.4
|
||||
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||
with:
|
||||
subject-path: "packed/WoofWare.DotnetRuntimeLocator.*.nupkg"
|
||||
|
||||
@@ -218,25 +234,30 @@ jobs:
|
||||
attestations: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Download NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: nuget-package
|
||||
path: packed
|
||||
- name: Identify .NET
|
||||
id: identify-dotnet
|
||||
run: nix develop --command bash -c "echo dotnet=$(which dotnet) >> $GITHUB_OUTPUT"
|
||||
- name: Obtain NuGet key
|
||||
uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544
|
||||
id: login
|
||||
with:
|
||||
user: ${{ secrets.NUGET_USER }}
|
||||
- name: Publish NuGet package
|
||||
uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059
|
||||
with:
|
||||
package-name: WoofWare.DotnetRuntimeLocator
|
||||
nuget-key: ${{ secrets.NUGET_API_KEY }}
|
||||
nuget-key: ${{ steps.login.outputs.NUGET_API_KEY }}
|
||||
nupkg-dir: packed/
|
||||
dotnet: ${{ steps.identify-dotnet.outputs.dotnet }}
|
||||
|
||||
@@ -248,12 +269,24 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Download NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: nuget-package
|
||||
- name: Tag and release
|
||||
- name: Compute package path
|
||||
id: compute-path
|
||||
run: |
|
||||
find . -maxdepth 1 -type f -name 'WoofWare.DotnetRuntimeLocator.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||
- name: Compute tag name
|
||||
id: compute-tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: sh .github/workflows/tag.sh
|
||||
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||
- name: Tag and release
|
||||
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-commitish: ${{ github.sha }}
|
||||
tag: ${{ steps.compute-tag.outputs.output }}
|
||||
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||
|
12
.github/workflows/flake_update.yaml
vendored
12
.github/workflows/flake_update.yaml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
@@ -21,18 +21,18 @@ jobs:
|
||||
- name: Update Nix flake
|
||||
run: 'nix flake update'
|
||||
|
||||
- name: Build passthru
|
||||
run: 'nix build ".#default.passthru.fetch-deps"'
|
||||
- name: Build fetch-deps
|
||||
run: 'nix build ".#default.fetch-deps"'
|
||||
|
||||
- name: Run passthru
|
||||
run: ./result nix/deps.nix
|
||||
- name: Run fetch-deps
|
||||
run: ./result nix/deps.json
|
||||
|
||||
- name: Format
|
||||
run: 'nix develop --command alejandra .'
|
||||
|
||||
- name: Create token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
# https://github.com/actions/create-github-app-token/issues/136
|
||||
app-id: ${{ secrets.APP_ID }}
|
||||
|
120
.github/workflows/tag.sh
vendored
120
.github/workflows/tag.sh
vendored
@@ -1,120 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Dry-run? $DRY_RUN!"
|
||||
|
||||
find . -maxdepth 1 -type f ! -name "$(printf "*\n*")" -name '*.nupkg' | while IFS= read -r file
|
||||
do
|
||||
tag=$(basename "$file" .nupkg)
|
||||
git tag "$tag"
|
||||
${DRY_RUN:+echo} git push origin "$tag"
|
||||
done
|
||||
|
||||
export TAG
|
||||
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.DotnetRuntimeLocator.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Attributes)
|
||||
|
||||
case "$TAG" in
|
||||
*"
|
||||
"*)
|
||||
echo "Error: TAG contains a newline; multiple plugins found."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# target_commitish empty indicates the repo default branch
|
||||
curl_body='{"tag_name":"'"$TAG"'","target_commitish":"","name":"'"$TAG"'","draft":false,"prerelease":false,"generate_release_notes":false}'
|
||||
|
||||
echo "cURL body: $curl_body"
|
||||
|
||||
failed_output=$(cat <<'EOF'
|
||||
{
|
||||
"message": "Validation Failed",
|
||||
"errors": [
|
||||
{
|
||||
"resource": "Release",
|
||||
"code": "already_exists",
|
||||
"field": "tag_name"
|
||||
}
|
||||
],
|
||||
"documentation_url": "https://docs.github.com/rest/releases/releases#create-a-release"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
success_output=$(cat <<'EOF'
|
||||
{
|
||||
"url": "https://api.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/releases/158152116",
|
||||
"assets_url": "https://api.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/releases/158152116/assets",
|
||||
"upload_url": "https://uploads.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/releases/158152116/assets{?name,label}",
|
||||
"html_url": "https://github.com/Smaug123/WoofWare.DotnetRuntimeLocator/releases/tag/WoofWare.DotnetRuntimeLocator.2.1.30",
|
||||
"id": 158152116,
|
||||
"author": {
|
||||
"login": "github-actions[bot]",
|
||||
"id": 41898282,
|
||||
"node_id": "MDM6Qm90NDE4OTgyODI=",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/github-actions%5Bbot%5D",
|
||||
"html_url": "https://github.com/apps/github-actions",
|
||||
"followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
|
||||
"following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
|
||||
"repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
|
||||
"events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
|
||||
"type": "Bot",
|
||||
"site_admin": false
|
||||
},
|
||||
"node_id": "RE_kwDOJfksgc4JbTW0",
|
||||
"tag_name": "WoofWare.DotnetRuntimeLocator.2.1.30",
|
||||
"target_commitish": "main",
|
||||
"name": "WoofWare.DotnetRuntimeLocator.2.1.30",
|
||||
"draft": false,
|
||||
"prerelease": false,
|
||||
"created_at": "2024-05-30T11:00:55Z",
|
||||
"published_at": "2024-05-30T11:03:02Z",
|
||||
"assets": [
|
||||
|
||||
],
|
||||
"tarball_url": "https://api.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/tarball/WoofWare.DotnetRuntimeLocator.2.1.30",
|
||||
"zipball_url": "https://api.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/zipball/WoofWare.DotnetRuntimeLocator.2.1.30",
|
||||
"body": null
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
HANDLE_OUTPUT=''
|
||||
handle_error() {
|
||||
ERROR_OUTPUT="$1"
|
||||
exit_message=$(echo "$ERROR_OUTPUT" | jq -r --exit-status 'if .errors | length == 1 then .errors[0].code else null end')
|
||||
if [ "$exit_message" = "already_exists" ] ; then
|
||||
HANDLE_OUTPUT="Did not create GitHub release because it already exists at this version."
|
||||
else
|
||||
echo "Unexpected error output from curl: $(cat curl_output.json)"
|
||||
echo "JQ output: $(exit_message)"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
handle_error "$failed_output"
|
||||
if [ "$HANDLE_OUTPUT" != "Did not create GitHub release because it already exists at this version." ]; then
|
||||
echo "Bad output from handler: $HANDLE_OUTPUT"
|
||||
exit 3
|
||||
fi
|
||||
HANDLE_OUTPUT=''
|
||||
echo "Tests passed."
|
||||
}
|
||||
|
||||
run_tests
|
||||
|
||||
if [ "$DRY_RUN" != 1 ] ; then
|
||||
if curl --fail-with-body -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/Smaug123/WoofWare.DotnetRuntimeLocator/releases -d "$curl_body" > curl_output.json; then
|
||||
echo "Curl succeeded."
|
||||
else
|
||||
handle_error "$(cat curl_output.json)"
|
||||
echo "$HANDLE_OUTPUT"
|
||||
fi
|
||||
fi
|
@@ -10,7 +10,7 @@
|
||||
<WarnOn>FS3388,FS3559</WarnOn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.133" PrivateAssets="all"/>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.8.38-alpha" PrivateAssets="all"/>
|
||||
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
||||
|
@@ -1,17 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<SelfContained>true</SelfContained>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.fs"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.fs"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator\WoofWare.DotnetRuntimeLocator.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator\WoofWare.DotnetRuntimeLocator.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -1,6 +1,8 @@
|
||||
namespace Example
|
||||
namespace Example
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open WoofWare.DotnetRuntimeLocator
|
||||
|
||||
module Program =
|
||||
@@ -18,4 +20,16 @@ module Program =
|
||||
for f in info.Frameworks do
|
||||
Console.WriteLine $"Framework: %O{f}"
|
||||
|
||||
// Identify the runtime which would execute this DLL
|
||||
let self = Assembly.GetExecutingAssembly().Location
|
||||
let runtimeSearchDirs = DotnetRuntime.SelectForDll self
|
||||
// For example, the System.Text.Json.dll which this DLL would load:
|
||||
runtimeSearchDirs
|
||||
|> Seq.tryPick (fun dir ->
|
||||
let attempt = Path.Combine (dir, "System.Text.Json.dll")
|
||||
if File.Exists attempt then Some attempt else None
|
||||
)
|
||||
|> Option.get
|
||||
|> fun s -> Console.WriteLine $"System.Text.Json location: %s{s}"
|
||||
|
||||
0
|
||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Patrick Stevens
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
13
README.md
13
README.md
@@ -11,6 +11,11 @@ See [the example](Example/Program.fs).
|
||||
let info = DotnetEnvironmentInfo.Get ()
|
||||
// or, if you already know a path to the `dotnet` executable...
|
||||
let info = DotnetEnvironmentInfo.GetSpecific "/path/to/dotnet"
|
||||
|
||||
// identify the directories containing the framework which would execute a given DLL
|
||||
let dirsToSearch : string seq = DotnetRuntime.SelectForDll "/path/to/dll.dll"
|
||||
// or, if you would be running with a specific `/path/to/dotnet exec /path/to/dll.dll`:
|
||||
let dirsToSearch : string seq = DotnetRuntime.SelectForDll ("/path/to/dll.dll", "/path/to/dotnet")
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -20,4 +25,10 @@ The easiest way to make sure we can find a `dotnet` is to have one on your PATH.
|
||||
If you have a *very* strange setup, we may be unable to locate the `libhostfxr` library we use to find the runtimes.
|
||||
In that case, you can supply the environment variable `WOOFWARE_DOTNET_LOCATOR_LIBHOSTFXR`,
|
||||
which should be a full path to a `libhostfxr` DLL on your system.
|
||||
(Normally this is in `/usr/share/dotnet/host/fxr/{runtime}/libhostfxr.so`; you must make sure your version is from runtime 6 or greater, because the required symbols were not added until then.)
|
||||
(Normally this is in `/usr/share/dotnet/host/fxr/{runtime}/libhostfxr.so`;
|
||||
you must make sure your version is from runtime 6 or greater,
|
||||
because the required symbols were not added until then.)
|
||||
|
||||
# Licence
|
||||
|
||||
WoofWare.DotnetRuntimeLocator is licensed to you under the MIT licence, a copy of which can be found at [LICENSE](./LICENSE).
|
||||
|
@@ -117,7 +117,10 @@ public record DotnetEnvironmentInfo(
|
||||
/// <summary>
|
||||
/// Get the environment information that is available to the specified `dotnet` executable.
|
||||
/// </summary>
|
||||
/// <param name="dotnetExe">A `dotnet` (or `dotnet.exe`) executable, e.g. one from /usr/bin/dotnet. Set this to null if you want us to just do our best.</param>
|
||||
/// <param name="dotnetExe">
|
||||
/// A `dotnet` (or `dotnet.exe`) executable, e.g. one from /usr/bin/dotnet. Set this to null if you
|
||||
/// want us to just do our best.
|
||||
/// </param>
|
||||
/// <returns>Information about the environment available to the given executable.</returns>
|
||||
/// <exception cref="Exception">Throws on any failure; handles nothing gracefully.</exception>
|
||||
public static DotnetEnvironmentInfo GetSpecific(FileInfo? dotnetExe)
|
||||
@@ -140,6 +143,7 @@ public record DotnetEnvironmentInfo(
|
||||
dotnetParent = parent.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
return CallDelegate(dotnetParent, f);
|
||||
}
|
||||
finally
|
||||
@@ -169,10 +173,7 @@ public record DotnetEnvironmentInfo(
|
||||
foreach (var component in path.Split(':'))
|
||||
{
|
||||
var dotnet = Path.Combine(component, "dotnet");
|
||||
if (File.Exists(dotnet))
|
||||
{
|
||||
return new FileInfo(dotnet);
|
||||
}
|
||||
if (File.Exists(dotnet)) return new FileInfo(dotnet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +188,11 @@ public record DotnetEnvironmentInfo(
|
||||
/// <exception cref="Exception">Throws on any failure; handles nothing gracefully.</exception>
|
||||
public static DotnetEnvironmentInfo Get()
|
||||
{
|
||||
var dotnetExe = LocateDotnetExe();
|
||||
var dotnetExe = Environment.GetEnvironmentVariable("WOOFWARE_DOTNET_LOCATOR_DOTNET_EXE") switch
|
||||
{
|
||||
null => LocateDotnetExe(),
|
||||
var s => new FileInfo(s)
|
||||
};
|
||||
|
||||
// `null` can happen! Maybe we're self-contained.
|
||||
return GetSpecific(dotnetExe);
|
||||
|
319
WoofWare.DotnetRuntimeLocator/DotnetRuntime.cs
Normal file
319
WoofWare.DotnetRuntimeLocator/DotnetRuntime.cs
Normal file
@@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace WoofWare.DotnetRuntimeLocator;
|
||||
|
||||
/// <summary>
|
||||
/// The result of a call to `DotnetRuntime.Select`.
|
||||
/// This is `type DotnetRuntimeSelection = | Framework of DotnetEnvironmentFrameworkInfo | Sdk of
|
||||
/// DotnetEnvironmentSdkInfo | Absent`.
|
||||
/// </summary>
|
||||
internal class DotnetRuntimeSelection
|
||||
{
|
||||
private readonly int _discriminator;
|
||||
private readonly DotnetEnvironmentFrameworkInfo? _framework;
|
||||
private readonly DotnetEnvironmentSdkInfo? _sdk;
|
||||
|
||||
/// <summary>
|
||||
/// The constructor which means "We found the right runtime, and it's from this framework".
|
||||
/// </summary>
|
||||
/// <param name="framework">For example, </param>
|
||||
public DotnetRuntimeSelection(DotnetEnvironmentFrameworkInfo framework)
|
||||
{
|
||||
_discriminator = 1;
|
||||
_framework = framework;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor which means "We found the right runtime, and it's from this SDK".
|
||||
/// </summary>
|
||||
/// <param name="sdk">For example, </param>
|
||||
public DotnetRuntimeSelection(DotnetEnvironmentSdkInfo sdk)
|
||||
{
|
||||
_discriminator = 2;
|
||||
_sdk = sdk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor which means "We were unable to find an appropriate runtime".
|
||||
/// </summary>
|
||||
public DotnetRuntimeSelection()
|
||||
{
|
||||
_discriminator = 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exhaustive match on this discriminated union.
|
||||
/// </summary>
|
||||
/// <param name="withFramework">If `this` is a `Framework`, call this continuation with its value.</param>
|
||||
/// <param name="withSdk">If `this` is a `Sdk`, call this continuation with its value.</param>
|
||||
/// <param name="withNone">If `this` represents the absence of a result, call this continuation.</param>
|
||||
/// <returns>The result of the continuation which was called.</returns>
|
||||
public TRet Visit<TRet>(Func<DotnetEnvironmentFrameworkInfo, TRet> withFramework,
|
||||
Func<DotnetEnvironmentSdkInfo, TRet> withSdk,
|
||||
Func<TRet> withNone)
|
||||
{
|
||||
return _discriminator switch
|
||||
{
|
||||
1 => withFramework.Invoke(_framework!),
|
||||
2 => withSdk.Invoke(_sdk!),
|
||||
3 => withNone.Invoke(),
|
||||
_ => throw new InvalidOperationException($"unrecognised union discriminator %i{_discriminator}")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Module to hold methods for automatically identifying a .NET runtime.
|
||||
/// </summary>
|
||||
public static class DotnetRuntime
|
||||
{
|
||||
/// <returns>For each requested runtime in the RuntimeOptions, the resolved place in which to find that runtime.</returns>
|
||||
private static IReadOnlyDictionary<string, DotnetRuntimeSelection> SelectRuntime(RuntimeOptions options,
|
||||
DotnetEnvironmentInfo env)
|
||||
{
|
||||
var rollForwardEnvVar = Environment.GetEnvironmentVariable("DOTNET_ROLL_FORWARD");
|
||||
RollForward rollForward;
|
||||
if (rollForwardEnvVar == null)
|
||||
{
|
||||
rollForward = options.RollForward ?? RollForward.Minor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Enum.TryParse(rollForwardEnvVar, out rollForward))
|
||||
throw new ArgumentException(
|
||||
$"Unable to parse the value of environment variable DOTNET_ROLL_FORWARD, which was: {rollForwardEnvVar}");
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, Version> desiredVersions;
|
||||
if (options.IncludedFrameworks == null)
|
||||
{
|
||||
if (options.Framework == null)
|
||||
{
|
||||
if (options.Frameworks == null)
|
||||
throw new InvalidDataException(
|
||||
"Expected runtimeconfig.json file to have either a framework or frameworks entry, but it had neither");
|
||||
|
||||
desiredVersions = options.Frameworks.Select(x => (x.Name, new Version(x.Version))).GroupBy(x => x.Name)
|
||||
.Select(data =>
|
||||
{
|
||||
var versions = (IReadOnlyList<Version>)data.Select(datum => datum.Item2).ToList();
|
||||
if (versions.Count != 1)
|
||||
{
|
||||
var description = string.Join(", ", versions.Select(x => x.ToString()));
|
||||
throw new InvalidDataException(
|
||||
$"Unexpectedly had not-exactly-one version desired for framework {data.Key}: {description}");
|
||||
}
|
||||
|
||||
return (data.Key, versions[0]);
|
||||
})
|
||||
.ToDictionary();
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = new Dictionary<string, Version>
|
||||
{ { options.Framework.Name, new Version(options.Framework.Version) } };
|
||||
desiredVersions = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredVersions = options.IncludedFrameworks.Select(x => (x.Name, new Version(x.Version)))
|
||||
.GroupBy(x => x.Name)
|
||||
.Select(data =>
|
||||
{
|
||||
var versions = (IReadOnlyList<Version>)data.Select(datum => datum.Item2).ToList();
|
||||
if (versions.Count != 1)
|
||||
{
|
||||
var description = string.Join(", ", versions.Select(x => x.ToString()));
|
||||
throw new InvalidDataException(
|
||||
$"Unexpectedly had not-exactly-one version desired for framework {data.Key}: {description}");
|
||||
}
|
||||
|
||||
return (data.Key, versions[0]);
|
||||
})
|
||||
.ToDictionary();
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, IReadOnlyList<RuntimeOnDisk>> availableRuntimes = env
|
||||
.Frameworks.SelectMany(availableFramework =>
|
||||
{
|
||||
var availableVersion = new Version(availableFramework.Version);
|
||||
if (!desiredVersions.TryGetValue(availableFramework.Name, out var desiredVersion))
|
||||
{
|
||||
// we don't desire this framework at any version; skip it
|
||||
return [];
|
||||
}
|
||||
|
||||
if (availableVersion < desiredVersion)
|
||||
{
|
||||
// It's never desired to roll *backward*.
|
||||
return [];
|
||||
}
|
||||
return new List<(string, DotnetEnvironmentFrameworkInfo)>
|
||||
{ (availableFramework.Name, availableFramework) };
|
||||
}).GroupBy(x => x.Item1)
|
||||
.Select(group =>
|
||||
{
|
||||
var grouping = group.Select(x => new RuntimeOnDisk(x.Item2, new Version(x.Item2.Version))).ToList();
|
||||
return (group.Key, (IReadOnlyList<RuntimeOnDisk>)grouping);
|
||||
})
|
||||
.ToDictionary();
|
||||
|
||||
switch (rollForward)
|
||||
{
|
||||
case RollForward.Minor:
|
||||
{
|
||||
return desiredVersions.Select(desired =>
|
||||
{
|
||||
if (!availableRuntimes.TryGetValue(desired.Key, out var available))
|
||||
{
|
||||
return (desired.Key, new DotnetRuntimeSelection());
|
||||
}
|
||||
|
||||
if (ReferenceEquals(available, null))
|
||||
{
|
||||
throw new NullReferenceException("logic error: contents of non-nullable dict can't be null");
|
||||
}
|
||||
|
||||
// If there's a correct major and minor version, take the latest patch.
|
||||
var correctMajorAndMinorVersion =
|
||||
available.Where(data =>
|
||||
data.InstalledVersion.Major == desired.Value.Major &&
|
||||
data.InstalledVersion.Minor == desired.Value.Minor).ToList();
|
||||
if (correctMajorAndMinorVersion.Count > 0)
|
||||
{
|
||||
return (desired.Key, new DotnetRuntimeSelection(correctMajorAndMinorVersion.MaxBy(v => v.InstalledVersion)!.Installed));
|
||||
}
|
||||
|
||||
// Otherwise roll forward to lowest higher minor version
|
||||
var candidate = available.Where(data => data.InstalledVersion.Major == desired.Value.Major)
|
||||
.MinBy(v => (v.InstalledVersion.Minor, -v.InstalledVersion.Build));
|
||||
|
||||
return (desired.Key, candidate == null ? new DotnetRuntimeSelection() : new DotnetRuntimeSelection(candidate.Installed));
|
||||
}).ToDictionary();
|
||||
}
|
||||
case RollForward.Major:
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
case RollForward.LatestPatch:
|
||||
{
|
||||
return desiredVersions.Select(desired =>
|
||||
{
|
||||
var matches = availableRuntimes[desired.Key]
|
||||
.Where(data =>
|
||||
data.InstalledVersion.Minor == desired.Value.Minor &&
|
||||
data.InstalledVersion.Major == desired.Value.Major).MaxBy(data => data.InstalledVersion);
|
||||
return matches == null
|
||||
? (desired.Key, new DotnetRuntimeSelection())
|
||||
: (desired.Key, new DotnetRuntimeSelection(matches.Installed));
|
||||
}).ToDictionary();
|
||||
}
|
||||
case RollForward.LatestMinor:
|
||||
{
|
||||
return desiredVersions.Select(desired =>
|
||||
{
|
||||
var matches = availableRuntimes[desired.Key]
|
||||
.Where(data =>
|
||||
data.InstalledVersion.Major == desired.Value.Major).MaxBy(data => data.InstalledVersion);
|
||||
return matches == null
|
||||
? (desired.Key, new DotnetRuntimeSelection())
|
||||
: (desired.Key, new DotnetRuntimeSelection(matches.Installed));
|
||||
}).ToDictionary();
|
||||
}
|
||||
case RollForward.LatestMajor:
|
||||
{
|
||||
return desiredVersions.Select(desired =>
|
||||
{
|
||||
var match = availableRuntimes[desired.Key].MaxBy(data => data.InstalledVersion);
|
||||
return match == null ? (desired.Key, new DotnetRuntimeSelection()) : (desired.Key, new DotnetRuntimeSelection(match.Installed));
|
||||
}).ToDictionary();
|
||||
}
|
||||
case RollForward.Disable:
|
||||
{
|
||||
return desiredVersions.Select(desired =>
|
||||
{
|
||||
var exactMatch = availableRuntimes[desired.Key]
|
||||
.FirstOrDefault(available => available.InstalledVersion == desired.Value);
|
||||
if (exactMatch != null)
|
||||
{
|
||||
return (desired.Key, new DotnetRuntimeSelection(exactMatch.Installed));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (desired.Key, new DotnetRuntimeSelection());
|
||||
}
|
||||
}
|
||||
).ToDictionary();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonSerializerOptions _options = new() {PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter<RollForward>() }};
|
||||
|
||||
/// <summary>
|
||||
/// Parse a runtimeconfig.json file.
|
||||
/// </summary>
|
||||
/// <param name="contents">Contents of the runtimeconfig.json file to parse.</param>
|
||||
/// <exception cref="NullReferenceException">I think this can't happen, but the docs suggest that deserialization might return null.</exception>
|
||||
public static RuntimeConfig? DeserializeRuntimeConfig(string contents)
|
||||
{
|
||||
return JsonSerializer.Deserialize<RuntimeConfig>(contents, _options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a .NET executable DLL, identify the most appropriate .NET runtime to run it.
|
||||
/// This is pretty half-baked at the moment; test this yourself to make sure it does what you want it to!
|
||||
/// </summary>
|
||||
/// <param name="dllPath">Path to an OutputType=Exe .dll file.</param>
|
||||
/// <param name="dotnet">
|
||||
/// Path to the `dotnet` binary which you would use e.g. in `dotnet exec` to run the DLL specified by
|
||||
/// `dllPath`.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An ordered collection of folder paths. When resolving any particular DLL during the execution of the input
|
||||
/// DLL, search these folders; if a DLL name appears in multiple of these folders, the earliest is correct for that
|
||||
/// DLL.
|
||||
/// </returns>
|
||||
public static IReadOnlyList<string> SelectForDll(string dllPath, string? dotnet = null)
|
||||
{
|
||||
if (!dllPath.EndsWith(".dll", StringComparison.Ordinal))
|
||||
throw new ArgumentException(
|
||||
$"SelectForDll requires the input DLL to have the extension '.dll'; provided: {dllPath}");
|
||||
|
||||
var dll = new FileInfo(dllPath);
|
||||
var dllParentDir = dll.Directory ?? throw new ArgumentException($"dll path {dllPath} had no parent");
|
||||
var name = dll.Name.Substring(0, dll.Name.Length - ".dll".Length);
|
||||
|
||||
var configFilePath = Path.Combine(dllParentDir.FullName, $"{name}.runtimeconfig.json");
|
||||
|
||||
// It appears to be undocumented why this returns a nullable, and the Rider decompiler doesn't suggest there are
|
||||
// any code paths where it can return null?
|
||||
var contents = File.ReadAllText(configFilePath);
|
||||
var runtimeConfig = DeserializeRuntimeConfig(contents) ?? throw new NullReferenceException($"Failed to parse contents of file {configFilePath} as a runtime config");
|
||||
|
||||
var availableRuntimes = dotnet == null
|
||||
? DotnetEnvironmentInfo.Get()
|
||||
: DotnetEnvironmentInfo.GetSpecific(new FileInfo(dotnet));
|
||||
|
||||
var runtimes = SelectRuntime(runtimeConfig.RuntimeOptions, availableRuntimes);
|
||||
|
||||
return runtimes.SelectMany(runtime => runtime.Value.Visit(framework => new[] { $"{framework.Path}/{framework.Version}" },
|
||||
sdk => [sdk.Path],
|
||||
() => []
|
||||
)).Prepend(dllParentDir.FullName).ToList();
|
||||
}
|
||||
|
||||
private record RuntimeOnDisk(
|
||||
DotnetEnvironmentFrameworkInfo Installed,
|
||||
Version InstalledVersion);
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace WoofWare.DotnetRuntimeLocator;
|
||||
|
120
WoofWare.DotnetRuntimeLocator/RuntimeConfigOptions.cs
Normal file
120
WoofWare.DotnetRuntimeLocator/RuntimeConfigOptions.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace WoofWare.DotnetRuntimeLocator;
|
||||
|
||||
/// <summary>
|
||||
/// The type of a "framework" entry in the "runtimeOptions" setting of a runtimeconfig.json file.
|
||||
/// </summary>
|
||||
public record RuntimeConfigFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// For example, "Microsoft.NETCore.App".
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// For example, "9.0.0".
|
||||
/// </summary>
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value of e.g. `--roll-forward` or DOTNET_ROLL_FORWARD.
|
||||
/// </summary>
|
||||
public enum RollForward
|
||||
{
|
||||
/// <summary>
|
||||
/// If the requested version is missing, roll forward to the lowest available minor version higher than requested.
|
||||
/// If the requested version is available, silently use the LatestPatch policy.
|
||||
/// Minor is the default if unspecified.
|
||||
/// </summary>
|
||||
Minor,
|
||||
|
||||
/// <summary>
|
||||
/// If the requested version is missing, roll forward to the lowest available major version higher than requested,
|
||||
/// at "lowest minor version" (the docs are unclear whether this means "lowest *available*", or "0").
|
||||
/// If the requested version is available, silently use the Minor policy.
|
||||
/// </summary>
|
||||
Major,
|
||||
|
||||
/// <summary>
|
||||
/// Roll forward to the highest patch version at exactly the requested major and minor versions.
|
||||
/// </summary>
|
||||
LatestPatch,
|
||||
|
||||
/// <summary>
|
||||
/// Roll forward to the highest minor version, even if the requested minor version is available.
|
||||
/// </summary>
|
||||
LatestMinor,
|
||||
|
||||
/// <summary>
|
||||
/// Roll forward to the highest available major version and highest available minor version at that major version,
|
||||
/// even if the requested version is available.
|
||||
/// </summary>
|
||||
LatestMajor,
|
||||
|
||||
/// <summary>
|
||||
/// Suppress all rolling forward: use only the exact specified version.
|
||||
/// </summary>
|
||||
Disable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The contents of the "runtimeOptions" key in a runtimeconfig.json file.
|
||||
/// </summary>
|
||||
public record RuntimeOptions
|
||||
{
|
||||
/// Target framework moniker, such as "net9.0".
|
||||
[JsonPropertyName("tfm")]
|
||||
public required string Tfm { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The .NET runtime which this executable expects.
|
||||
/// This is optional, because you can instead specify multiple Frameworks, in which case any of the frameworks
|
||||
/// is acceptable (according to Claude; the MS docs are impenetrable as ever).
|
||||
/// </summary>
|
||||
[JsonPropertyName("framework")]
|
||||
public RuntimeConfigFramework? Framework { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Any of these runtimes by itself would be enough to run this executable.
|
||||
/// It's much more normal to see a single `framework` instead of this.
|
||||
/// </summary>
|
||||
[JsonPropertyName("frameworks")]
|
||||
public IReadOnlyList<RuntimeConfigFramework>? Frameworks { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// This is a self-contained executable which has these framework entirely contained next to it.
|
||||
/// </summary>
|
||||
[JsonPropertyName("includedFrameworks")]
|
||||
public IReadOnlyList<RuntimeConfigFramework>? IncludedFrameworks { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// This application advertises that it's fine with running under this roll-forward.
|
||||
/// </summary>
|
||||
[JsonPropertyName("rollForward")]
|
||||
public RollForward? RollForward { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The contents of a runtimeconfig.json file.
|
||||
/// Note that this record doesn't capture everything: for example, "configProperties" might be present in the file,
|
||||
/// but is not represented in this type.
|
||||
/// </summary>
|
||||
public record RuntimeConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The contents of the file.
|
||||
/// </summary>
|
||||
[JsonPropertyName("runtimeOptions")]
|
||||
public required RuntimeOptions RuntimeOptions { get; init; }
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(RuntimeConfig))]
|
||||
internal partial class SourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
@@ -44,4 +44,54 @@ WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.op_Inequality [static met
|
||||
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Path [property]: string
|
||||
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Path [method]: string -> unit
|
||||
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Version [method]: string -> unit
|
||||
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Version [property]: string
|
||||
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Version [property]: string
|
||||
WoofWare.DotnetRuntimeLocator.DotnetRuntime inherit obj
|
||||
WoofWare.DotnetRuntimeLocator.DotnetRuntime.DeserializeRuntimeConfig [static method]: string -> WoofWare.DotnetRuntimeLocator.RuntimeConfig
|
||||
WoofWare.DotnetRuntimeLocator.DotnetRuntime.SelectForDll [static method]: (string, string) -> string System.Collections.Generic.IReadOnlyList
|
||||
WoofWare.DotnetRuntimeLocator.RollForward inherit System.Enum
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.Disable [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Disable
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.LatestMajor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestMajor
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.LatestMinor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestMinor
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.LatestPatch [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestPatch
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.Major [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Major
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.Minor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Minor
|
||||
WoofWare.DotnetRuntimeLocator.RollForward.value__ [field]: int
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeConfig System.IEquatable
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig..ctor [constructor]: unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfig
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.get_RuntimeOptions [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeOptions
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfig, WoofWare.DotnetRuntimeLocator.RuntimeConfig) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfig, WoofWare.DotnetRuntimeLocator.RuntimeConfig) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.RuntimeOptions [property]: WoofWare.DotnetRuntimeLocator.RuntimeOptions
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfig.set_RuntimeOptions [method]: WoofWare.DotnetRuntimeLocator.RuntimeOptions -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.IEquatable
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework..ctor [constructor]: unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.get_Name [method]: unit -> string
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.get_Version [method]: unit -> string
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.Name [property]: string
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework, WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework, WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.set_Name [method]: string -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.set_Version [method]: string -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.Version [property]: string
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeOptions System.IEquatable
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions..ctor [constructor]: unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeOptions
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Framework [property]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Frameworks [property]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Framework [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Frameworks [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_IncludedFrameworks [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_RollForward [method]: unit -> WoofWare.DotnetRuntimeLocator.RollForward System.Nullable
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Tfm [method]: unit -> string
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.IncludedFrameworks [property]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeOptions, WoofWare.DotnetRuntimeLocator.RuntimeOptions) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeOptions, WoofWare.DotnetRuntimeLocator.RuntimeOptions) -> bool
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.RollForward [property]: WoofWare.DotnetRuntimeLocator.RollForward System.Nullable
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Framework [method]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Frameworks [method]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_IncludedFrameworks [method]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_RollForward [method]: WoofWare.DotnetRuntimeLocator.RollForward System.Nullable -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Tfm [method]: string -> unit
|
||||
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Tfm [property]: string
|
21
WoofWare.DotnetRuntimeLocator/Test/Assembly.fs
Normal file
21
WoofWare.DotnetRuntimeLocator/Test/Assembly.fs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace WoofWare.DotnetRuntimeLocator.Test
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Assembly =
|
||||
let getEmbeddedResource (assembly : Assembly) (name : string) : string =
|
||||
let names = assembly.GetManifestResourceNames ()
|
||||
|
||||
let names =
|
||||
names |> Seq.filter (fun s -> s.EndsWith (name, StringComparison.Ordinal))
|
||||
|
||||
use s =
|
||||
names
|
||||
|> Seq.exactlyOne
|
||||
|> assembly.GetManifestResourceStream
|
||||
|> fun s -> new StreamReader (s)
|
||||
|
||||
s.ReadToEnd ()
|
@@ -1,27 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<NuGetAudit>false</NuGetAudit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<NuGetAudit>false</NuGetAudit>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="TestSurface.fs" />
|
||||
<Compile Include="TestDotnetEnvironmentInfo.fs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assembly.fs" />
|
||||
<Compile Include="TestDotnetRuntime.fs" />
|
||||
<Compile Include="TestRuntimeConfigParse.fs"/>
|
||||
<Compile Include="TestSurface.fs"/>
|
||||
<Compile Include="TestDotnetEnvironmentInfo.fs"/>
|
||||
<EmbeddedResource Include="runtimeconfig1.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApiSurface" Version="4.0.40" />
|
||||
<PackageReference Include="FsUnit" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
||||
<PackageReference Include="NUnit" Version="4.1.0"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApiSurface" Version="5.0.1"/>
|
||||
<PackageReference Include="FsUnit" Version="7.1.1"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
||||
<PackageReference Include="NUnit" Version="4.4.0"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.1.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
36
WoofWare.DotnetRuntimeLocator/Test/TestDotnetRuntime.fs
Normal file
36
WoofWare.DotnetRuntimeLocator/Test/TestDotnetRuntime.fs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace WoofWare.DotnetRuntimeLocator.Test
|
||||
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open NUnit.Framework
|
||||
open WoofWare.DotnetRuntimeLocator
|
||||
|
||||
[<TestFixture>]
|
||||
module TestDotnetRuntime =
|
||||
|
||||
let inline shouldBeSome (x : 'a option) : unit =
|
||||
match x with
|
||||
| None -> failwith "option was None"
|
||||
| Some _ -> ()
|
||||
|
||||
let inline shouldBeNone (x : 'a option) : unit =
|
||||
match x with
|
||||
| Some x -> failwith $"expectd None, but option was Some %O{x}"
|
||||
| None -> ()
|
||||
|
||||
[<Test>]
|
||||
let ``Test DotnetRuntime`` () =
|
||||
let assy = Assembly.GetExecutingAssembly ()
|
||||
let selectedRuntime = DotnetRuntime.SelectForDll assy.Location
|
||||
|
||||
let existsDll (name : string) =
|
||||
selectedRuntime
|
||||
|> Seq.tryPick (fun dir ->
|
||||
let attempt = Path.Combine (dir, name)
|
||||
if File.Exists attempt then Some attempt else None
|
||||
)
|
||||
|
||||
existsDll "System.Private.CoreLib.dll" |> shouldBeSome
|
||||
existsDll "System.Text.Json.dll" |> shouldBeSome
|
||||
existsDll "Test.dll" |> shouldBeSome
|
||||
existsDll "blah-de-blah.dll" |> shouldBeNone
|
49
WoofWare.DotnetRuntimeLocator/Test/TestRuntimeConfigParse.fs
Normal file
49
WoofWare.DotnetRuntimeLocator/Test/TestRuntimeConfigParse.fs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace WoofWare.DotnetRuntimeLocator.Test
|
||||
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open System.Text.Json
|
||||
open FsUnitTyped
|
||||
open NUnit.Framework
|
||||
open WoofWare.DotnetRuntimeLocator
|
||||
|
||||
[<TestFixture>]
|
||||
module TestRuntimeConfigParse =
|
||||
|
||||
[<Test>]
|
||||
let ``Can parse our own runtime config`` () =
|
||||
let assy = Assembly.GetExecutingAssembly ()
|
||||
|
||||
let runtimeConfig =
|
||||
Path.Combine (FileInfo(assy.Location).Directory.FullName, $"%s{assy.GetName().Name}.runtimeconfig.json")
|
||||
|> File.ReadAllText
|
||||
|
||||
let actual = JsonSerializer.Deserialize<RuntimeConfig> runtimeConfig
|
||||
|
||||
let expected =
|
||||
RuntimeConfig (
|
||||
RuntimeOptions =
|
||||
RuntimeOptions (
|
||||
Tfm = "net8.0",
|
||||
Framework = RuntimeConfigFramework (Name = "Microsoft.NETCore.App", Version = "8.0.0")
|
||||
)
|
||||
)
|
||||
|
||||
actual |> shouldEqual expected
|
||||
|
||||
[<Test>]
|
||||
let ``Example 1`` () =
|
||||
let content =
|
||||
Assembly.getEmbeddedResource (Assembly.GetExecutingAssembly ()) "runtimeconfig1.json"
|
||||
|
||||
let expected =
|
||||
RuntimeConfig (
|
||||
RuntimeOptions =
|
||||
RuntimeOptions (
|
||||
Tfm = "net8.0",
|
||||
RollForward = RollForward.Major,
|
||||
Framework = RuntimeConfigFramework (Name = "Microsoft.NETCore.App", Version = "8.0.0")
|
||||
)
|
||||
)
|
||||
|
||||
DotnetRuntime.DeserializeRuntimeConfig content |> shouldEqual expected
|
@@ -14,10 +14,11 @@ module TestSurface =
|
||||
let ``Update API surface`` () =
|
||||
ApiSurface.writeAssemblyBaseline assembly
|
||||
|
||||
[<Test>]
|
||||
[<Test ; Explicit "Bug in ApiSurface: https://github.com/G-Research/ApiSurface/pull/111">]
|
||||
let ``Ensure public API is fully documented`` () =
|
||||
DocCoverage.assertFullyDocumented assembly
|
||||
|
||||
[<Test ; Explicit "Not yet published">]
|
||||
let ``Ensure version is monotonic`` () =
|
||||
[<Test>]
|
||||
// https://github.com/nunit/nunit3-vs-adapter/issues/876
|
||||
let ``EnsureVersionIsMonotonic`` () =
|
||||
MonotonicVersion.validate assembly "WoofWare.DotnetRuntimeLocator"
|
||||
|
13
WoofWare.DotnetRuntimeLocator/Test/runtimeconfig1.json
Normal file
13
WoofWare.DotnetRuntimeLocator/Test/runtimeconfig1.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net8.0",
|
||||
"rollForward": "Major",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "8.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
@@ -23,8 +23,10 @@
|
||||
<Compile Include="DotnetEnvironmentFrameworkInfo.cs"/>
|
||||
<Compile Include="DotnetEnvironmentInfo.cs"/>
|
||||
<Compile Include="DotnetEnvironmentSdkInfo.cs"/>
|
||||
<Compile Include="DotnetRuntime.cs" />
|
||||
<Compile Include="InteropStructs.cs"/>
|
||||
<Compile Include="Boilerplate.cs"/>
|
||||
<Compile Include="RuntimeConfigOptions.cs"/>
|
||||
<EmbeddedResource Include="SurfaceBaseline.txt"/>
|
||||
<EmbeddedResource Include="version.json"/>
|
||||
<None Include="..\README.md">
|
||||
|
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"version": "0.1",
|
||||
"publicReleaseRefSpec": ["^refs/heads/main$"],
|
||||
"version": "0.4",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
"pathFilters": [
|
||||
"^Test/",
|
||||
":!Test/",
|
||||
":/WoofWare.DotnetRuntimeLocator",
|
||||
":/Directory.Build.props",
|
||||
":/README.md"
|
||||
]
|
||||
}
|
||||
}
|
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1731890469,
|
||||
"narHash": "sha256-D1FNZ70NmQEwNxpSSdTXCSklBH1z2isPR84J6DQrJGs=",
|
||||
"lastModified": 1759536663,
|
||||
"narHash": "sha256-hhM8SUI6kQMei5TImFdNQy9EDT8g2hAD161DUtbfAy0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5083ec887760adfe12af64830a66807423a859a7",
|
||||
"rev": "27ac93958969b5f3dccd654b402599cf3de633ac",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
12
flake.nix
12
flake.nix
@@ -42,15 +42,18 @@
|
||||
'';
|
||||
};
|
||||
in {
|
||||
packages = {
|
||||
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).hash;
|
||||
packages = let
|
||||
deps = builtins.fromJSON (builtins.readFile ./nix/deps.json);
|
||||
in {
|
||||
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") deps)).hash;
|
||||
default = pkgs.buildDotnetModule {
|
||||
inherit pname version dotnet-sdk dotnet-runtime;
|
||||
name = "WoofWare.Myriad.Plugins";
|
||||
name = "WoofWare.DotnetRuntimeLocator";
|
||||
src = ./.;
|
||||
projectFile = "./WoofWare.DotnetRuntimeLocator/WoofWare.DotnetRuntimeLocator.csproj";
|
||||
testProjectFile = "./WoofWare.DotnetRuntimeLocator/Test/Test.fsproj";
|
||||
nugetDeps = ./nix/deps.nix; # `nix build .#default.passthru.fetch-deps && ./result nix/deps.nix`
|
||||
disabledTests = ["WoofWare.DotnetRuntimeLocator.Test.TestSurface.EnsureVersionIsMonotonic"];
|
||||
nugetDeps = ./nix/deps.json; # `nix build .#default.fetch-deps && ./result nix/deps.json`
|
||||
doCheck = true;
|
||||
};
|
||||
};
|
||||
@@ -60,6 +63,7 @@
|
||||
pkgs.alejandra
|
||||
pkgs.nodePackages.markdown-link-check
|
||||
pkgs.shellcheck
|
||||
pkgs.xmlstarlet
|
||||
];
|
||||
};
|
||||
});
|
||||
|
172
nix/deps.json
Normal file
172
nix/deps.json
Normal file
@@ -0,0 +1,172 @@
|
||||
[
|
||||
{
|
||||
"pname": "ApiSurface",
|
||||
"version": "5.0.1",
|
||||
"hash": "sha256-0GMXEMFgWbbE2OGxW+6h4zGgQHg+IZy1aI13Dn97xSU="
|
||||
},
|
||||
{
|
||||
"pname": "fantomas",
|
||||
"version": "6.3.8",
|
||||
"hash": "sha256-dNbs5+gzjjMw2fl0ZRB9qzj9d+rz1o3Wi/qUvBDoz2E="
|
||||
},
|
||||
{
|
||||
"pname": "FSharp.Core",
|
||||
"version": "8.0.403",
|
||||
"hash": "sha256-3XSQp7JUOU5T6gvSQXNfBF4t4gaX4J4xushH+cfM9mE="
|
||||
},
|
||||
{
|
||||
"pname": "FsUnit",
|
||||
"version": "7.1.1",
|
||||
"hash": "sha256-UMCEGKxQ4ytjmPuVpiNaAPbi3RQH9gqa61JJIUS/6hg="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.ApplicationInsights",
|
||||
"version": "2.23.0",
|
||||
"hash": "sha256-5sf3bg7CZZjHseK+F3foOchEhmVeioePxMZVvS6Rjb0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeCoverage",
|
||||
"version": "17.14.1",
|
||||
"hash": "sha256-f8QytG8GvRoP47rO2KEmnDLxIpyesaq26TFjDdW40Gs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NET.Test.Sdk",
|
||||
"version": "17.14.1",
|
||||
"hash": "sha256-mZUzDFvFp7x1nKrcnRd0hhbNu5g8EQYt8SKnRgdhT/A="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.Telemetry",
|
||||
"version": "1.7.3",
|
||||
"hash": "sha256-Z6WsY2FCUbNnT5HJd7IOrfOvqknVXp6PWzTVeb0idVg="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.TrxReport.Abstractions",
|
||||
"version": "1.7.3",
|
||||
"hash": "sha256-PTee04FHyTHx/gF5NLckXuVje807G51MzkPrZ1gkgCw="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.VSTestBridge",
|
||||
"version": "1.7.3",
|
||||
"hash": "sha256-8d+wZmucfSO7PsviHjVxYB4q6NcjgxvnCUpLePq35sM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Platform",
|
||||
"version": "1.7.3",
|
||||
"hash": "sha256-cavX11P5o9rooqC3ZHw5h002OKRg2ZNR/VaRwpNTQYA="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Platform.MSBuild",
|
||||
"version": "1.7.3",
|
||||
"hash": "sha256-cREl529UQ/c5atT8KimMgrgNdy6MrAd0sBGT8sXRRPM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.AdapterUtilities",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-Vr+3Tad/h/nk7f/5HMExn3HvCGFCarehFAzJSfCBaOc="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.ObjectModel",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-6S0fjfj8vA+h6dJVNwLi6oZhYDO/I/6hBZaq2VTW+Uk="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.ObjectModel",
|
||||
"version": "17.14.1",
|
||||
"hash": "sha256-QMf6O+w0IT+16Mrzo7wn+N20f3L1/mDhs/qjmEo1rYs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.TestHost",
|
||||
"version": "17.14.1",
|
||||
"hash": "sha256-1cxHWcvHRD7orQ3EEEPPxVGEkTpxom1/zoICC9SInJs="
|
||||
},
|
||||
{
|
||||
"pname": "Nerdbank.GitVersioning",
|
||||
"version": "3.8.38-alpha",
|
||||
"hash": "sha256-gPMrVbjOZxXoofczF/pn6eVkLhjVSJIyQrLO2oljrDc="
|
||||
},
|
||||
{
|
||||
"pname": "Newtonsoft.Json",
|
||||
"version": "13.0.3",
|
||||
"hash": "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Common",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-jDOwt3veI1GSG8CfBnf2+dJxD3E/Nmlc+vHtD4J76Ms="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Configuration",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-1PN9s6fhCw3wd2260U6hQ4vG3jIvcG8GIn1oQgxMXA0="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Frameworks",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-3ViM3R1ucQMEL2hQYsivT86kI6veMQK2xDsiAcFcVQk="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Packaging",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-Yafbnxs3maj55bJ1oKQiZ0QkntFUzXdhorL94YEUOhY="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Protocol",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-uLDKfs+QN1MdnuQtTES8qfNzzsmYKM6XB9pwJc4G+eo="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Versioning",
|
||||
"version": "6.14.0",
|
||||
"hash": "sha256-DqdOJgsphKxSvqB8b60zNPCaiLfbiu3WnUJ/90feLrY="
|
||||
},
|
||||
{
|
||||
"pname": "NUnit",
|
||||
"version": "4.4.0",
|
||||
"hash": "sha256-5geF5QOF+X/WkuCEgkPVKH4AdKx4U0olpU07S8+G3nU="
|
||||
},
|
||||
{
|
||||
"pname": "NUnit3TestAdapter",
|
||||
"version": "5.1.0",
|
||||
"hash": "sha256-5z470sFjV67wGHaw8KfmSloIAYe81Dokp0f8I6zXsDc="
|
||||
},
|
||||
{
|
||||
"pname": "System.Collections.Immutable",
|
||||
"version": "8.0.0",
|
||||
"hash": "sha256-F7OVjKNwpqbUh8lTidbqJWYi476nsq9n+6k0+QVRo3w="
|
||||
},
|
||||
{
|
||||
"pname": "System.Diagnostics.DiagnosticSource",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-6mW3N6FvcdNH/pB58pl+pFSCGWgyaP4hfVtC/SMWDV4="
|
||||
},
|
||||
{
|
||||
"pname": "System.Formats.Asn1",
|
||||
"version": "6.0.0",
|
||||
"hash": "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8="
|
||||
},
|
||||
{
|
||||
"pname": "System.Reflection.Metadata",
|
||||
"version": "1.6.0",
|
||||
"hash": "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E="
|
||||
},
|
||||
{
|
||||
"pname": "System.Reflection.Metadata",
|
||||
"version": "8.0.0",
|
||||
"hash": "sha256-dQGC30JauIDWNWXMrSNOJncVa1umR1sijazYwUDdSIE="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.Cryptography.Pkcs",
|
||||
"version": "6.0.4",
|
||||
"hash": "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.Cryptography.ProtectedData",
|
||||
"version": "4.4.0",
|
||||
"hash": "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE="
|
||||
},
|
||||
{
|
||||
"pname": "System.Text.Json",
|
||||
"version": "8.0.5",
|
||||
"hash": "sha256-yKxo54w5odWT6nPruUVsaX53oPRe+gKzGvLnnxtwP68="
|
||||
}
|
||||
]
|
224
nix/deps.nix
224
nix/deps.nix
@@ -1,224 +0,0 @@
|
||||
# This file was automatically generated by passthru.fetch-deps.
|
||||
# Please dont edit it manually, your changes might get overwritten!
|
||||
{fetchNuGet}: [
|
||||
(fetchNuGet {
|
||||
pname = "ApiSurface";
|
||||
version = "4.0.40";
|
||||
hash = "sha256-oO9V30T9+QN/DKSTqS6jRH7ES/NkV5n5jZnaWM0CP7E=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "fantomas";
|
||||
version = "6.3.8";
|
||||
hash = "sha256-dNbs5+gzjjMw2fl0ZRB9qzj9d+rz1o3Wi/qUvBDoz2E=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "8.0.401";
|
||||
hash = "sha256-+tp7/Ssr5lb55ZBTOjTuuH0rLCGfhe5Yjq4jvU5KML0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FsUnit";
|
||||
version = "6.0.0";
|
||||
hash = "sha256-q87WQf6MqGhzvaQ7WkkUlCdoE94DY0CD5PaXEj64A6M=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Ref";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-BxvIeZIaBdC0wyDQqKW0E5axSRSrtQk3oEPsT287014=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-jM/HzLumZvI939DrNb8LHnEr/in1Lws0j/FAfdXSzbk=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-2eUqoTcqTU3ebv53IV6yvN9EhkOqnyBRd2tz74HuSsE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-6mY2uBhvKCpEFJLYX9+f1mpYrWdN69i+14DPjO4U8eo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-ljEkMgkgfEeqzRnmTubjSK2dzkph0cSQ7+2J986F7HI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.CodeCoverage";
|
||||
version = "17.10.0";
|
||||
hash = "sha256-yQFwqVChRtIRpbtkJr92JH2i+O7xn91NGbYgnKs8G2g=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NET.Test.Sdk";
|
||||
version = "17.10.0";
|
||||
hash = "sha256-rkHIqB2mquNXF89XBTFpUL2z5msjTBsOcyjSBCh36I0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-yrtPCYD8skaWnfIoaUdQ1dns0YrypxDocskS2WGxF6g=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-maNzxJQ5oCd86VI4ROzl4RqOV1RNXn3qWjrAfBjr2Y0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-cBcfv7tnZa2xO5T5VOx3/7EvJ5u4/C4dFnV1Jj6VFPU=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-05wMp5+etiV/vgktqGo8+4XB7FNYxwCUKpJsW48tgvQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Ref";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-IcpSbsSHgYBbNVvbcXfmRRM9bdx3pogLncO4RuXEab0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-jPUhSrzqnH1GNi/c7dSnZSQhFNVGdmlAQkDLdXVWBBc=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-Gf3e0EdBEgq8GcZttTHbKGupFlDyB80nhYpBN0X9Kro=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-IGArFhlq3UzZY93lJ+WrB+zmuu/2o8lVwT7MJKpz6DE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
||||
version = "6.0.35";
|
||||
hash = "sha256-EtFBg8yBNhAEQlL97oVGiu05rPMSKLd0wE44zTBT7FI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Platforms";
|
||||
version = "2.0.0";
|
||||
hash = "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||
version = "17.10.0";
|
||||
hash = "sha256-3YjVGK2zEObksBGYg8b/CqoJgLQ1jUv4GCWNjDhLRh4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.TestPlatform.TestHost";
|
||||
version = "17.10.0";
|
||||
hash = "sha256-+yzP3FY6WoOosSpYnB7duZLhOPUZMQYy8zJ1d3Q4hK4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Nerdbank.GitVersioning";
|
||||
version = "3.6.133";
|
||||
hash = "sha256-AEnBQaGGPMBmZJjZrdWARq/jY4SluuPIsKBbvfNEvLE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Newtonsoft.Json";
|
||||
version = "13.0.1";
|
||||
hash = "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Newtonsoft.Json";
|
||||
version = "13.0.3";
|
||||
hash = "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Common";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-cM3Q7srAykk6KA/FThZkDjs+MIIjiUJSXZjRSqPNP1o=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Configuration";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-H/qaaKbyp3oo/w2dBvaXEhG5+Tgcp75tJR1brpSdCqs=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Frameworks";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-E88PUsK5J0b9c0sN+xNZU+X1MOCfJaIvByr1H4ZHLUM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Packaging";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-RK18XuOdmXPXhmBLRGjw00QsLiKuYawqjDQUlzcbRaM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Protocol";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-TPWWce4FhI3VaDhAR6mUYydFA6AjrPtcJSMmPQEmu0I=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Versioning";
|
||||
version = "6.10.0";
|
||||
hash = "sha256-r8w4/bin+ZQK6AzkuFXhWbteQlzRFY++S1yDTrq0KfQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit";
|
||||
version = "4.1.0";
|
||||
hash = "sha256-srzj0lf2ReKw41TnigZwf8rqKKNzGRRVrgN3hR/vRjo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit3TestAdapter";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-ER3ogl0L5FYyc6pVVPY1ch+AQxG/WgFcnWECnYQJPes=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Formats.Asn1";
|
||||
version = "6.0.0";
|
||||
hash = "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.IO.Abstractions";
|
||||
version = "4.2.13";
|
||||
hash = "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.IO.FileSystem.AccessControl";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Reflection.Metadata";
|
||||
version = "1.6.0";
|
||||
hash = "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.AccessControl";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.Pkcs";
|
||||
version = "6.0.4";
|
||||
hash = "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.ProtectedData";
|
||||
version = "4.4.0";
|
||||
hash = "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Principal.Windows";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Text.Encodings.Web";
|
||||
version = "7.0.0";
|
||||
hash = "sha256-tF8qt9GZh/nPy0mEnj6nKLG4Lldpoi/D8xM5lv2CoYQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Text.Json";
|
||||
version = "7.0.3";
|
||||
hash = "sha256-aSJZ17MjqaZNQkprfxm/09LaCoFtpdWmqU9BTROzWX4=";
|
||||
})
|
||||
]
|
Reference in New Issue
Block a user