mirror of
				https://github.com/actions/setup-dotnet.git
				synced 2025-10-31 19:33:45 +00:00 
			
		
		
		
	Refactor and update unit-tests (#418)
* Update unit-tests and dotnet-install scripts
This commit is contained in:
		
							parent
							
								
									fc8786b149
								
							
						
					
					
						commit
						0f534f5829
					
				
							
								
								
									
										2
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							| @ -24,7 +24,7 @@ jobs: | ||||
|       - name: Clear toolcache | ||||
|         shell: pwsh | ||||
|         run: __tests__/clear-toolcache.ps1 ${{ runner.os }} | ||||
|       - name: Setup dotnet 2.2.402 and 3.1.404 | ||||
|       - name: Setup dotnet 2.2.402, 3.1.404 and 3.0.x | ||||
|         uses: ./ | ||||
|         with: | ||||
|           dotnet-version: | | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`authutil tests Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -15,7 +15,7 @@ exports[`authutil tests Existing config not in repo root, sets up a partial NuGe | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -30,7 +30,7 @@ exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org, | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -45,7 +45,7 @@ exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a p | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -63,7 +63,7 @@ exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet. | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -81,7 +81,7 @@ exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.conf | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -96,7 +96,7 @@ exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -111,7 +111,7 @@ exports[`authutil tests Existing config w/ only GPR source, sets up a partial Nu | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -130,7 +130,7 @@ exports[`authutil tests Existing config w/ two GPR sources, sets up a partial Nu | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests No existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests no existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -148,7 +148,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests No existing config, sets up a full NuGet.config with URL and token for other source 1`] = ` | ||||
| exports[`authutil tests no existing config, sets up a full NuGet.config with URL and token for other source 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
| @ -166,7 +166,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL | ||||
| </configuration>" | ||||
| `; | ||||
| 
 | ||||
| exports[`authutil tests No existing config, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| exports[`authutil tests no existing config, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = ` | ||||
| "<?xml version=\\"1.0\\"?> | ||||
| <configuration> | ||||
|   <config> | ||||
|  | ||||
| @ -91,9 +91,9 @@ describe('authutil tests', () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = ''; | ||||
|   }); | ||||
| 
 | ||||
|   it('No existing config, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|   it('no existing config, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -104,10 +104,10 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('No existing config, auth token environment variable not provided, throws', async () => { | ||||
|   it('no existing config, auth token environment variable not provided, throws', async () => { | ||||
|     let thrown = false; | ||||
|     try { | ||||
|       await auth.configAuthentication( | ||||
|       auth.configAuthentication( | ||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|         '', | ||||
|         fakeSourcesDirForTesting | ||||
| @ -118,10 +118,10 @@ describe('authutil tests', () => { | ||||
|     expect(thrown).toBe(true); | ||||
|   }); | ||||
| 
 | ||||
|   it('No existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => { | ||||
|   it('no existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     process.env['INPUT_OWNER'] = 'otherorg'; | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/otherorg/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -132,7 +132,7 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => { | ||||
|   it('existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
| @ -141,7 +141,7 @@ describe('authutil tests', () => { | ||||
|     fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig); | ||||
|     let thrown = false; | ||||
|     try { | ||||
|       await auth.configAuthentication( | ||||
|       auth.configAuthentication( | ||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|         '', | ||||
|         fakeSourcesDirForTesting | ||||
| @ -152,14 +152,14 @@ describe('authutil tests', () => { | ||||
|     expect(thrown).toBe(true); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|   it('existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -170,14 +170,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|   it('existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -188,14 +188,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -206,14 +206,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -224,14 +224,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -242,7 +242,7 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ spaces in key, throws for now', async () => { | ||||
|   it('existing config w/ spaces in key, throws for now', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
| @ -251,7 +251,7 @@ describe('authutil tests', () => { | ||||
|     fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig); | ||||
|     let thrown = false; | ||||
|     try { | ||||
|       await auth.configAuthentication( | ||||
|       auth.configAuthentication( | ||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|         '', | ||||
|         fakeSourcesDirForTesting | ||||
| @ -262,7 +262,7 @@ describe('authutil tests', () => { | ||||
|     expect(thrown).toBe(true); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigDirectory: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
| @ -274,7 +274,7 @@ describe('authutil tests', () => { | ||||
|     ); | ||||
|     fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true}); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||
|       'subfolder/nuget.config', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -285,14 +285,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -303,14 +303,14 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|   it('existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     const inputNuGetConfigPath: string = path.join( | ||||
|       fakeSourcesDirForTesting, | ||||
|       'nuget.config' | ||||
|     ); | ||||
|     fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig); | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
| @ -321,9 +321,9 @@ describe('authutil tests', () => { | ||||
|     ).toMatchSnapshot(); | ||||
|   }); | ||||
| 
 | ||||
|   it('No existing config, sets up a full NuGet.config with URL and token for other source', async () => { | ||||
|   it('no existing config, sets up a full NuGet.config with URL and token for other source', async () => { | ||||
|     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||
|     await auth.configAuthentication( | ||||
|     auth.configAuthentication( | ||||
|       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||
|       '', | ||||
|       fakeSourcesDirForTesting | ||||
|  | ||||
| @ -1,21 +1,45 @@ | ||||
| import cscFile from '../.github/csc.json'; | ||||
| describe('csc tests', () => { | ||||
|   it('Valid regular expression', async () => { | ||||
|     const regex = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; | ||||
|   test('regular expression in csc.json is valid', async () => { | ||||
|     const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; | ||||
|     const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0]; | ||||
| 
 | ||||
|     console.log(regex); | ||||
|     const re = new RegExp(regex); | ||||
|     const regex = new RegExp(regexPattern); | ||||
| 
 | ||||
|     // Ideally we would verify that this
 | ||||
|     const stringsToMatch = [ | ||||
|       'Program.cs(10,79): error CS1002: ; expected [/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj]', | ||||
|       "S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs(33,7): error CS1003: Syntax error, ',' expected [S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop]" | ||||
|     ]; | ||||
|     // Expected results are calculated according to the csc matcher located in csc.json file
 | ||||
|     const expectedResults = [ | ||||
|       { | ||||
|         file: 'Program.cs', | ||||
|         line: '10', | ||||
|         severity: 'error', | ||||
|         code: 'CS1002', | ||||
|         message: '; expected', | ||||
|         fromPath: | ||||
|           '/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj' | ||||
|       }, | ||||
|       { | ||||
|         file: 'S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs', | ||||
|         line: '33', | ||||
|         severity: 'error', | ||||
|         code: 'CS1003', | ||||
|         message: "Syntax error, ',' expected", | ||||
|         fromPath: | ||||
|           'S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop' | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     stringsToMatch.forEach(string => { | ||||
|       const matchStr = string.match(re); | ||||
|       console.log(matchStr); | ||||
|       expect(matchStr).toEqual(expect.anything()); | ||||
|     stringsToMatch.map((string, index) => { | ||||
|       const matchedResultsArray = string.match(regex); | ||||
|       for (const propName in expectedResults[index]) { | ||||
|         const propertyIndex = regexResultsMap[propName]; | ||||
|         const expectedPropValue = expectedResults[index][propName]; | ||||
|         const matchedPropValue = matchedResultsArray![propertyIndex]; | ||||
|         expect(matchedPropValue).toEqual(expectedPropValue); | ||||
|       } | ||||
|     }); | ||||
|   }, 10000); | ||||
| }); | ||||
|  | ||||
							
								
								
									
										52
									
								
								__tests__/installation-scripts.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								__tests__/installation-scripts.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| import path from 'path'; | ||||
| import fs from 'fs'; | ||||
| import * as hc from '@actions/http-client'; | ||||
| 
 | ||||
| describe('Dotnet installation scripts tests', () => { | ||||
|   it('Uses an up to date bash download script', async () => { | ||||
|     const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||||
|       allowRetries: true, | ||||
|       maxRetries: 3 | ||||
|     }); | ||||
|     const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||||
|       'https://dot.net/v1/dotnet-install.sh' | ||||
|     ); | ||||
|     expect(response.message.statusCode).toBe(200); | ||||
|     const upToDateContents: string = await response.readBody(); | ||||
|     const currentContents: string = fs | ||||
|       .readFileSync( | ||||
|         path.join(__dirname, '..', 'externals', 'install-dotnet.sh') | ||||
|       ) | ||||
|       .toString(); | ||||
|     expect(normalizeFileContents(currentContents)).toBe( | ||||
|       normalizeFileContents(upToDateContents) | ||||
|     ); | ||||
|   }, 30000); | ||||
| 
 | ||||
|   it('Uses an up to date powershell download script', async () => { | ||||
|     const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||||
|       allowRetries: true, | ||||
|       maxRetries: 3 | ||||
|     }); | ||||
|     const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||||
|       'https://dot.net/v1/dotnet-install.ps1' | ||||
|     ); | ||||
|     expect(response.message.statusCode).toBe(200); | ||||
|     const upToDateContents: string = await response.readBody(); | ||||
|     const currentContents: string = fs | ||||
|       .readFileSync( | ||||
|         path.join(__dirname, '..', 'externals', 'install-dotnet.ps1') | ||||
|       ) | ||||
|       .toString(); | ||||
|     expect(normalizeFileContents(currentContents)).toBe( | ||||
|       normalizeFileContents(upToDateContents) | ||||
|     ); | ||||
|   }, 30000); | ||||
| }); | ||||
| 
 | ||||
| function normalizeFileContents(contents: string): string { | ||||
|   return contents | ||||
|     .trim() | ||||
|     .replace(new RegExp('\r\n', 'g'), '\n') | ||||
|     .replace(new RegExp('\r', 'g'), '\n'); | ||||
| } | ||||
| @ -1,298 +1,399 @@ | ||||
| import * as io from '@actions/io'; | ||||
| import * as os from 'os'; | ||||
| import fs from 'fs'; | ||||
| import path from 'path'; | ||||
| import each from 'jest-each'; | ||||
| import * as hc from '@actions/http-client'; | ||||
| import semver from 'semver'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as installer from '../src/installer'; | ||||
| import {QualityOptions} from '../src/setup-dotnet'; | ||||
| 
 | ||||
| import {IS_WINDOWS} from '../src/utils'; | ||||
| import {IS_LINUX} from '../src/utils'; | ||||
| import {QualityOptions} from '../src/setup-dotnet'; | ||||
| 
 | ||||
| let toolDir: string; | ||||
| describe('installer tests', () => { | ||||
|   const env = process.env; | ||||
| 
 | ||||
| if (IS_WINDOWS) { | ||||
|   toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); | ||||
| } else if (IS_LINUX) { | ||||
|   toolDir = '/usr/share/dotnet'; | ||||
| } else { | ||||
|   toolDir = path.join(process.env['HOME'] + '', '.dotnet'); | ||||
| } | ||||
| const tempDir = path.join(__dirname, 'runner', 'temp'); | ||||
|   beforeEach(() => { | ||||
|     jest.resetModules(); | ||||
|     process.env = {...env}; | ||||
|   }); | ||||
| 
 | ||||
| process.env['RUNNER_TOOL_CACHE'] = toolDir; | ||||
| process.env['RUNNER_TEMP'] = tempDir; | ||||
|   describe('DotnetCoreInstaller tests', () => { | ||||
|     const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|     const warningSpy = jest.spyOn(core, 'warning'); | ||||
|     const whichSpy = jest.spyOn(io, 'which'); | ||||
|     const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); | ||||
| 
 | ||||
| describe('DotnetCoreInstaller tests', () => { | ||||
|   beforeAll(async () => { | ||||
|     process.env.RUNNER_TOOL_CACHE = toolDir; | ||||
|     process.env.DOTNET_INSTALL_DIR = toolDir; | ||||
|     process.env.RUNNER_TEMP = tempDir; | ||||
|     process.env.DOTNET_ROOT = ''; | ||||
|     try { | ||||
|       await io.rmRF(`${toolDir}/*`); | ||||
|       await io.rmRF(`${tempDir}/*`); | ||||
|     } catch (err) { | ||||
|       console.log( | ||||
|         `Failed to remove test directories, check the error message:${os.EOL}`, | ||||
|         err.message | ||||
|       ); | ||||
|     } | ||||
|   }, 30000); | ||||
|     describe('installDotnet() tests', () => { | ||||
|       whichSpy.mockImplementation(() => Promise.resolve('PathToShell')); | ||||
| 
 | ||||
|   afterEach(async () => { | ||||
|     try { | ||||
|       await io.rmRF(`${toolDir}/*`); | ||||
|       await io.rmRF(`${tempDir}/*`); | ||||
|     } catch (err) { | ||||
|       console.log( | ||||
|         `Failed to remove test directories, check the error message:${os.EOL}`, | ||||
|         err.message | ||||
|       ); | ||||
|     } | ||||
|   }, 30000); | ||||
|       it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => { | ||||
|         const inputVersion = '3.1.100'; | ||||
|         const inputQuality = '' as QualityOptions; | ||||
|         const errorMessage = 'fictitious error message!'; | ||||
|         getExecOutputSpy.mockImplementation(() => { | ||||
|           return Promise.resolve({ | ||||
|             exitCode: 1, | ||||
|             stdout: '', | ||||
|             stderr: errorMessage | ||||
|           }); | ||||
|         }); | ||||
|         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|           inputVersion, | ||||
|           inputQuality | ||||
|         ); | ||||
|         await expect(dotnetInstaller.installDotnet()).rejects.toThrow( | ||||
|           `Failed to install dotnet, exit code: 1. ${errorMessage}` | ||||
|         ); | ||||
|       }); | ||||
| 
 | ||||
|   it('Aquires multiple versions of dotnet', async () => { | ||||
|     const versions = ['2.2.207', '3.1.120']; | ||||
|       it('should return version of .NET SDK after installation complete', async () => { | ||||
|         const inputVersion = '3.1.100'; | ||||
|         const inputQuality = '' as QualityOptions; | ||||
|         getExecOutputSpy.mockImplementation(() => { | ||||
|           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|         }); | ||||
|         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|     for (const version of versions) { | ||||
|       await getDotnet(version); | ||||
|     } | ||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '2.2.207'))).toBe(true); | ||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.120'))).toBe(true); | ||||
|         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|           inputVersion, | ||||
|           inputQuality | ||||
|         ); | ||||
|         const installedVersion = await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|     if (IS_WINDOWS) { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); | ||||
|     } else { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); | ||||
|     } | ||||
|         expect(installedVersion).toBe(inputVersion); | ||||
|       }); | ||||
| 
 | ||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); | ||||
|     expect(process.env.PATH).toBeDefined(); | ||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); | ||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); | ||||
|   }, 600000); | ||||
|       it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => { | ||||
|         const inputVersion = '6.0.300'; | ||||
|         const inputQuality = '' as QualityOptions; | ||||
| 
 | ||||
|   it('Acquires version of dotnet if no matching version is installed', async () => { | ||||
|     await getDotnet('3.1.201'); | ||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); | ||||
|     if (IS_WINDOWS) { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); | ||||
|     } else { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); | ||||
|     } | ||||
|         getExecOutputSpy.mockImplementation(() => { | ||||
|           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|         }); | ||||
|         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); | ||||
|     expect(process.env.PATH).toBeDefined(); | ||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); | ||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); | ||||
|   }, 600000); //This needs some time to download on "slower" internet connections
 | ||||
|         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|           inputVersion, | ||||
|           inputQuality | ||||
|         ); | ||||
| 
 | ||||
|   it('Acquires generic version of dotnet if no matching version is installed', async () => { | ||||
|     await getDotnet('3.1'); | ||||
|     const directory = fs | ||||
|       .readdirSync(path.join(toolDir, 'sdk')) | ||||
|       .filter(fn => fn.startsWith('3.1.')); | ||||
|     expect(directory.length > 0).toBe(true); | ||||
|     if (IS_WINDOWS) { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); | ||||
|     } else { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); | ||||
|     } | ||||
|         await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); | ||||
|     expect(process.env.PATH).toBeDefined(); | ||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); | ||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); | ||||
|   }, 600000); //This needs some time to download on "slower" internet connections
 | ||||
|         const scriptArguments = ( | ||||
|           getExecOutputSpy.mock.calls[0][1] as string[] | ||||
|         ).join(' '); | ||||
|         const expectedArgument = IS_WINDOWS | ||||
|           ? `-Version ${inputVersion}` | ||||
|           : `--version ${inputVersion}`; | ||||
| 
 | ||||
|   it('Returns string with installed SDK version', async () => { | ||||
|     const version = '3.1.120'; | ||||
|         expect(scriptArguments).toContain(expectedArgument); | ||||
|       }); | ||||
| 
 | ||||
|     const installedVersion = await getDotnet(version); | ||||
|       it(`should warn if the 'quality' input is set and the supplied version is in A.B.C syntax`, async () => { | ||||
|         const inputVersion = '6.0.300'; | ||||
|         const inputQuality = 'ga' as QualityOptions; | ||||
| 
 | ||||
|     expect(installedVersion).toBe('3.1.120'); | ||||
|   }, 600000); | ||||
|         getExecOutputSpy.mockImplementation(() => { | ||||
|           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|         }); | ||||
|         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|   it('Throws if no location contains correct dotnet version', async () => { | ||||
|     await expect(async () => { | ||||
|       await getDotnet('1000.0.0'); | ||||
|     }).rejects.toThrow(); | ||||
|   }, 30000); | ||||
|         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|           inputVersion, | ||||
|           inputQuality | ||||
|         ); | ||||
| 
 | ||||
|   it('Uses an up to date bash download script', async () => { | ||||
|     const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||||
|       allowRetries: true, | ||||
|       maxRetries: 3 | ||||
|     }); | ||||
|     const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||||
|       'https://dot.net/v1/dotnet-install.sh' | ||||
|     ); | ||||
|     expect(response.message.statusCode).toBe(200); | ||||
|     const upToDateContents: string = await response.readBody(); | ||||
|     const currentContents: string = fs | ||||
|       .readFileSync( | ||||
|         path.join(__dirname, '..', 'externals', 'install-dotnet.sh') | ||||
|       ) | ||||
|       .toString(); | ||||
|     expect(normalizeFileContents(currentContents)).toBe( | ||||
|       normalizeFileContents(upToDateContents) | ||||
|     ); | ||||
|   }, 30000); | ||||
|         await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|   it('Uses an up to date powershell download script', async () => { | ||||
|     const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||||
|       allowRetries: true, | ||||
|       maxRetries: 3 | ||||
|     }); | ||||
|     const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||||
|       'https://dot.net/v1/dotnet-install.ps1' | ||||
|     ); | ||||
|     expect(response.message.statusCode).toBe(200); | ||||
|     const upToDateContents: string = await response.readBody(); | ||||
|     const currentContents: string = fs | ||||
|       .readFileSync( | ||||
|         path.join(__dirname, '..', 'externals', 'install-dotnet.ps1') | ||||
|       ) | ||||
|       .toString(); | ||||
|     expect(normalizeFileContents(currentContents)).toBe( | ||||
|       normalizeFileContents(upToDateContents) | ||||
|     ); | ||||
|   }, 30000); | ||||
| }); | ||||
|         expect(warningSpy).toHaveBeenCalledWith( | ||||
|           `'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.` | ||||
|         ); | ||||
|       }); | ||||
| 
 | ||||
| describe('DotnetVersionResolver tests', () => { | ||||
|   each([ | ||||
|     '3.1', | ||||
|     '3.x', | ||||
|     '3.1.x', | ||||
|     '3.1.*', | ||||
|     '3.1.X', | ||||
|     '3.1.2', | ||||
|     '3.1.0-preview1' | ||||
|   ]).test( | ||||
|     "if valid version: '%s' is supplied, it should return version object with some value", | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|       ); | ||||
|       const versionObject = await dotnetVersionResolver.createDotNetVersion(); | ||||
|       it(`should warn if the 'quality' input is set and version isn't in A.B.C syntax but major tag is lower then 6`, async () => { | ||||
|         const inputVersion = '3.1'; | ||||
|         const inputQuality = 'ga' as QualityOptions; | ||||
| 
 | ||||
|       expect(!!versionObject.value).toBe(true); | ||||
|     } | ||||
|   ); | ||||
|         getExecOutputSpy.mockImplementation(() => { | ||||
|           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|         }); | ||||
|         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|   each([ | ||||
|     '.', | ||||
|     '..', | ||||
|     ' . ', | ||||
|     '. ', | ||||
|     ' .', | ||||
|     ' . . ', | ||||
|     ' .. ', | ||||
|     ' .  ', | ||||
|     '-1.-1', | ||||
|     '-1', | ||||
|     '-1.-1.-1', | ||||
|     '..3', | ||||
|     '1..3', | ||||
|     '1..', | ||||
|     '.2.3', | ||||
|     '.2.x', | ||||
|     '*.', | ||||
|     '1.2.', | ||||
|     '1.2.-abc', | ||||
|     'a.b', | ||||
|     'a.b.c', | ||||
|     'a.b.c-preview', | ||||
|     ' 0 . 1 . 2 ', | ||||
|     'invalid' | ||||
|   ]).test( | ||||
|     "if invalid version: '%s' is supplied, it should throw", | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|           inputVersion, | ||||
|           inputQuality | ||||
|         ); | ||||
| 
 | ||||
|         await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|         expect(warningSpy).toHaveBeenCalledWith( | ||||
|           `'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.` | ||||
|         ); | ||||
|       }); | ||||
| 
 | ||||
|       each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||
|         `should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`, | ||||
|         async inputVersion => { | ||||
|           const inputQuality = 'ga' as QualityOptions; | ||||
|           const exitCode = 0; | ||||
|           getExecOutputSpy.mockImplementation(() => { | ||||
|             return Promise.resolve({ | ||||
|               exitCode: exitCode, | ||||
|               stdout: '', | ||||
|               stderr: '' | ||||
|             }); | ||||
|           }); | ||||
|           maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|             inputVersion, | ||||
|             inputQuality | ||||
|           ); | ||||
| 
 | ||||
|           await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|           const scriptArguments = ( | ||||
|             getExecOutputSpy.mock.calls[0][1] as string[] | ||||
|           ).join(' '); | ||||
|           const expectedArgument = IS_WINDOWS | ||||
|             ? `-Quality ${inputQuality}` | ||||
|             : `--quality ${inputQuality}`; | ||||
| 
 | ||||
|           expect(scriptArguments).toContain(expectedArgument); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       await expect( | ||||
|         async () => await dotnetVersionResolver.createDotNetVersion() | ||||
|       ).rejects.toThrow(); | ||||
|     } | ||||
|   ); | ||||
|       each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||
|         `should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`, | ||||
|         async inputVersion => { | ||||
|           const inputQuality = '' as QualityOptions; | ||||
|           const exitCode = 0; | ||||
|           getExecOutputSpy.mockImplementation(() => { | ||||
|             return Promise.resolve({ | ||||
|               exitCode: exitCode, | ||||
|               stdout: '', | ||||
|               stderr: '' | ||||
|             }); | ||||
|           }); | ||||
|           maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|   each(['3.1', '3.1.x', '3.1.*', '3.1.X']).test( | ||||
|     "if version: '%s' that can be resolved to 'channel' option is supplied, it should set type to 'channel' in version object", | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|             inputVersion, | ||||
|             inputQuality | ||||
|           ); | ||||
| 
 | ||||
|           await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|           const scriptArguments = ( | ||||
|             getExecOutputSpy.mock.calls[0][1] as string[] | ||||
|           ).join(' '); | ||||
|           const expectedArgument = IS_WINDOWS | ||||
|             ? `-Channel 6.0` | ||||
|             : `--channel 6.0`; | ||||
| 
 | ||||
|           expect(scriptArguments).toContain(expectedArgument); | ||||
|         } | ||||
|       ); | ||||
|       const versionObject = await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|       expect(versionObject.type.toLowerCase().includes('channel')).toBe(true); | ||||
|     } | ||||
|   ); | ||||
| 
 | ||||
|   each(['6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||
|     "if version: '%s' that can be resolved to 'channel' option is supplied and its major tag is >= 6, it should set type to 'channel' and qualityFlag to 'true' in version object", | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|       ); | ||||
|       const versionObject = await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|       expect(versionObject.type.toLowerCase().includes('channel')).toBe(true); | ||||
|       expect(versionObject.qualityFlag).toBe(true); | ||||
|     } | ||||
|   ); | ||||
| 
 | ||||
|   each(['3.1.2', '3.1.0-preview1']).test( | ||||
|     "if version: '%s' that can be resolved to 'version' option is supplied, it should set quality flag to 'false' and type to 'version' in version object", | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|       ); | ||||
|       const versionObject = await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|       expect(versionObject.type.toLowerCase().includes('version')).toBe(true); | ||||
|       expect(versionObject.qualityFlag).toBe(false); | ||||
|     } | ||||
|   ); | ||||
| 
 | ||||
|   each(['3.1.2', '3.1']).test( | ||||
|     'it should create proper line arguments for powershell/bash installation scripts', | ||||
|     async version => { | ||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|         version | ||||
|       ); | ||||
|       const versionObject = await dotnetVersionResolver.createDotNetVersion(); | ||||
|       const windowsRegEx = new RegExp(/^-[VC]/); | ||||
|       const nonWindowsRegEx = new RegExp(/^--[vc]/); | ||||
| 
 | ||||
|       if (IS_WINDOWS) { | ||||
|         expect(windowsRegEx.test(versionObject.type)).toBe(true); | ||||
|         expect(nonWindowsRegEx.test(versionObject.type)).toBe(false); | ||||
|       } else { | ||||
|         expect(nonWindowsRegEx.test(versionObject.type)).toBe(true); | ||||
|         expect(windowsRegEx.test(versionObject.type)).toBe(false); | ||||
|         it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => { | ||||
|           process.env['https_proxy'] = 'https://proxy.com'; | ||||
|           const inputVersion = '6.0.100'; | ||||
|           const inputQuality = '' as QualityOptions; | ||||
| 
 | ||||
|           getExecOutputSpy.mockImplementation(() => { | ||||
|             return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|           }); | ||||
|           maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|             inputVersion, | ||||
|             inputQuality | ||||
|           ); | ||||
| 
 | ||||
|           await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|           const scriptArguments = ( | ||||
|             getExecOutputSpy.mock.calls[0][1] as string[] | ||||
|           ).join(' '); | ||||
| 
 | ||||
|           expect(scriptArguments).toContain( | ||||
|             `-ProxyAddress ${process.env['https_proxy']}` | ||||
|           ); | ||||
|         }); | ||||
| 
 | ||||
|         it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => { | ||||
|           process.env['no_proxy'] = 'first.url,second.url'; | ||||
|           const inputVersion = '6.0.100'; | ||||
|           const inputQuality = '' as QualityOptions; | ||||
| 
 | ||||
|           getExecOutputSpy.mockImplementation(() => { | ||||
|             return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||
|           }); | ||||
|           maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||
| 
 | ||||
|           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|             inputVersion, | ||||
|             inputQuality | ||||
|           ); | ||||
| 
 | ||||
|           await dotnetInstaller.installDotnet(); | ||||
| 
 | ||||
|           const scriptArguments = ( | ||||
|             getExecOutputSpy.mock.calls[0][1] as string[] | ||||
|           ).join(' '); | ||||
| 
 | ||||
|           expect(scriptArguments).toContain( | ||||
|             `-ProxyBypassList ${process.env['no_proxy']}` | ||||
|           ); | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   ); | ||||
|     }); | ||||
| 
 | ||||
|     describe('addToPath() tests', () => { | ||||
|       it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => { | ||||
|         process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir'; | ||||
|         installer.DotnetCoreInstaller.addToPath(); | ||||
|         const dotnet_root = process.env['DOTNET_ROOT']; | ||||
|         expect(dotnet_root).toBe(process.env['DOTNET_INSTALL_DIR']); | ||||
|       }); | ||||
| 
 | ||||
|       it(`should export value from DOTNET_INSTALL_DIR env.var to the PATH`, async () => { | ||||
|         process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir'; | ||||
|         installer.DotnetCoreInstaller.addToPath(); | ||||
|         const path = process.env['PATH']; | ||||
|         expect(path).toContain(process.env['DOTNET_INSTALL_DIR']); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('DotnetVersionResolver tests', () => { | ||||
|     describe('createDotNetVersion() tests', () => { | ||||
|       each([ | ||||
|         '3.1', | ||||
|         '3.x', | ||||
|         '3.1.x', | ||||
|         '3.1.*', | ||||
|         '3.1.X', | ||||
|         '3.1.2', | ||||
|         '3.1.0-preview1' | ||||
|       ]).test( | ||||
|         'if valid version is supplied (%s), it should return version object with some value', | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
|           const versionObject = | ||||
|             await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|           expect(!!versionObject.value).toBe(true); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       each([ | ||||
|         '.', | ||||
|         '..', | ||||
|         ' . ', | ||||
|         '. ', | ||||
|         ' .', | ||||
|         ' . . ', | ||||
|         ' .. ', | ||||
|         ' .  ', | ||||
|         '-1.-1', | ||||
|         '-1', | ||||
|         '-1.-1.-1', | ||||
|         '..3', | ||||
|         '1..3', | ||||
|         '1..', | ||||
|         '.2.3', | ||||
|         '.2.x', | ||||
|         '*.', | ||||
|         '1.2.', | ||||
|         '1.2.-abc', | ||||
|         'a.b', | ||||
|         'a.b.c', | ||||
|         'a.b.c-preview', | ||||
|         ' 0 . 1 . 2 ', | ||||
|         'invalid' | ||||
|       ]).test( | ||||
|         'if invalid version is supplied (%s), it should throw', | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
| 
 | ||||
|           await expect( | ||||
|             async () => await dotnetVersionResolver.createDotNetVersion() | ||||
|           ).rejects.toThrow(); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       each(['3', '3.1', '3.1.x', '3.1.*', '3.1.X']).test( | ||||
|         "if version that can be resolved to 'channel' option is supplied (%s), it should set type to 'channel' in version object", | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
|           const versionObject = | ||||
|             await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|           expect(versionObject.type.toLowerCase().includes('channel')).toBe( | ||||
|             true | ||||
|           ); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       each(['6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||
|         "if version that can be resolved to 'channel' option is supplied and its major tag is >= 6 (%s), it should set type to 'channel' and qualityFlag to 'true' in version object", | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
|           const versionObject = | ||||
|             await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|           expect(versionObject.type.toLowerCase().includes('channel')).toBe( | ||||
|             true | ||||
|           ); | ||||
|           expect(versionObject.qualityFlag).toBe(true); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       each(['3.1.2', '3.1.0-preview1']).test( | ||||
|         "if version that can be resolved to 'version' option is supplied (%s), it should set quality flag to 'false' and type to 'version' in version object", | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
|           const versionObject = | ||||
|             await dotnetVersionResolver.createDotNetVersion(); | ||||
| 
 | ||||
|           expect(versionObject.type.toLowerCase().includes('version')).toBe( | ||||
|             true | ||||
|           ); | ||||
|           expect(versionObject.qualityFlag).toBe(false); | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       each(['3.1.2', '3.1']).test( | ||||
|         'it should create proper line arguments for powershell/bash installation scripts', | ||||
|         async version => { | ||||
|           const dotnetVersionResolver = new installer.DotnetVersionResolver( | ||||
|             version | ||||
|           ); | ||||
|           const versionObject = | ||||
|             await dotnetVersionResolver.createDotNetVersion(); | ||||
|           const windowsRegEx = new RegExp(/^-(Version|Channel)/); | ||||
|           const nonWindowsRegEx = new RegExp(/^--(version|channel)/); | ||||
| 
 | ||||
|           if (IS_WINDOWS) { | ||||
|             expect(windowsRegEx.test(versionObject.type)).toBe(true); | ||||
|             expect(nonWindowsRegEx.test(versionObject.type)).toBe(false); | ||||
|           } else { | ||||
|             expect(nonWindowsRegEx.test(versionObject.type)).toBe(true); | ||||
|             expect(windowsRegEx.test(versionObject.type)).toBe(false); | ||||
|           } | ||||
|         } | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| function normalizeFileContents(contents: string): string { | ||||
|   return contents | ||||
|     .trim() | ||||
|     .replace(new RegExp('\r\n', 'g'), '\n') | ||||
|     .replace(new RegExp('\r', 'g'), '\n'); | ||||
| } | ||||
| 
 | ||||
| async function getDotnet(version: string, quality = ''): Promise<string> { | ||||
|   const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||
|     version, | ||||
|     quality as QualityOptions | ||||
|   ); | ||||
|   const installedVersion = await dotnetInstaller.installDotnet(); | ||||
|   installer.DotnetCoreInstaller.addToPath(); | ||||
|   return installedVersion; | ||||
| } | ||||
|  | ||||
| @ -1,114 +1,146 @@ | ||||
| import * as io from '@actions/io'; | ||||
| import * as core from '@actions/core'; | ||||
| import fs from 'fs'; | ||||
| import os from 'os'; | ||||
| import path from 'path'; | ||||
| import semver from 'semver'; | ||||
| import * as auth from '../src/authutil'; | ||||
| 
 | ||||
| import * as setup from '../src/setup-dotnet'; | ||||
| import {IS_WINDOWS} from '../src/utils'; | ||||
| import {IS_LINUX} from '../src/utils'; | ||||
| 
 | ||||
| let toolDir: string; | ||||
| 
 | ||||
| if (IS_WINDOWS) { | ||||
|   toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); | ||||
| } else if (IS_LINUX) { | ||||
|   toolDir = '/usr/share/dotnet'; | ||||
| } else { | ||||
|   toolDir = path.join(process.env['HOME'] + '', '.dotnet'); | ||||
| } | ||||
| 
 | ||||
| function createGlobalJsonPath(dotnetVersion: string) { | ||||
|   const globalJsonPath = path.join(process.cwd(), 'global.json'); | ||||
|   const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "${dotnetVersion}"${os.EOL}}${os.EOL}}`; | ||||
|   if (!fs.existsSync(globalJsonPath)) { | ||||
|     fs.writeFileSync(globalJsonPath, jsonContents); | ||||
|   } | ||||
|   return globalJsonPath; | ||||
| } | ||||
| 
 | ||||
| const tempDir = path.join(__dirname, 'runner', 'temp2'); | ||||
| import {DotnetCoreInstaller} from '../src/installer'; | ||||
| 
 | ||||
| describe('setup-dotnet tests', () => { | ||||
|   const getInputSpy = jest.spyOn(core, 'getInput'); | ||||
|   const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput'); | ||||
|   const setOutputSpy = jest.spyOn(core, 'setOutput'); | ||||
| 
 | ||||
|   const inputs = {} as any; | ||||
| 
 | ||||
|   beforeAll(async () => { | ||||
|     process.env.RUNNER_TOOL_CACHE = toolDir; | ||||
|     process.env.DOTNET_INSTALL_DIR = toolDir; | ||||
|     process.env.RUNNER_TEMP = tempDir; | ||||
|     try { | ||||
|       await io.rmRF(`${toolDir}/*`); | ||||
|       await io.rmRF(`${tempDir}/*`); | ||||
|     } catch (err) { | ||||
|       console.log(err.message); | ||||
|       console.log('Failed to remove test directories'); | ||||
|     } | ||||
|   }, 30000); | ||||
|   const getInputSpy = jest.spyOn(core, 'getInput'); | ||||
|   const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput'); | ||||
|   const setFailedSpy = jest.spyOn(core, 'setFailed'); | ||||
|   const debugSpy = jest.spyOn(core, 'debug'); | ||||
|   const infoSpy = jest.spyOn(core, 'info'); | ||||
|   const setOutputSpy = jest.spyOn(core, 'setOutput'); | ||||
| 
 | ||||
|   afterEach(async () => { | ||||
|     try { | ||||
|       await io.rmRF(path.join(process.cwd(), 'global.json')); | ||||
|       await io.rmRF(`${toolDir}/*`); | ||||
|       await io.rmRF(`${tempDir}/*`); | ||||
|     } catch (err) { | ||||
|       console.log(err.message); | ||||
|       console.log('Failed to remove test directories'); | ||||
|     } | ||||
|   }, 30000); | ||||
|   const existsSyncSpy = jest.spyOn(fs, 'existsSync'); | ||||
| 
 | ||||
|   it('Acquires version of dotnet from global.json if no matching version is installed', async () => { | ||||
|     createGlobalJsonPath('3.1.201'); | ||||
|     await setup.run(); | ||||
|   const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); | ||||
| 
 | ||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); | ||||
|     if (IS_WINDOWS) { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); | ||||
|     } else { | ||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); | ||||
|     } | ||||
|   }, 400000); | ||||
|   const installDotnetSpy = jest.spyOn( | ||||
|     DotnetCoreInstaller.prototype, | ||||
|     'installDotnet' | ||||
|   ); | ||||
|   const addToPathSpy = jest.spyOn(DotnetCoreInstaller, 'addToPath'); | ||||
| 
 | ||||
|   it("Sets output with the latest installed by action version if global.json file isn't specified", async () => { | ||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||||
|   const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication'); | ||||
| 
 | ||||
|     getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||||
|   describe('run() tests', () => { | ||||
|     beforeEach(() => { | ||||
|       getMultilineInputSpy.mockImplementation(input => inputs[input as string]); | ||||
|       getInputSpy.mockImplementation(input => inputs[input as string]); | ||||
|     }); | ||||
| 
 | ||||
|     await setup.run(); | ||||
|     afterEach(() => { | ||||
|       jest.clearAllMocks(); | ||||
|       jest.resetAllMocks(); | ||||
|     }); | ||||
| 
 | ||||
|     expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '6.0.401'); | ||||
|   }, 400000); | ||||
|     it('should fail the action if global-json-file input is present, but the file does not exist in the file system', async () => { | ||||
|       inputs['global-json-file'] = 'fictitious.json'; | ||||
|       inputs['dotnet-version'] = []; | ||||
| 
 | ||||
|   it("Sets output with the version specified in global.json, if it's present", async () => { | ||||
|     createGlobalJsonPath('3.0.103'); | ||||
|       const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`; | ||||
| 
 | ||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||||
|     inputs['global-json-file'] = './global.json'; | ||||
|       await setup.run(); | ||||
|       expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage); | ||||
|     }); | ||||
| 
 | ||||
|     getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||||
|     test(`if 'dotnet-version' and 'global-json-file' inputs aren't present, should log into debug output, try to find global.json in the repo root, fail and log message into info output`, async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = []; | ||||
| 
 | ||||
|     getInputSpy.mockImplementation(input => inputs[input]); | ||||
|       maxSatisfyingSpy.mockImplementation(() => null); | ||||
|       setOutputSpy.mockImplementation(() => {}); | ||||
| 
 | ||||
|     await setup.run(); | ||||
|       const expectedDebugMessage = | ||||
|         'No version found, trying to find version from global.json'; | ||||
|       const expectedInfoMessage = `global.json wasn't found in the root directory. No .NET version will be installed.`; | ||||
| 
 | ||||
|     expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '3.0.103'); | ||||
|   }, 400000); | ||||
|       await setup.run(); | ||||
| 
 | ||||
|   it('Sets output with the version specified in global.json with absolute path', async () => { | ||||
|     const globalJsonPath = createGlobalJsonPath('3.0.103'); | ||||
|       expect(debugSpy).toHaveBeenCalledWith(expectedDebugMessage); | ||||
|       expect(existsSyncSpy).toHaveBeenCalled(); | ||||
|       expect(infoSpy).toHaveBeenCalledWith(expectedInfoMessage); | ||||
|     }); | ||||
| 
 | ||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||||
|     inputs['global-json-file'] = globalJsonPath; | ||||
|     it('should fail the action if quality is supplied but its value is not supported', async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = ['6.0']; | ||||
|       inputs['dotnet-quality'] = 'fictitiousQuality'; | ||||
| 
 | ||||
|     getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||||
|       const expectedErrorMessage = `${inputs['dotnet-quality']} is not a supported value for 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`; | ||||
| 
 | ||||
|     getInputSpy.mockImplementation(input => inputs[input]); | ||||
|       await setup.run(); | ||||
|       expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage); | ||||
|     }); | ||||
| 
 | ||||
|     await setup.run(); | ||||
|     it('should call installDotnet() multiple times if dotnet-version multiline input is provided', async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = ['6.0', '7.0']; | ||||
|       inputs['dotnet-quality'] = ''; | ||||
| 
 | ||||
|     expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '3.0.103'); | ||||
|   }, 400000); | ||||
|       installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||||
| 
 | ||||
|       await setup.run(); | ||||
|       expect(installDotnetSpy).toHaveBeenCalledTimes(2); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call addToPath() after installation complete', async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = ['6.0', '7.0']; | ||||
|       inputs['dotnet-quality'] = ''; | ||||
| 
 | ||||
|       installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||||
|       addToPathSpy.mockImplementation(() => {}); | ||||
| 
 | ||||
|       await setup.run(); | ||||
|       expect(addToPathSpy).toHaveBeenCalledTimes(1); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call auth.configAuthentication() if source-url input is provided', async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = []; | ||||
|       inputs['dotnet-quality'] = ''; | ||||
|       inputs['source-url'] = 'fictitious.source.url'; | ||||
| 
 | ||||
|       configAuthenticationSpy.mockImplementation(() => {}); | ||||
| 
 | ||||
|       await setup.run(); | ||||
|       expect(configAuthenticationSpy).toHaveBeenCalledWith( | ||||
|         inputs['source-url'], | ||||
|         undefined | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call auth.configAuthentication() with proper parameters if source-url and config-file inputs are provided', async () => { | ||||
|       inputs['global-json-file'] = ''; | ||||
|       inputs['dotnet-version'] = []; | ||||
|       inputs['dotnet-quality'] = ''; | ||||
|       inputs['source-url'] = 'fictitious.source.url'; | ||||
|       inputs['config-file'] = 'fictitious.path'; | ||||
| 
 | ||||
|       configAuthenticationSpy.mockImplementation(() => {}); | ||||
|       setOutputSpy.mockImplementation(() => {}); | ||||
| 
 | ||||
|       await setup.run(); | ||||
|       expect(configAuthenticationSpy).toHaveBeenCalledWith( | ||||
|         inputs['source-url'], | ||||
|         inputs['config-file'] | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call setOutput() after installation complete', async () => { | ||||
|       inputs['dotnet-version'] = ['6.0.300']; | ||||
| 
 | ||||
|       installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||||
|       addToPathSpy.mockImplementation(() => {}); | ||||
| 
 | ||||
|       await setup.run(); | ||||
|       expect(setOutputSpy).toHaveBeenCalledTimes(1); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
							
								
								
									
										459
									
								
								externals/install-dotnet.ps1
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										459
									
								
								externals/install-dotnet.ps1
									
									
									
									
										vendored
									
									
								
							| @ -9,6 +9,12 @@ | ||||
| .DESCRIPTION | ||||
|     Installs dotnet cli. If dotnet installation already exists in the given directory | ||||
|     it will update it only if the requested version differs from the one already installed. | ||||
| 
 | ||||
|     Note that the intended use of this script is for Continuous Integration (CI) scenarios, where: | ||||
|     - The SDK needs to be installed without user interaction and without admin rights. | ||||
|     - The SDK installation doesn't need to persist across multiple CI runs. | ||||
|     To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer. | ||||
| 
 | ||||
| .PARAMETER Channel | ||||
|     Default: LTS | ||||
|     Download from the Channel specified. Possible values: | ||||
| @ -164,6 +170,12 @@ function Say-Verbose($str) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function Measure-Action($name, $block) { | ||||
|     $time = Measure-Command $block | ||||
|     $totalSeconds = $time.TotalSeconds | ||||
|     Say-Verbose "⏱ Action '$name' took $totalSeconds seconds" | ||||
| } | ||||
| 
 | ||||
| function Say-Invocation($Invocation) { | ||||
|     $command = $Invocation.MyCommand; | ||||
|     $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") | ||||
| @ -1104,10 +1116,10 @@ function Prepare-Install-Directory { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | ||||
| Say "- The SDK needs to be installed without user interaction and without admin rights." | ||||
| Say "- The SDK installation doesn't need to persist across multiple CI runs." | ||||
| Say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.`r`n" | ||||
| Say-Verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | ||||
| Say-Verbose "- The SDK needs to be installed without user interaction and without admin rights." | ||||
| Say-Verbose "- The SDK installation doesn't need to persist across multiple CI runs." | ||||
| Say-Verbose "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.`r`n" | ||||
| 
 | ||||
| if ($SharedRuntime -and (-not $Runtime)) { | ||||
|     $Runtime = "dotnet" | ||||
| @ -1115,14 +1127,16 @@ if ($SharedRuntime -and (-not $Runtime)) { | ||||
| 
 | ||||
| $OverrideNonVersionedFiles = !$SkipNonVersionedFiles | ||||
| 
 | ||||
| $CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture | ||||
| $NormalizedQuality = Get-NormalizedQuality $Quality | ||||
| Say-Verbose "Normalized quality: '$NormalizedQuality'" | ||||
| $NormalizedChannel = Get-NormalizedChannel $Channel | ||||
| Say-Verbose "Normalized channel: '$NormalizedChannel'" | ||||
| $NormalizedProduct = Get-NormalizedProduct $Runtime | ||||
| Say-Verbose "Normalized product: '$NormalizedProduct'" | ||||
| $FeedCredential = ValidateFeedCredential $FeedCredential | ||||
| Measure-Action "Product discovery" { | ||||
|     $script:CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture | ||||
|     $script:NormalizedQuality = Get-NormalizedQuality $Quality | ||||
|     Say-Verbose "Normalized quality: '$NormalizedQuality'" | ||||
|     $script:NormalizedChannel = Get-NormalizedChannel $Channel | ||||
|     Say-Verbose "Normalized channel: '$NormalizedChannel'" | ||||
|     $script:NormalizedProduct = Get-NormalizedProduct $Runtime | ||||
|     Say-Verbose "Normalized product: '$NormalizedProduct'" | ||||
|     $script:FeedCredential = ValidateFeedCredential $FeedCredential | ||||
| } | ||||
| 
 | ||||
| $InstallRoot = Resolve-Installation-Path $InstallDir | ||||
| Say-Verbose "InstallRoot: $InstallRoot" | ||||
| @ -1200,7 +1214,7 @@ if ($DryRun) { | ||||
|     return | ||||
| } | ||||
| 
 | ||||
| Prepare-Install-Directory | ||||
| Measure-Action "Installation directory preparation" { Prepare-Install-Directory } | ||||
| 
 | ||||
| $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) | ||||
| Say-Verbose "Zip path: $ZipPath" | ||||
| @ -1214,7 +1228,7 @@ foreach ($link in $DownloadLinks) | ||||
|     Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)" | ||||
| 
 | ||||
|     try { | ||||
|         DownloadFile -Source $link.downloadLink -OutPath $ZipPath | ||||
|         Measure-Action "Package download" { DownloadFile -Source $link.downloadLink -OutPath $ZipPath } | ||||
|         Say-Verbose "Download succeeded." | ||||
|         $DownloadSucceeded = $true | ||||
|         $DownloadedLink = $link | ||||
| @ -1251,7 +1265,7 @@ if (-not $DownloadSucceeded) { | ||||
| } | ||||
| 
 | ||||
| Say "Extracting the archive." | ||||
| Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot | ||||
| Measure-Action "Package extraction" { Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot } | ||||
| 
 | ||||
| #  Check if the SDK version is installed; if not, fail the installation. | ||||
| $isAssetInstalled = $false | ||||
| @ -1277,225 +1291,224 @@ if (!$isAssetInstalled) { | ||||
| 
 | ||||
| SafeRemoveFile -Path $ZipPath | ||||
| 
 | ||||
| Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot | ||||
| Measure-Action "Setting up shell environment" { Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot } | ||||
| 
 | ||||
| Say "Note that the script does not resolve dependencies during installation." | ||||
| Say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install/windows#dependencies" | ||||
| Say "Installed version is $($DownloadedLink.effectiveVersion)" | ||||
| Say "Installation finished" | ||||
| 
 | ||||
| # SIG # Begin signature block | ||||
| # MIInzgYJKoZIhvcNAQcCoIInvzCCJ7sCAQExDzANBglghkgBZQMEAgEFADB5Bgor | ||||
| # MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor | ||||
| # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG | ||||
| # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB7pzZ0nuEMd30h | ||||
| # n1EcAYUQN+1clltqaLf9611TDrw/laCCDYUwggYDMIID66ADAgECAhMzAAACzfNk | ||||
| # v/jUTF1RAAAAAALNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | ||||
| # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBhfTi3SRn7+vyy | ||||
| # uCXKPjhiawegWZ493EcaOEycbgkZcKCCDXYwggX0MIID3KADAgECAhMzAAACy7d1 | ||||
| # OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | ||||
| # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy | ||||
| # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p | ||||
| # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAyWhcNMjMwNTExMjA0NjAyWjB0MQsw | ||||
| # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw | ||||
| # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u | ||||
| # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy | ||||
| # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | ||||
| # AQDrIzsY62MmKrzergm7Ucnu+DuSHdgzRZVCIGi9CalFrhwtiK+3FIDzlOYbs/zz | ||||
| # HwuLC3hir55wVgHoaC4liQwQ60wVyR17EZPa4BQ28C5ARlxqftdp3H8RrXWbVyvQ | ||||
| # aUnBQVZM73XDyGV1oUPZGHGWtgdqtBUd60VjnFPICSf8pnFiit6hvSxH5IVWI0iO | ||||
| # nfqdXYoPWUtVUMmVqW1yBX0NtbQlSHIU6hlPvo9/uqKvkjFUFA2LbC9AWQbJmH+1 | ||||
| # uM0l4nDSKfCqccvdI5l3zjEk9yUSUmh1IQhDFn+5SL2JmnCF0jZEZ4f5HE7ykDP+ | ||||
| # oiA3Q+fhKCseg+0aEHi+DRPZAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE | ||||
| # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU0WymH4CP7s1+yQktEwbcLQuR9Zww | ||||
| # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh | ||||
| # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ3MDUzMDAfBgNVHSMEGDAW | ||||
| # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v | ||||
| # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw | ||||
| # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov | ||||
| # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx | ||||
| # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB | ||||
| # AE7LSuuNObCBWYuttxJAgilXJ92GpyV/fTiyXHZ/9LbzXs/MfKnPwRydlmA2ak0r | ||||
| # GWLDFh89zAWHFI8t9JLwpd/VRoVE3+WyzTIskdbBnHbf1yjo/+0tpHlnroFJdcDS | ||||
| # MIsH+T7z3ClY+6WnjSTetpg1Y/pLOLXZpZjYeXQiFwo9G5lzUcSd8YVQNPQAGICl | ||||
| # 2JRSaCNlzAdIFCF5PNKoXbJtEqDcPZ8oDrM9KdO7TqUE5VqeBe6DggY1sZYnQD+/ | ||||
| # LWlz5D0wCriNgGQ/TWWexMwwnEqlIwfkIcNFxo0QND/6Ya9DTAUykk2SKGSPt0kL | ||||
| # tHxNEn2GJvcNtfohVY/b0tuyF05eXE3cdtYZbeGoU1xQixPZAlTdtLmeFNly82uB | ||||
| # VbybAZ4Ut18F//UrugVQ9UUdK1uYmc+2SdRQQCccKwXGOuYgZ1ULW2u5PyfWxzo4 | ||||
| # BR++53OB/tZXQpz4OkgBZeqs9YaYLFfKRlQHVtmQghFHzB5v/WFonxDVlvPxy2go | ||||
| # a0u9Z+ZlIpvooZRvm6OtXxdAjMBcWBAsnBRr/Oj5s356EDdf2l/sLwLFYE61t+ME | ||||
| # iNYdy0pXL6gN3DxTVf2qjJxXFkFfjjTisndudHsguEMk8mEtnvwo9fOSKT6oRHhM | ||||
| # 9sZ4HTg/TTMjUljmN3mBYWAWI5ExdC1inuog0xrKmOWVMIIHejCCBWKgAwIBAgIK | ||||
| # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV | ||||
| # AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA | ||||
| # wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4 | ||||
| # 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5 | ||||
| # RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN | ||||
| # lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X | ||||
| # a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE | ||||
| # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w | ||||
| # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW | ||||
| # MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci | ||||
| # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j | ||||
| # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG | ||||
| # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu | ||||
| # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 | ||||
| # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ | ||||
| # ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf | ||||
| # zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh | ||||
| # 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4 | ||||
| # EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j | ||||
| # 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck | ||||
| # 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd | ||||
| # jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N | ||||
| # mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1 | ||||
| # pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB | ||||
| # fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To | ||||
| # /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq | ||||
| # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x | ||||
| # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv | ||||
| # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 | ||||
| # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG | ||||
| # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG | ||||
| # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg | ||||
| # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC | ||||
| # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 | ||||
| # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr | ||||
| # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg | ||||
| # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy | ||||
| # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 | ||||
| # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh | ||||
| # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k | ||||
| # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB | ||||
| # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn | ||||
| # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 | ||||
| # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w | ||||
| # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o | ||||
| # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD | ||||
| # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa | ||||
| # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny | ||||
| # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG | ||||
| # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t | ||||
| # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV | ||||
| # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 | ||||
| # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG | ||||
| # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl | ||||
| # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb | ||||
| # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l | ||||
| # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 | ||||
| # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 | ||||
| # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 | ||||
| # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam | ||||
| # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa | ||||
| # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah | ||||
| # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA | ||||
| # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt | ||||
| # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr | ||||
| # /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw | ||||
| # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN | ||||
| # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp | ||||
| # Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB | ||||
| # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO | ||||
| # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFmuaTXYQ37AFvsEol24fdW+ | ||||
| # nRqHcc1fr+VQVdqhXc/vMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A | ||||
| # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB | ||||
| # BQAEggEAjY5XW5Ly7TJ1OTbeIR98xU+2dmtw7L71ws+ICnQCGhj2xJDUK+5yrTfO | ||||
| # 8C98l/P4ynFi33Dl8z2YElqUCuqEXbiCzz06lIL4NuibC5DV/X80ZmICR/NYd2v1 | ||||
| # ww7IH+7dpsHAowBBindCYpVwQ3Ea3kDWgsjPAinAysFFushSOnNWFvrF6vi2smrs | ||||
| # smbrAAhEhSfLd1Pxxdw73hQ0YjM/D3F3opaybMQ0blpHhOaqtbiyYzvk0doIzBEc | ||||
| # trSH4NDIc3yLNj5VbjSczpexE+hyQNY4xCtwco4bVtXhONUihv08AIKR8+sIaI7A | ||||
| # mM/SWrrwGYSSSxydKqDei7biKG4jDqGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC | ||||
| # FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq | ||||
| # hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl | ||||
| # AwQCAQUABCB6Hzt2gUb/WZK8fvVnOocriE4rYr6mscZi3gZnBCpiigIGZBr2iMZU | ||||
| # GBMyMDIzMDMzMTE1MjEwNi41MTZaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV | ||||
| # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE | ||||
| # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl | ||||
| # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO | ||||
| # OjA4NDItNEJFNi1DMjlBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT | ||||
| # ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAGybkADf26plJIAAQAAAbIwDQYJ | ||||
| # KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x | ||||
| # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv | ||||
| # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIw | ||||
| # OTIwMjAyMjAxWhcNMjMxMjE0MjAyMjAxWjCB0jELMAkGA1UEBhMCVVMxEzARBgNV | ||||
| # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv | ||||
| # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm | ||||
| # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw | ||||
| # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE | ||||
| # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD | ||||
| # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG | ||||
| # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la | ||||
| # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc | ||||
| # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D | ||||
| # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ | ||||
| # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk | ||||
| # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 | ||||
| # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd | ||||
| # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL | ||||
| # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd | ||||
| # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 | ||||
| # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS | ||||
| # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI | ||||
| # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL | ||||
| # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD | ||||
| # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv | ||||
| # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf | ||||
| # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 | ||||
| # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf | ||||
| # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF | ||||
| # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h | ||||
| # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA | ||||
| # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn | ||||
| # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 | ||||
| # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b | ||||
| # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ | ||||
| # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy | ||||
| # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp | ||||
| # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi | ||||
| # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb | ||||
| # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS | ||||
| # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL | ||||
| # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX | ||||
| # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4x | ||||
| # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt | ||||
| # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p | ||||
| # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAALN82S/+NRMXVEAAAAA | ||||
| # As0wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw | ||||
| # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINK7 | ||||
| # cJe0KVfbcXchjID30U/cUg7pWAQUa3+n8JuhjLCLMEIGCisGAQQBgjcCAQwxNDAy | ||||
| # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j | ||||
| # b20wDQYJKoZIhvcNAQEBBQAEggEAODLxcflOtjpIXXIhbYyQ0wFeBx0NrmoMU/Ri | ||||
| # e7CRrAieAbG4iLJzs4DhUov5iuMHY6AAbLWAH54QlSkd4XNp6POsE7lSzN9yjlVw | ||||
| # V/e0XCaYeXIbtd75hGd5P7wAhM4m2ViDI4IRHyQtjysW0U0F6YiqNlFm7Fzo5Si6 | ||||
| # l2XxvuEDSdyJcEN70wHQajx6bKfnI/oMY59iGjDXvDP/6cQV9NI0gPHFTwPKA7vg | ||||
| # PySyVFEG7dQMoEwAWy9GHbcS//RulgUwBhWcrtUP411XLSO6is2VTknwbdglc9HZ | ||||
| # zViuS4C1ujHlPrlMzm8Y5iGVIQCna5w2NU/kGsSK5+dMkovomKGCFykwghclBgor | ||||
| # BgEEAYI3AwMBMYIXFTCCFxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZI | ||||
| # AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE | ||||
| # WQoDATAxMA0GCWCGSAFlAwQCAQUABCDRz6ce9oWlH6+o0BtjmAjtvEMN1hfhIA5v | ||||
| # +wTZHvB4XgIGY2PeyIloGBMyMDIyMTExMDE1MDUxNi43MzRaMASAAgH0oIHYpIHV | ||||
| # MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||
| # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL | ||||
| # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT | ||||
| # HVRoYWxlcyBUU1MgRVNOOkEyNDAtNEI4Mi0xMzBFMSUwIwYDVQQDExxNaWNyb3Nv | ||||
| # ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAG4CNTB | ||||
| # uHngUUkAAQAAAbgwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV | ||||
| # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv | ||||
| # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg | ||||
| # UENBIDIwMTAwHhcNMjIwOTIwMjAyMjE2WhcNMjMxMjE0MjAyMjE2WjCB0jELMAkG | ||||
| # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx | ||||
| # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z | ||||
| # b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg | ||||
| # VFNTIEVTTjpBMjQwLTRCODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt | ||||
| # U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJwb | ||||
| # sfwRHERn5C95QPGn37tJ5vOiY9aWjeIDxpgaXaYGiqsw0G0cvCK3YulrqemEf2Ck | ||||
| # GSdcOJAF++EqhOSqrO13nGcjqw6hFNnsGwKANyzddwnOO0jz1lfBIIu77TbfNvna | ||||
| # WbwSRu0DTGHA7n7PR0MYJ9bC/HopStpbFf606LKcTWnwaUuEdAhx6FAqg1rkgugi | ||||
| # uuaaxKyxRkdjFZLKFXEXL9p01PtwS0fG6vZiRVnEKgeal2TeLvdAIqapBwltPYif | ||||
| # gqnp7Z4VJMcPo0TWmRNVFOcHRNwWHehN9xg6ugIGXPo7hMpWrPgg4moHO2epc0T3 | ||||
| # 6rgm9hlDrl28bG5TakmV7NJ98kbF5lgtlrowT6ecwEVtuLd4a0gzYqhanW7zaFZn | ||||
| # Dft5yMexy59ifETdzpwArj2nJAyIsiq1PY3XPm2mUMLlACksqelHKfWihK/Fehw/ | ||||
| # mziovBVwkkr/G0F19OWgR+MBUKifwpOyQiLAxrqvVnfCY4QjJCZiHIuS15HCQ/TI | ||||
| # t/Qj4x1WvRa1UqjnmpLu4/yBYWZsdvZoq8SXI7iOs7muecAJeEkYlM6iOkMighzE | ||||
| # hjQK9ThPpoAtluXbL7qIHGrfFlHmX/4soc7jj1j8uB31U34gJlB2XphjMaT+E+O9 | ||||
| # SImk/6GRV9Sm8C88Fnmm2VdwMluCNAUzPFjfvHx3AgMBAAGjggFJMIIBRTAdBgNV | ||||
| # HQ4EFgQUxP1HJTeFwzNYo1njfucXuUfQaW4wHwYDVR0jBBgwFoAUn6cVXQBeYl2D | ||||
| # 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv | ||||
| # ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy | ||||
| # MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov | ||||
| # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l | ||||
| # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB | ||||
| # Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD | ||||
| # ggIBAJ9uk8miwpMoKw3D996piEzbegAGxkABHYn2vP2hbqnkS9U97s/6QlyZOhGF | ||||
| # sVudaiLeRZZTsaG5hR0oCuBINZ/lelo5xzHc+mBOpBXpxSaW1hqoxaCLsVH1EBtz | ||||
| # 7in25Hjy+ejuBcilH6EZ0ZtNxmWGIQz8R0AuS0Tj4VgJXHIlXP9dVOiyGo9Velrk | ||||
| # +FGx/BC+iEuCaKd/IsypHPiCUCh52DGc91s2S7ldQx1H4CljOAtanDfbvSejASWL | ||||
| # o/s3w0XMAbDurWNns0XidAF2RnL1PaxoOyz9VYakNGK4F3/uJRZnVgbsCYuwNX1B | ||||
| # mSwM1ZbPSnggNSGTZx/FQ20Jj/ulrK0ryAbvNbNb4kkaS4a767ifCqvUOFLlUT8P | ||||
| # N43hhldxI6yHPMOWItJpEHIZBiTNKblBsYbIrghb1Ym9tfSsLa5ZJDzVZNndRfhU | ||||
| # qJOyXF+CVm9OtVmFDG9kIwM6QAX8Q0if721z4VOzZNvD8ktg1lI+XjXgXDJVs3h4 | ||||
| # 7sMu9GXSYzky+7dtgmc3iRPkda3YVRdmPJtNFN0NLybcssE7vhFCij75eDGQBFq0 | ||||
| # A4KVG6uBdr6UTWwE0VKHxBz2BpGvn7BCs+5yxnF+HV6CUickDqqPi/II7Zssd9Eb | ||||
| # P9uzj4luldXDAPrWGtdGq+wK0odlGNVuCMxsL3hn8+KiO9UiMIIHcTCCBVmgAwIB | ||||
| # AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE | ||||
| # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc | ||||
| # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 | ||||
| # IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1 | ||||
| # WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu | ||||
| # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv | ||||
| # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC | ||||
| # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O | ||||
| # 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn | ||||
| # hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t | ||||
| # 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq | ||||
| # D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP | ||||
| # frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW | ||||
| # rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv | ||||
| # 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb | ||||
| # r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten | ||||
| # IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc | ||||
| # xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a | ||||
| # j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB | ||||
| # MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU | ||||
| # n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw | ||||
| # QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E | ||||
| # b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB | ||||
| # gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/ | ||||
| # MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ | ||||
| # oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p | ||||
| # Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB | ||||
| # BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v | ||||
| # Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h | ||||
| # LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x | ||||
| # 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p | ||||
| # y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A | ||||
| # oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC | ||||
| # HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB | ||||
| # 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt | ||||
| # yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3 | ||||
| # rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV | ||||
| # v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24 | ||||
| # 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw | ||||
| # Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB | ||||
| # 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl | ||||
| # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk | ||||
| # TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U | ||||
| # aGFsZXMgVFNTIEVTTjpBMjQwLTRCODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0 | ||||
| # IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAcGteVqFx/IbTKXHL | ||||
| # euXCPRPMD7uggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu | ||||
| # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv | ||||
| # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN | ||||
| # BgkqhkiG9w0BAQUFAAIFAOcW7qowIhgPMjAyMjExMTAxMTI5NDZaGA8yMDIyMTEx | ||||
| # MTExMjk0NlowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA5xbuqgIBADAHAgEAAgIE | ||||
| # qTAHAgEAAgIRVjAKAgUA5xhAKgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE | ||||
| # AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GB | ||||
| # AGsU2HTQg158bHX+QngoY7NVfCbGRaLjQOi8geKi26qQWAxll9QLFg4+epiG2nZB | ||||
| # eQvhxeNmIzounhWfJ+gfhFMi8aBT5z4dLK9iBtmpG1Y14RmSS4andiUlS6bVNVNe | ||||
| # WGObqHijMVeMOphiTaAfzR6zSASDaG0CfVm9bNBOnZZsMYIEDTCCBAkCAQEwgZMw | ||||
| # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl | ||||
| # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd | ||||
| # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAG4CNTBuHngUUkAAQAA | ||||
| # AbgwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB | ||||
| # BDAvBgkqhkiG9w0BCQQxIgQg578XwPrBwneU95xu1sHFncHeCC0UPQ7QK7PvSSby | ||||
| # VpwwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAo69Y4oHA7Q4pS+Y1NsBfr | ||||
| # pIYTeWsPeGTami0X0PD7HzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI | ||||
| # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv | ||||
| # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD | ||||
| # QSAyMDEwAhMzAAABuAjUwbh54FFJAAEAAAG4MCIEIJVlMK4mQfdJaAZx7Unfka/I | ||||
| # D4Wbw5edh/SR7TTptzRqMA0GCSqGSIb3DQEBCwUABIICAA1QlR3ywR7e+jqZ++NC | ||||
| # xsIwREiwVS70CEkbH8XpPRS0mFS0SHcCfpwymGfdep3D0CWk0PIfMhXq0SD97iBI | ||||
| # rOLdHglVBkMYTjGEBHyBzv/LevAZUuzoc5aqyIF4Ywa5KS4PGbMSuRK5CKAojOzH | ||||
| # A/vp2/KYuADmf9kOOgOfDVicyfoqZ+3W+QaUI/k0KKV4dPLF55+y18C+Td6sR60Y | ||||
| # AkcvGZObuj/OkREhdTJ1qJ2E/4RKG8gtGY1DfluLon7+UvS/ciWDWrJnHMmkxM11 | ||||
| # cYuRIvLArIdq/YS2bcSnY6AVO2zYjj7gCqDN9GuCurstUKC5uxVl3VNxntC0u3Le | ||||
| # BoI/R5uMYlTXodW8ukLNL6zHrQ4wI4udgW77KJref+3E1PEpZBRMxwose7Vt8lDc | ||||
| # sW1vdM+eZzUXRLhDR8a0Nai7+PaNoukoGf4pvwsu8Mkeji5a0hWtU9lUVRv6nzue | ||||
| # 3L2olhsbiHhAET7N6Rj0kzEhbUgfVUJrGvNlWOfN7MDr+OpArGXMPLtovbKTLtXF | ||||
| # v/GrJo9wQuyqUmY6KQSRDZgOw1CcoZpJcy40HG/aOlJwk03N13OZD5H3KfHwEphR | ||||
| # YnbGwGq9zUId5druSr5s40Yyl3idAkqmI5SXAm9v/gRq2X9vMU0a7KqXet9wO62F | ||||
| # TqxV+7Qp48Vw6hW1g+Q7oWoc | ||||
| # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl | ||||
| # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjowODQyLTRC | ||||
| # RTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC | ||||
| # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqiZTIde/lQ4rC+Bml5f/Wu | ||||
| # q/xKTxrfbG23HofmQ+qZAN4GyO73PF3y9OAfpt7Qf2jcldWOGUB+HzBuwllYyP3f | ||||
| # x4MY8zvuAuB37FvoytnNC2DKnVrVlHOVcGUL9CnmhDNMA2/nskjIf2IoiG9J0qLY | ||||
| # r8duvHdQJ9Li2Pq9guySb9mvUL60ogslCO9gkh6FiEDwMrwUr8Wja6jFpUTny8tg | ||||
| # 0N0cnCN2w4fKkp5qZcbUYFYicLSb/6A7pHCtX6xnjqwhmJoib3vkKJyVxbuFLRhV | ||||
| # XxH95b0LHeNhifn3jvo2j+/4QV10jEpXVW+iC9BsTtR69xvTjU51ZgP7BR4YDEWq | ||||
| # 7JsylSOv5B5THTDXRf184URzFhTyb8OZQKY7mqMh7c8J8w1sEM4XDUF2UZNy829N | ||||
| # VCzG2tfdEXZaHxF8RmxpQYBxyhZwY1rotuIS+gfN2eq+hkAT3ipGn8/KmDwDtzAb | ||||
| # nfuXjApgeZqwgcYJ8pDJ+y/xU6ouzJz1Bve5TTihkiA7wQsQe6R60Zk9dPdNzw0M | ||||
| # K5niRzuQZAt4GI96FhjhlUWcUZOCkv/JXM/OGu/rgSplYwdmPLzzfDtXyuy/GCU5 | ||||
| # I4l08g6iifXypMgoYkkceOAAz4vx1x0BOnZWfI3fSwqNUvoN7ncTT+MB4Vpvf1QB | ||||
| # ppjBAQUuvui6eCG0MCVNAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUmfIngFzZEZlP | ||||
| # kjDOVluBSDDaanEwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD | ||||
| # VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j | ||||
| # cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG | ||||
| # CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu | ||||
| # Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw | ||||
| # MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD | ||||
| # CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBANxHtu3FzIabaDbW | ||||
| # qswdKBlAhKXRCN+5CSMiv2TYa4i2QuWIm+99piwAhDhADfbqor1zyLi95Y6GQnvI | ||||
| # WUgdeC7oL1ZtZye92zYK+EIfwYZmhS+CH4infAzUvscHZF3wlrJUfPUIDGVP0lCY | ||||
| # Vse9mguvG0dqkY4ayQPEHOvJubgZZaOdg/N8dInd6fGeOc+0DoGzB+LieObJ2Q0A | ||||
| # tEt3XN3iX8Cp6+dZTX8xwE/LvhRwPpb/+nKshO7TVuvenwdTwqB/LT6CNPaElwFe | ||||
| # KxKrqRTPMbHeg+i+KnBLfwmhEXsMg2s1QX7JIxfvT96md0eiMjiMEO22LbOzmLMN | ||||
| # d3LINowAnRBAJtX+3/e390B9sMGMHp+a1V+hgs62AopBl0p/00li30DN5wEQ5If3 | ||||
| # 5Zk7b/T6pEx6rJUDYCti7zCbikjKTanBnOc99zGMlej5X+fC/k5ExUCrOs3/VzGR | ||||
| # CZt5LvVQSdWqq/QMzTEmim4sbzASK9imEkjNtZZyvC1CsUcD1voFktld4mKMjE+u | ||||
| # DEV3IddD+DrRk94nVzNPSuZXewfVOnXHSeqG7xM3V7fl2aL4v1OhL2+JwO1Tx3B0 | ||||
| # irO1O9qbNdJk355bntd1RSVKgM22KFBHnoL7Js7pRhBiaKmVTQGoOb+j1Qa7q+ci | ||||
| # xGo48Vh9k35BDsJS/DLoXFSPDl4mMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ | ||||
| # mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT | ||||
| # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m | ||||
| # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh | ||||
| # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1 | ||||
| # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||
| # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | ||||
| # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB | ||||
| # BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK | ||||
| # NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg | ||||
| # fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp | ||||
| # rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d | ||||
| # vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9 | ||||
| # 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR | ||||
| # Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu | ||||
| # qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO | ||||
| # ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb | ||||
| # oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6 | ||||
| # bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t | ||||
| # AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW | ||||
| # BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb | ||||
| # UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz | ||||
| # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku | ||||
| # aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA | ||||
| # QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2 | ||||
| # VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu | ||||
| # bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw | ||||
| # LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 | ||||
| # d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt | ||||
| # MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q | ||||
| # XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6 | ||||
| # U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt | ||||
| # I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis | ||||
| # 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp | ||||
| # kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0 | ||||
| # sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e | ||||
| # W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ | ||||
| # sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7 | ||||
| # Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0 | ||||
| # dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ | ||||
| # tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx | ||||
| # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT | ||||
| # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh | ||||
| # bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjow | ||||
| # ODQyLTRCRTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy | ||||
| # dmljZaIjCgEBMAcGBSsOAwIaAxUAjhJ+EeySRfn2KCNsjn9cF9AUSTqggYMwgYCk | ||||
| # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||
| # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | ||||
| # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF | ||||
| # AOfRUdUwIhgPMjAyMzAzMzEyMDM0MjlaGA8yMDIzMDQwMTIwMzQyOVowdDA6Bgor | ||||
| # BgEEAYRZCgQBMSwwKjAKAgUA59FR1QIBADAHAgEAAgIKJDAHAgEAAgIRLzAKAgUA | ||||
| # 59KjVQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID | ||||
| # B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAJlOESCa/uRR1x6GunE8 | ||||
| # K/WgHWTpSE31EITDOfTMvDcF4ptngCS5aOc4gfzmhNNehWfP6EOrgoSQzJYZ4YCh | ||||
| # fYbHNMk56f18sq8t7y2hgR7KixcEo/4HVzeSdaOclHNc4Gn7kCGpMvpT3Xz9Lzc7 | ||||
| # UKWDZ0zkNKnbS8TZLNueVQwfMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx | ||||
| # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT | ||||
| # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt | ||||
| # U3RhbXAgUENBIDIwMTACEzMAAAGybkADf26plJIAAQAAAbIwDQYJYIZIAWUDBAIB | ||||
| # BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx | ||||
| # IgQgXhJRuHCXk3arJvifIY3DBe9Ce9EmlP1y6U4XkgL31DkwgfoGCyqGSIb3DQEJ | ||||
| # EAIvMYHqMIHnMIHkMIG9BCBTeM485+E+t4PEVieUoFKX7PVyLo/nzu+htJPCG04+ | ||||
| # NTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw | ||||
| # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x | ||||
| # JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABsm5A | ||||
| # A39uqZSSAAEAAAGyMCIEIGGWlnNnYHrB5HguWG0/nJd/WvSrCogze+QCpenu3IM5 | ||||
| # MA0GCSqGSIb3DQEBCwUABIICADVOLTuNxeEnBOfZpb7Nv4uf91W/Ho5i99zenDSJ | ||||
| # x5QHVs+bKXmgc3a7/SSsliAT3zygHc7cH4zARbCZePLTivByKmeG08Ka35eyR+FK | ||||
| # awSNrI/X+eVIC6nw/egCwviBC1NAG8jHGkuScbHeiiGajvS6lp3ORML7UexMuE4w | ||||
| # 9SEumoghljCLZMwCSvw+3WxhQoBEZroR8u+PID2RdD0vi85FjKPWcZZijVLqHeFi | ||||
| # TnuFqwRCLTV0MV+dDCbjwXneIqV+AVlnqb9iDMr3ZhISlRcy9XJNpY5vQBj/wqUW | ||||
| # vefrmpdz0LNkdtXYThPkyl3mha2KsoQi5SA9zSjlAjFgY3ppmXvi3Frbfqk+iL+f | ||||
| # l/Qc4+B71jG4t28lTWKteJiHqo+6AUXK2rlAl0d74yvhO6N8lMMtXhdJc8JABYn1 | ||||
| # v2/KKZn5RvPFF8QP7Ac1saIe1+gUFNcsYOLaMm/xl8E6kefWwZnm5Rhm606g1AC/ | ||||
| # N5Wo08aAs0ymTPH91dEbmOURXLbA3vCyG7kbfgnhCs/j7oQHWaFDzEYuXDIA4ICT | ||||
| # dxPUTltbq3OWdp0PAS8JSEKPQFaOoQEnPa4adrXWxMvOmel8IGqJiQ+BPOaLQG64 | ||||
| # Qu2tMkH/5szb1fsEnCe8SJmy5ESF+kmpnLBtJ17Y9o+9nJHF5ddFmvzy+LUaIqDN | ||||
| # cOfH | ||||
| # SIG # End signature block | ||||
|  | ||||
							
								
								
									
										14
									
								
								externals/install-dotnet.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								externals/install-dotnet.sh
									
									
									
									
										vendored
									
									
								
							| @ -1617,6 +1617,10 @@ do | ||||
|             echo "       $script_name -h|-?|--help" | ||||
|             echo "" | ||||
|             echo "$script_name is a simple command line interface for obtaining dotnet cli." | ||||
|             echo "    Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | ||||
|             echo "    - The SDK needs to be installed without user interaction and without admin rights." | ||||
|             echo "    - The SDK installation doesn't need to persist across multiple CI runs." | ||||
|             echo "    To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer." | ||||
|             echo "" | ||||
|             echo "Options:" | ||||
|             echo "  -c,--channel <CHANNEL>         Download from the channel specified, Defaults to \`$channel\`." | ||||
| @ -1694,10 +1698,10 @@ do | ||||
|     shift | ||||
| done | ||||
| 
 | ||||
| say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | ||||
| say "- The SDK needs to be installed without user interaction and without admin rights." | ||||
| say "- The SDK installation doesn't need to persist across multiple CI runs." | ||||
| say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.\n" | ||||
| say_verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | ||||
| say_verbose "- The SDK needs to be installed without user interaction and without admin rights." | ||||
| say_verbose "- The SDK installation doesn't need to persist across multiple CI runs." | ||||
| say_verbose "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.\n" | ||||
| 
 | ||||
| if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then | ||||
|     message="Provide credentials via --feed-credential parameter." | ||||
| @ -1731,4 +1735,4 @@ fi | ||||
| 
 | ||||
| say "Note that the script does not resolve dependencies during installation." | ||||
| say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section." | ||||
| say "Installation finished successfully." | ||||
| say "Installation finished successfully." | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user