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 |       - name: Clear toolcache | ||||||
|         shell: pwsh |         shell: pwsh | ||||||
|         run: __tests__/clear-toolcache.ps1 ${{ runner.os }} |         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: ./ |         uses: ./ | ||||||
|         with: |         with: | ||||||
|           dotnet-version: | |           dotnet-version: | | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | // 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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -15,7 +15,7 @@ exports[`authutil tests Existing config not in repo root, sets up a partial NuGe | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -30,7 +30,7 @@ exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org, | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -45,7 +45,7 @@ exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a p | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -63,7 +63,7 @@ exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet. | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -81,7 +81,7 @@ exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.conf | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -96,7 +96,7 @@ exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -111,7 +111,7 @@ exports[`authutil tests Existing config w/ only GPR source, sets up a partial Nu | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -130,7 +130,7 @@ exports[`authutil tests Existing config w/ two GPR sources, sets up a partial Nu | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -148,7 +148,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
| @ -166,7 +166,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL | |||||||
| </configuration>" | </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\\"?> | "<?xml version=\\"1.0\\"?> | ||||||
| <configuration> | <configuration> | ||||||
|   <config> |   <config> | ||||||
|  | |||||||
| @ -91,9 +91,9 @@ describe('authutil tests', () => { | |||||||
|     process.env['NUGET_AUTH_TOKEN'] = ''; |     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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -104,10 +104,10 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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; |     let thrown = false; | ||||||
|     try { |     try { | ||||||
|       await auth.configAuthentication( |       auth.configAuthentication( | ||||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', |         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|         '', |         '', | ||||||
|         fakeSourcesDirForTesting |         fakeSourcesDirForTesting | ||||||
| @ -118,10 +118,10 @@ describe('authutil tests', () => { | |||||||
|     expect(thrown).toBe(true); |     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['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     process.env['INPUT_OWNER'] = 'otherorg'; |     process.env['INPUT_OWNER'] = 'otherorg'; | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/otherorg/index.json', |       'https://nuget.pkg.github.com/otherorg/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -132,7 +132,7 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
| @ -141,7 +141,7 @@ describe('authutil tests', () => { | |||||||
|     fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig); | ||||||
|     let thrown = false; |     let thrown = false; | ||||||
|     try { |     try { | ||||||
|       await auth.configAuthentication( |       auth.configAuthentication( | ||||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', |         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|         '', |         '', | ||||||
|         fakeSourcesDirForTesting |         fakeSourcesDirForTesting | ||||||
| @ -152,14 +152,14 @@ describe('authutil tests', () => { | |||||||
|     expect(thrown).toBe(true); |     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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -170,14 +170,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -188,14 +188,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -206,14 +206,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -224,14 +224,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com', |       'https://nuget.pkg.github.com', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -242,7 +242,7 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
| @ -251,7 +251,7 @@ describe('authutil tests', () => { | |||||||
|     fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig); | ||||||
|     let thrown = false; |     let thrown = false; | ||||||
|     try { |     try { | ||||||
|       await auth.configAuthentication( |       auth.configAuthentication( | ||||||
|         'https://nuget.pkg.github.com/OwnerName/index.json', |         'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|         '', |         '', | ||||||
|         fakeSourcesDirForTesting |         fakeSourcesDirForTesting | ||||||
| @ -262,7 +262,7 @@ describe('authutil tests', () => { | |||||||
|     expect(thrown).toBe(true); |     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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigDirectory: string = path.join( |     const inputNuGetConfigDirectory: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
| @ -274,7 +274,7 @@ describe('authutil tests', () => { | |||||||
|     ); |     ); | ||||||
|     fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true}); |     fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true}); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://nuget.pkg.github.com/OwnerName/index.json', |       'https://nuget.pkg.github.com/OwnerName/index.json', | ||||||
|       'subfolder/nuget.config', |       'subfolder/nuget.config', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -285,14 +285,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', |       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -303,14 +303,14 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN'; | ||||||
|     const inputNuGetConfigPath: string = path.join( |     const inputNuGetConfigPath: string = path.join( | ||||||
|       fakeSourcesDirForTesting, |       fakeSourcesDirForTesting, | ||||||
|       'nuget.config' |       'nuget.config' | ||||||
|     ); |     ); | ||||||
|     fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig); |     fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig); | ||||||
|     await auth.configAuthentication( |     auth.configAuthentication( | ||||||
|       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', |       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
| @ -321,9 +321,9 @@ describe('authutil tests', () => { | |||||||
|     ).toMatchSnapshot(); |     ).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'; |     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', |       'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json', | ||||||
|       '', |       '', | ||||||
|       fakeSourcesDirForTesting |       fakeSourcesDirForTesting | ||||||
|  | |||||||
| @ -1,21 +1,45 @@ | |||||||
| import cscFile from '../.github/csc.json'; | import cscFile from '../.github/csc.json'; | ||||||
| describe('csc tests', () => { | describe('csc tests', () => { | ||||||
|   it('Valid regular expression', async () => { |   test('regular expression in csc.json is valid', async () => { | ||||||
|     const regex = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; |     const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; | ||||||
|  |     const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0]; | ||||||
| 
 | 
 | ||||||
|     console.log(regex); |     const regex = new RegExp(regexPattern); | ||||||
|     const re = new RegExp(regex); |  | ||||||
| 
 | 
 | ||||||
|     // Ideally we would verify that this
 |  | ||||||
|     const stringsToMatch = [ |     const stringsToMatch = [ | ||||||
|       'Program.cs(10,79): error CS1002: ; expected [/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj]', |       '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]" |       "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 => { |     stringsToMatch.map((string, index) => { | ||||||
|       const matchStr = string.match(re); |       const matchedResultsArray = string.match(regex); | ||||||
|       console.log(matchStr); |       for (const propName in expectedResults[index]) { | ||||||
|       expect(matchStr).toEqual(expect.anything()); |         const propertyIndex = regexResultsMap[propName]; | ||||||
|  |         const expectedPropValue = expectedResults[index][propName]; | ||||||
|  |         const matchedPropValue = matchedResultsArray![propertyIndex]; | ||||||
|  |         expect(matchedPropValue).toEqual(expectedPropValue); | ||||||
|  |       } | ||||||
|     }); |     }); | ||||||
|   }, 10000); |   }, 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 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 * as installer from '../src/installer'; | ||||||
| import {QualityOptions} from '../src/setup-dotnet'; |  | ||||||
| 
 | 
 | ||||||
| import {IS_WINDOWS} from '../src/utils'; | 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) { |   beforeEach(() => { | ||||||
|   toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); |     jest.resetModules(); | ||||||
| } else if (IS_LINUX) { |     process.env = {...env}; | ||||||
|   toolDir = '/usr/share/dotnet'; |   }); | ||||||
| } else { |  | ||||||
|   toolDir = path.join(process.env['HOME'] + '', '.dotnet'); |  | ||||||
| } |  | ||||||
| const tempDir = path.join(__dirname, 'runner', 'temp'); |  | ||||||
| 
 | 
 | ||||||
| process.env['RUNNER_TOOL_CACHE'] = toolDir; |   describe('DotnetCoreInstaller tests', () => { | ||||||
| process.env['RUNNER_TEMP'] = tempDir; |     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', () => { |     describe('installDotnet() tests', () => { | ||||||
|   beforeAll(async () => { |       whichSpy.mockImplementation(() => Promise.resolve('PathToShell')); | ||||||
|     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); |  | ||||||
| 
 | 
 | ||||||
|   afterEach(async () => { |       it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => { | ||||||
|     try { |         const inputVersion = '3.1.100'; | ||||||
|       await io.rmRF(`${toolDir}/*`); |         const inputQuality = '' as QualityOptions; | ||||||
|       await io.rmRF(`${tempDir}/*`); |         const errorMessage = 'fictitious error message!'; | ||||||
|     } catch (err) { |         getExecOutputSpy.mockImplementation(() => { | ||||||
|       console.log( |           return Promise.resolve({ | ||||||
|         `Failed to remove test directories, check the error message:${os.EOL}`, |             exitCode: 1, | ||||||
|         err.message |             stdout: '', | ||||||
|       ); |             stderr: errorMessage | ||||||
|     } |           }); | ||||||
|   }, 30000); |         }); | ||||||
|  |         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 () => { |       it('should return version of .NET SDK after installation complete', async () => { | ||||||
|     const versions = ['2.2.207', '3.1.120']; |         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) { |         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||||
|       await getDotnet(version); |           inputVersion, | ||||||
|     } |           inputQuality | ||||||
|     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 installedVersion = await dotnetInstaller.installDotnet(); | ||||||
| 
 | 
 | ||||||
|     if (IS_WINDOWS) { |         expect(installedVersion).toBe(inputVersion); | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); |       }); | ||||||
|     } else { |  | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); |       it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => { | ||||||
|     expect(process.env.PATH).toBeDefined(); |         const inputVersion = '6.0.300'; | ||||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); |         const inputQuality = '' as QualityOptions; | ||||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); |  | ||||||
|   }, 600000); |  | ||||||
| 
 | 
 | ||||||
|   it('Acquires version of dotnet if no matching version is installed', async () => { |         getExecOutputSpy.mockImplementation(() => { | ||||||
|     await getDotnet('3.1.201'); |           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); |         }); | ||||||
|     if (IS_WINDOWS) { |         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); |  | ||||||
|     } else { |  | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); |         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||||
|     expect(process.env.PATH).toBeDefined(); |           inputVersion, | ||||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); |           inputQuality | ||||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); |         ); | ||||||
|   }, 600000); //This needs some time to download on "slower" internet connections
 |  | ||||||
| 
 | 
 | ||||||
|   it('Acquires generic version of dotnet if no matching version is installed', async () => { |         await dotnetInstaller.installDotnet(); | ||||||
|     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); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     expect(process.env.DOTNET_ROOT).toBeDefined(); |         const scriptArguments = ( | ||||||
|     expect(process.env.PATH).toBeDefined(); |           getExecOutputSpy.mock.calls[0][1] as string[] | ||||||
|     expect(process.env.DOTNET_ROOT).toBe(toolDir); |         ).join(' '); | ||||||
|     expect(process.env.PATH?.startsWith(toolDir)).toBe(true); |         const expectedArgument = IS_WINDOWS | ||||||
|   }, 600000); //This needs some time to download on "slower" internet connections
 |           ? `-Version ${inputVersion}` | ||||||
|  |           : `--version ${inputVersion}`; | ||||||
| 
 | 
 | ||||||
|   it('Returns string with installed SDK version', async () => { |         expect(scriptArguments).toContain(expectedArgument); | ||||||
|     const version = '3.1.120'; |       }); | ||||||
| 
 | 
 | ||||||
|     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'); |         getExecOutputSpy.mockImplementation(() => { | ||||||
|   }, 600000); |           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||||
|  |         }); | ||||||
|  |         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||||
| 
 | 
 | ||||||
|   it('Throws if no location contains correct dotnet version', async () => { |         const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||||
|     await expect(async () => { |           inputVersion, | ||||||
|       await getDotnet('1000.0.0'); |           inputQuality | ||||||
|     }).rejects.toThrow(); |         ); | ||||||
|   }, 30000); |  | ||||||
| 
 | 
 | ||||||
|   it('Uses an up to date bash download script', async () => { |         await dotnetInstaller.installDotnet(); | ||||||
|     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 () => { |         expect(warningSpy).toHaveBeenCalledWith( | ||||||
|     const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { |           `'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.` | ||||||
|       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); |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| describe('DotnetVersionResolver tests', () => { |       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 () => { | ||||||
|   each([ |         const inputVersion = '3.1'; | ||||||
|     '3.1', |         const inputQuality = 'ga' as QualityOptions; | ||||||
|     '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(); |  | ||||||
| 
 | 
 | ||||||
|       expect(!!versionObject.value).toBe(true); |         getExecOutputSpy.mockImplementation(() => { | ||||||
|     } |           return Promise.resolve({exitCode: 0, stdout: '', stderr: ''}); | ||||||
|   ); |         }); | ||||||
|  |         maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||||
| 
 | 
 | ||||||
|   each([ |         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.` | ||||||
|     '-1.-1', |         ); | ||||||
|     '-1', |       }); | ||||||
|     '-1.-1.-1', | 
 | ||||||
|     '..3', |       each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||||
|     '1..3', |         `should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`, | ||||||
|     '1..', |         async inputVersion => { | ||||||
|     '.2.3', |           const inputQuality = 'ga' as QualityOptions; | ||||||
|     '.2.x', |           const exitCode = 0; | ||||||
|     '*.', |           getExecOutputSpy.mockImplementation(() => { | ||||||
|     '1.2.', |             return Promise.resolve({ | ||||||
|     '1.2.-abc', |               exitCode: exitCode, | ||||||
|     'a.b', |               stdout: '', | ||||||
|     'a.b.c', |               stderr: '' | ||||||
|     'a.b.c-preview', |             }); | ||||||
|     ' 0 . 1 . 2 ', |           }); | ||||||
|     'invalid' |           maxSatisfyingSpy.mockImplementation(() => inputVersion); | ||||||
|   ]).test( | 
 | ||||||
|     "if invalid version: '%s' is supplied, it should throw", |           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||||
|     async version => { |             inputVersion, | ||||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( |             inputQuality | ||||||
|         version |           ); | ||||||
|  | 
 | ||||||
|  |           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( |       each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test( | ||||||
|         async () => await dotnetVersionResolver.createDotNetVersion() |         `should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`, | ||||||
|       ).rejects.toThrow(); |         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( |           const dotnetInstaller = new installer.DotnetCoreInstaller( | ||||||
|     "if version: '%s' that can be resolved to 'channel' option is supplied, it should set type to 'channel' in version object", |             inputVersion, | ||||||
|     async version => { |             inputQuality | ||||||
|       const dotnetVersionResolver = new installer.DotnetVersionResolver( |           ); | ||||||
|         version | 
 | ||||||
|  |           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) { |       if (IS_WINDOWS) { | ||||||
|         expect(windowsRegEx.test(versionObject.type)).toBe(true); |         it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => { | ||||||
|         expect(nonWindowsRegEx.test(versionObject.type)).toBe(false); |           process.env['https_proxy'] = 'https://proxy.com'; | ||||||
|       } else { |           const inputVersion = '6.0.100'; | ||||||
|         expect(nonWindowsRegEx.test(versionObject.type)).toBe(true); |           const inputQuality = '' as QualityOptions; | ||||||
|         expect(windowsRegEx.test(versionObject.type)).toBe(false); | 
 | ||||||
|  |           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 * as core from '@actions/core'; | ||||||
| import fs from 'fs'; | import fs from 'fs'; | ||||||
| import os from 'os'; | import semver from 'semver'; | ||||||
| import path from 'path'; | import * as auth from '../src/authutil'; | ||||||
| 
 | 
 | ||||||
| import * as setup from '../src/setup-dotnet'; | import * as setup from '../src/setup-dotnet'; | ||||||
| import {IS_WINDOWS} from '../src/utils'; | import {DotnetCoreInstaller} from '../src/installer'; | ||||||
| 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'); |  | ||||||
| 
 | 
 | ||||||
| describe('setup-dotnet tests', () => { | 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; |   const inputs = {} as any; | ||||||
| 
 | 
 | ||||||
|   beforeAll(async () => { |   const getInputSpy = jest.spyOn(core, 'getInput'); | ||||||
|     process.env.RUNNER_TOOL_CACHE = toolDir; |   const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput'); | ||||||
|     process.env.DOTNET_INSTALL_DIR = toolDir; |   const setFailedSpy = jest.spyOn(core, 'setFailed'); | ||||||
|     process.env.RUNNER_TEMP = tempDir; |   const debugSpy = jest.spyOn(core, 'debug'); | ||||||
|     try { |   const infoSpy = jest.spyOn(core, 'info'); | ||||||
|       await io.rmRF(`${toolDir}/*`); |   const setOutputSpy = jest.spyOn(core, 'setOutput'); | ||||||
|       await io.rmRF(`${tempDir}/*`); |  | ||||||
|     } catch (err) { |  | ||||||
|       console.log(err.message); |  | ||||||
|       console.log('Failed to remove test directories'); |  | ||||||
|     } |  | ||||||
|   }, 30000); |  | ||||||
| 
 | 
 | ||||||
|   afterEach(async () => { |   const existsSyncSpy = jest.spyOn(fs, 'existsSync'); | ||||||
|     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); |  | ||||||
| 
 | 
 | ||||||
|   it('Acquires version of dotnet from global.json if no matching version is installed', async () => { |   const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); | ||||||
|     createGlobalJsonPath('3.1.201'); |  | ||||||
|     await setup.run(); |  | ||||||
| 
 | 
 | ||||||
|     expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); |   const installDotnetSpy = jest.spyOn( | ||||||
|     if (IS_WINDOWS) { |     DotnetCoreInstaller.prototype, | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); |     'installDotnet' | ||||||
|     } else { |   ); | ||||||
|       expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); |   const addToPathSpy = jest.spyOn(DotnetCoreInstaller, 'addToPath'); | ||||||
|     } |  | ||||||
|   }, 400000); |  | ||||||
| 
 | 
 | ||||||
|   it("Sets output with the latest installed by action version if global.json file isn't specified", async () => { |   const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication'); | ||||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; |  | ||||||
| 
 | 
 | ||||||
|     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'); |     it('should fail the action if global-json-file input is present, but the file does not exist in the file system', async () => { | ||||||
|   }, 400000); |       inputs['global-json-file'] = 'fictitious.json'; | ||||||
|  |       inputs['dotnet-version'] = []; | ||||||
| 
 | 
 | ||||||
|   it("Sets output with the version specified in global.json, if it's present", async () => { |       const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`; | ||||||
|     createGlobalJsonPath('3.0.103'); |  | ||||||
| 
 | 
 | ||||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; |       await setup.run(); | ||||||
|     inputs['global-json-file'] = './global.json'; |       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'); |       await setup.run(); | ||||||
|   }, 400000); |  | ||||||
| 
 | 
 | ||||||
|   it('Sets output with the version specified in global.json with absolute path', async () => { |       expect(debugSpy).toHaveBeenCalledWith(expectedDebugMessage); | ||||||
|     const globalJsonPath = createGlobalJsonPath('3.0.103'); |       expect(existsSyncSpy).toHaveBeenCalled(); | ||||||
|  |       expect(infoSpy).toHaveBeenCalledWith(expectedInfoMessage); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     inputs['dotnet-version'] = ['3.1.201', '6.0.401']; |     it('should fail the action if quality is supplied but its value is not supported', async () => { | ||||||
|     inputs['global-json-file'] = globalJsonPath; |       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'); |       installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||||||
|   }, 400000); | 
 | ||||||
|  |       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 | .DESCRIPTION | ||||||
|     Installs dotnet cli. If dotnet installation already exists in the given directory |     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. |     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 | .PARAMETER Channel | ||||||
|     Default: LTS |     Default: LTS | ||||||
|     Download from the Channel specified. Possible values: |     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) { | function Say-Invocation($Invocation) { | ||||||
|     $command = $Invocation.MyCommand; |     $command = $Invocation.MyCommand; | ||||||
|     $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") |     $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-Verbose "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-Verbose "- 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-Verbose "- 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 "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)) { | if ($SharedRuntime -and (-not $Runtime)) { | ||||||
|     $Runtime = "dotnet" |     $Runtime = "dotnet" | ||||||
| @ -1115,14 +1127,16 @@ if ($SharedRuntime -and (-not $Runtime)) { | |||||||
| 
 | 
 | ||||||
| $OverrideNonVersionedFiles = !$SkipNonVersionedFiles | $OverrideNonVersionedFiles = !$SkipNonVersionedFiles | ||||||
| 
 | 
 | ||||||
| $CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture | Measure-Action "Product discovery" { | ||||||
| $NormalizedQuality = Get-NormalizedQuality $Quality |     $script:CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture | ||||||
| Say-Verbose "Normalized quality: '$NormalizedQuality'" |     $script:NormalizedQuality = Get-NormalizedQuality $Quality | ||||||
| $NormalizedChannel = Get-NormalizedChannel $Channel |     Say-Verbose "Normalized quality: '$NormalizedQuality'" | ||||||
| Say-Verbose "Normalized channel: '$NormalizedChannel'" |     $script:NormalizedChannel = Get-NormalizedChannel $Channel | ||||||
| $NormalizedProduct = Get-NormalizedProduct $Runtime |     Say-Verbose "Normalized channel: '$NormalizedChannel'" | ||||||
| Say-Verbose "Normalized product: '$NormalizedProduct'" |     $script:NormalizedProduct = Get-NormalizedProduct $Runtime | ||||||
| $FeedCredential = ValidateFeedCredential $FeedCredential |     Say-Verbose "Normalized product: '$NormalizedProduct'" | ||||||
|  |     $script:FeedCredential = ValidateFeedCredential $FeedCredential | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| $InstallRoot = Resolve-Installation-Path $InstallDir | $InstallRoot = Resolve-Installation-Path $InstallDir | ||||||
| Say-Verbose "InstallRoot: $InstallRoot" | Say-Verbose "InstallRoot: $InstallRoot" | ||||||
| @ -1200,7 +1214,7 @@ if ($DryRun) { | |||||||
|     return |     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()) | $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) | ||||||
| Say-Verbose "Zip path: $ZipPath" | Say-Verbose "Zip path: $ZipPath" | ||||||
| @ -1214,7 +1228,7 @@ foreach ($link in $DownloadLinks) | |||||||
|     Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)" |     Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)" | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|         DownloadFile -Source $link.downloadLink -OutPath $ZipPath |         Measure-Action "Package download" { DownloadFile -Source $link.downloadLink -OutPath $ZipPath } | ||||||
|         Say-Verbose "Download succeeded." |         Say-Verbose "Download succeeded." | ||||||
|         $DownloadSucceeded = $true |         $DownloadSucceeded = $true | ||||||
|         $DownloadedLink = $link |         $DownloadedLink = $link | ||||||
| @ -1251,7 +1265,7 @@ if (-not $DownloadSucceeded) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Say "Extracting the archive." | 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. | #  Check if the SDK version is installed; if not, fail the installation. | ||||||
| $isAssetInstalled = $false | $isAssetInstalled = $false | ||||||
| @ -1277,225 +1291,224 @@ if (!$isAssetInstalled) { | |||||||
| 
 | 
 | ||||||
| SafeRemoveFile -Path $ZipPath | 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 "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 "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install/windows#dependencies" | ||||||
| Say "Installed version is $($DownloadedLink.effectiveVersion)" | Say "Installed version is $($DownloadedLink.effectiveVersion)" | ||||||
| Say "Installation finished" | Say "Installation finished" | ||||||
| 
 |  | ||||||
| # SIG # Begin signature block | # SIG # Begin signature block | ||||||
| # MIInzgYJKoZIhvcNAQcCoIInvzCCJ7sCAQExDzANBglghkgBZQMEAgEFADB5Bgor | # MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor | ||||||
| # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG | ||||||
| # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB7pzZ0nuEMd30h | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBhfTi3SRn7+vyy | ||||||
| # n1EcAYUQN+1clltqaLf9611TDrw/laCCDYUwggYDMIID66ADAgECAhMzAAACzfNk | # uCXKPjhiawegWZ493EcaOEycbgkZcKCCDXYwggX0MIID3KADAgECAhMzAAACy7d1 | ||||||
| # v/jUTF1RAAAAAALNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | # OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | ||||||
| # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy | # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy | ||||||
| # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p | # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p | ||||||
| # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAyWhcNMjMwNTExMjA0NjAyWjB0MQsw | # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw | ||||||
| # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u | # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u | ||||||
| # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy | # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy | ||||||
| # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | ||||||
| # AQDrIzsY62MmKrzergm7Ucnu+DuSHdgzRZVCIGi9CalFrhwtiK+3FIDzlOYbs/zz | # AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA | ||||||
| # HwuLC3hir55wVgHoaC4liQwQ60wVyR17EZPa4BQ28C5ARlxqftdp3H8RrXWbVyvQ | # wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4 | ||||||
| # aUnBQVZM73XDyGV1oUPZGHGWtgdqtBUd60VjnFPICSf8pnFiit6hvSxH5IVWI0iO | # 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5 | ||||||
| # nfqdXYoPWUtVUMmVqW1yBX0NtbQlSHIU6hlPvo9/uqKvkjFUFA2LbC9AWQbJmH+1 | # RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN | ||||||
| # uM0l4nDSKfCqccvdI5l3zjEk9yUSUmh1IQhDFn+5SL2JmnCF0jZEZ4f5HE7ykDP+ | # lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X | ||||||
| # oiA3Q+fhKCseg+0aEHi+DRPZAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE | # a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE | ||||||
| # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU0WymH4CP7s1+yQktEwbcLQuR9Zww | # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w | ||||||
| # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh | # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW | ||||||
| # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ3MDUzMDAfBgNVHSMEGDAW | # MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci | ||||||
| # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v | # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j | ||||||
| # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw | # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG | ||||||
| # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov | # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu | ||||||
| # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx | # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 | ||||||
| # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB | # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ | ||||||
| # AE7LSuuNObCBWYuttxJAgilXJ92GpyV/fTiyXHZ/9LbzXs/MfKnPwRydlmA2ak0r | # ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf | ||||||
| # GWLDFh89zAWHFI8t9JLwpd/VRoVE3+WyzTIskdbBnHbf1yjo/+0tpHlnroFJdcDS | # zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh | ||||||
| # MIsH+T7z3ClY+6WnjSTetpg1Y/pLOLXZpZjYeXQiFwo9G5lzUcSd8YVQNPQAGICl | # 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4 | ||||||
| # 2JRSaCNlzAdIFCF5PNKoXbJtEqDcPZ8oDrM9KdO7TqUE5VqeBe6DggY1sZYnQD+/ | # EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j | ||||||
| # LWlz5D0wCriNgGQ/TWWexMwwnEqlIwfkIcNFxo0QND/6Ya9DTAUykk2SKGSPt0kL | # 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck | ||||||
| # tHxNEn2GJvcNtfohVY/b0tuyF05eXE3cdtYZbeGoU1xQixPZAlTdtLmeFNly82uB | # 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd | ||||||
| # VbybAZ4Ut18F//UrugVQ9UUdK1uYmc+2SdRQQCccKwXGOuYgZ1ULW2u5PyfWxzo4 | # jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N | ||||||
| # BR++53OB/tZXQpz4OkgBZeqs9YaYLFfKRlQHVtmQghFHzB5v/WFonxDVlvPxy2go | # mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1 | ||||||
| # a0u9Z+ZlIpvooZRvm6OtXxdAjMBcWBAsnBRr/Oj5s356EDdf2l/sLwLFYE61t+ME | # pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB | ||||||
| # iNYdy0pXL6gN3DxTVf2qjJxXFkFfjjTisndudHsguEMk8mEtnvwo9fOSKT6oRHhM | # fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To | ||||||
| # 9sZ4HTg/TTMjUljmN3mBYWAWI5ExdC1inuog0xrKmOWVMIIHejCCBWKgAwIBAgIK | # /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq | ||||||
| # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV | # 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 | # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv | ||||||
| # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm | # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl | ||||||
| # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw | # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjowODQyLTRC | ||||||
| # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE | # RTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC | ||||||
| # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD | # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqiZTIde/lQ4rC+Bml5f/Wu | ||||||
| # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG | # q/xKTxrfbG23HofmQ+qZAN4GyO73PF3y9OAfpt7Qf2jcldWOGUB+HzBuwllYyP3f | ||||||
| # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la | # x4MY8zvuAuB37FvoytnNC2DKnVrVlHOVcGUL9CnmhDNMA2/nskjIf2IoiG9J0qLY | ||||||
| # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc | # r8duvHdQJ9Li2Pq9guySb9mvUL60ogslCO9gkh6FiEDwMrwUr8Wja6jFpUTny8tg | ||||||
| # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D | # 0N0cnCN2w4fKkp5qZcbUYFYicLSb/6A7pHCtX6xnjqwhmJoib3vkKJyVxbuFLRhV | ||||||
| # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ | # XxH95b0LHeNhifn3jvo2j+/4QV10jEpXVW+iC9BsTtR69xvTjU51ZgP7BR4YDEWq | ||||||
| # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk | # 7JsylSOv5B5THTDXRf184URzFhTyb8OZQKY7mqMh7c8J8w1sEM4XDUF2UZNy829N | ||||||
| # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 | # VCzG2tfdEXZaHxF8RmxpQYBxyhZwY1rotuIS+gfN2eq+hkAT3ipGn8/KmDwDtzAb | ||||||
| # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd | # nfuXjApgeZqwgcYJ8pDJ+y/xU6ouzJz1Bve5TTihkiA7wQsQe6R60Zk9dPdNzw0M | ||||||
| # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL | # K5niRzuQZAt4GI96FhjhlUWcUZOCkv/JXM/OGu/rgSplYwdmPLzzfDtXyuy/GCU5 | ||||||
| # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd | # I4l08g6iifXypMgoYkkceOAAz4vx1x0BOnZWfI3fSwqNUvoN7ncTT+MB4Vpvf1QB | ||||||
| # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 | # ppjBAQUuvui6eCG0MCVNAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUmfIngFzZEZlP | ||||||
| # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS | # kjDOVluBSDDaanEwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD | ||||||
| # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI | # VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j | ||||||
| # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL | # cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG | ||||||
| # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD | # CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu | ||||||
| # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv | # Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw | ||||||
| # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf | # MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD | ||||||
| # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 | # CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBANxHtu3FzIabaDbW | ||||||
| # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf | # qswdKBlAhKXRCN+5CSMiv2TYa4i2QuWIm+99piwAhDhADfbqor1zyLi95Y6GQnvI | ||||||
| # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF | # WUgdeC7oL1ZtZye92zYK+EIfwYZmhS+CH4infAzUvscHZF3wlrJUfPUIDGVP0lCY | ||||||
| # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h | # Vse9mguvG0dqkY4ayQPEHOvJubgZZaOdg/N8dInd6fGeOc+0DoGzB+LieObJ2Q0A | ||||||
| # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA | # tEt3XN3iX8Cp6+dZTX8xwE/LvhRwPpb/+nKshO7TVuvenwdTwqB/LT6CNPaElwFe | ||||||
| # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn | # KxKrqRTPMbHeg+i+KnBLfwmhEXsMg2s1QX7JIxfvT96md0eiMjiMEO22LbOzmLMN | ||||||
| # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 | # d3LINowAnRBAJtX+3/e390B9sMGMHp+a1V+hgs62AopBl0p/00li30DN5wEQ5If3 | ||||||
| # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b | # 5Zk7b/T6pEx6rJUDYCti7zCbikjKTanBnOc99zGMlej5X+fC/k5ExUCrOs3/VzGR | ||||||
| # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ | # CZt5LvVQSdWqq/QMzTEmim4sbzASK9imEkjNtZZyvC1CsUcD1voFktld4mKMjE+u | ||||||
| # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy | # DEV3IddD+DrRk94nVzNPSuZXewfVOnXHSeqG7xM3V7fl2aL4v1OhL2+JwO1Tx3B0 | ||||||
| # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp | # irO1O9qbNdJk355bntd1RSVKgM22KFBHnoL7Js7pRhBiaKmVTQGoOb+j1Qa7q+ci | ||||||
| # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi | # xGo48Vh9k35BDsJS/DLoXFSPDl4mMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ | ||||||
| # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb | # mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT | ||||||
| # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS | # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m | ||||||
| # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL | # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh | ||||||
| # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX | # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1 | ||||||
| # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4x | # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||||
| # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt | # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | ||||||
| # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p | # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB | ||||||
| # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAALN82S/+NRMXVEAAAAA | # BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK | ||||||
| # As0wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw | # NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg | ||||||
| # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINK7 | # fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp | ||||||
| # cJe0KVfbcXchjID30U/cUg7pWAQUa3+n8JuhjLCLMEIGCisGAQQBgjcCAQwxNDAy | # rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d | ||||||
| # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j | # vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9 | ||||||
| # b20wDQYJKoZIhvcNAQEBBQAEggEAODLxcflOtjpIXXIhbYyQ0wFeBx0NrmoMU/Ri | # 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR | ||||||
| # e7CRrAieAbG4iLJzs4DhUov5iuMHY6AAbLWAH54QlSkd4XNp6POsE7lSzN9yjlVw | # Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu | ||||||
| # V/e0XCaYeXIbtd75hGd5P7wAhM4m2ViDI4IRHyQtjysW0U0F6YiqNlFm7Fzo5Si6 | # qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO | ||||||
| # l2XxvuEDSdyJcEN70wHQajx6bKfnI/oMY59iGjDXvDP/6cQV9NI0gPHFTwPKA7vg | # ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb | ||||||
| # PySyVFEG7dQMoEwAWy9GHbcS//RulgUwBhWcrtUP411XLSO6is2VTknwbdglc9HZ | # oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6 | ||||||
| # zViuS4C1ujHlPrlMzm8Y5iGVIQCna5w2NU/kGsSK5+dMkovomKGCFykwghclBgor | # bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t | ||||||
| # BgEEAYI3AwMBMYIXFTCCFxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZI | # AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW | ||||||
| # AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE | # BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb | ||||||
| # WQoDATAxMA0GCWCGSAFlAwQCAQUABCDRz6ce9oWlH6+o0BtjmAjtvEMN1hfhIA5v | # UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz | ||||||
| # +wTZHvB4XgIGY2PeyIloGBMyMDIyMTExMDE1MDUxNi43MzRaMASAAgH0oIHYpIHV | # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku | ||||||
| # MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | # aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA | ||||||
| # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL | # QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2 | ||||||
| # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT | # VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu | ||||||
| # HVRoYWxlcyBUU1MgRVNOOkEyNDAtNEI4Mi0xMzBFMSUwIwYDVQQDExxNaWNyb3Nv | # bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw | ||||||
| # ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAG4CNTB | # LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 | ||||||
| # uHngUUkAAQAAAbgwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV | # d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt | ||||||
| # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv | # MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q | ||||||
| # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg | # XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6 | ||||||
| # UENBIDIwMTAwHhcNMjIwOTIwMjAyMjE2WhcNMjMxMjE0MjAyMjE2WjCB0jELMAkG | # U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt | ||||||
| # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx | # I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis | ||||||
| # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z | # 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp | ||||||
| # b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg | # kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0 | ||||||
| # VFNTIEVTTjpBMjQwLTRCODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt | # sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e | ||||||
| # U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJwb | # W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ | ||||||
| # sfwRHERn5C95QPGn37tJ5vOiY9aWjeIDxpgaXaYGiqsw0G0cvCK3YulrqemEf2Ck | # sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7 | ||||||
| # GSdcOJAF++EqhOSqrO13nGcjqw6hFNnsGwKANyzddwnOO0jz1lfBIIu77TbfNvna | # Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0 | ||||||
| # WbwSRu0DTGHA7n7PR0MYJ9bC/HopStpbFf606LKcTWnwaUuEdAhx6FAqg1rkgugi | # dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ | ||||||
| # uuaaxKyxRkdjFZLKFXEXL9p01PtwS0fG6vZiRVnEKgeal2TeLvdAIqapBwltPYif | # tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx | ||||||
| # gqnp7Z4VJMcPo0TWmRNVFOcHRNwWHehN9xg6ugIGXPo7hMpWrPgg4moHO2epc0T3 | # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT | ||||||
| # 6rgm9hlDrl28bG5TakmV7NJ98kbF5lgtlrowT6ecwEVtuLd4a0gzYqhanW7zaFZn | # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh | ||||||
| # Dft5yMexy59ifETdzpwArj2nJAyIsiq1PY3XPm2mUMLlACksqelHKfWihK/Fehw/ | # bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjow | ||||||
| # mziovBVwkkr/G0F19OWgR+MBUKifwpOyQiLAxrqvVnfCY4QjJCZiHIuS15HCQ/TI | # ODQyLTRCRTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy | ||||||
| # t/Qj4x1WvRa1UqjnmpLu4/yBYWZsdvZoq8SXI7iOs7muecAJeEkYlM6iOkMighzE | # dmljZaIjCgEBMAcGBSsOAwIaAxUAjhJ+EeySRfn2KCNsjn9cF9AUSTqggYMwgYCk | ||||||
| # hjQK9ThPpoAtluXbL7qIHGrfFlHmX/4soc7jj1j8uB31U34gJlB2XphjMaT+E+O9 | # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||||
| # SImk/6GRV9Sm8C88Fnmm2VdwMluCNAUzPFjfvHx3AgMBAAGjggFJMIIBRTAdBgNV | # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | ||||||
| # HQ4EFgQUxP1HJTeFwzNYo1njfucXuUfQaW4wHwYDVR0jBBgwFoAUn6cVXQBeYl2D | # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF | ||||||
| # 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv | # AOfRUdUwIhgPMjAyMzAzMzEyMDM0MjlaGA8yMDIzMDQwMTIwMzQyOVowdDA6Bgor | ||||||
| # ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy | # BgEEAYRZCgQBMSwwKjAKAgUA59FR1QIBADAHAgEAAgIKJDAHAgEAAgIRLzAKAgUA | ||||||
| # MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov | # 59KjVQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID | ||||||
| # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l | # B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAJlOESCa/uRR1x6GunE8 | ||||||
| # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB | # K/WgHWTpSE31EITDOfTMvDcF4ptngCS5aOc4gfzmhNNehWfP6EOrgoSQzJYZ4YCh | ||||||
| # Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD | # fYbHNMk56f18sq8t7y2hgR7KixcEo/4HVzeSdaOclHNc4Gn7kCGpMvpT3Xz9Lzc7 | ||||||
| # ggIBAJ9uk8miwpMoKw3D996piEzbegAGxkABHYn2vP2hbqnkS9U97s/6QlyZOhGF | # UKWDZ0zkNKnbS8TZLNueVQwfMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx | ||||||
| # sVudaiLeRZZTsaG5hR0oCuBINZ/lelo5xzHc+mBOpBXpxSaW1hqoxaCLsVH1EBtz | # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT | ||||||
| # 7in25Hjy+ejuBcilH6EZ0ZtNxmWGIQz8R0AuS0Tj4VgJXHIlXP9dVOiyGo9Velrk | # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt | ||||||
| # +FGx/BC+iEuCaKd/IsypHPiCUCh52DGc91s2S7ldQx1H4CljOAtanDfbvSejASWL | # U3RhbXAgUENBIDIwMTACEzMAAAGybkADf26plJIAAQAAAbIwDQYJYIZIAWUDBAIB | ||||||
| # o/s3w0XMAbDurWNns0XidAF2RnL1PaxoOyz9VYakNGK4F3/uJRZnVgbsCYuwNX1B | # BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx | ||||||
| # mSwM1ZbPSnggNSGTZx/FQ20Jj/ulrK0ryAbvNbNb4kkaS4a767ifCqvUOFLlUT8P | # IgQgXhJRuHCXk3arJvifIY3DBe9Ce9EmlP1y6U4XkgL31DkwgfoGCyqGSIb3DQEJ | ||||||
| # N43hhldxI6yHPMOWItJpEHIZBiTNKblBsYbIrghb1Ym9tfSsLa5ZJDzVZNndRfhU | # EAIvMYHqMIHnMIHkMIG9BCBTeM485+E+t4PEVieUoFKX7PVyLo/nzu+htJPCG04+ | ||||||
| # qJOyXF+CVm9OtVmFDG9kIwM6QAX8Q0if721z4VOzZNvD8ktg1lI+XjXgXDJVs3h4 | # NTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw | ||||||
| # 7sMu9GXSYzky+7dtgmc3iRPkda3YVRdmPJtNFN0NLybcssE7vhFCij75eDGQBFq0 | # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x | ||||||
| # A4KVG6uBdr6UTWwE0VKHxBz2BpGvn7BCs+5yxnF+HV6CUickDqqPi/II7Zssd9Eb | # JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABsm5A | ||||||
| # P9uzj4luldXDAPrWGtdGq+wK0odlGNVuCMxsL3hn8+KiO9UiMIIHcTCCBVmgAwIB | # A39uqZSSAAEAAAGyMCIEIGGWlnNnYHrB5HguWG0/nJd/WvSrCogze+QCpenu3IM5 | ||||||
| # AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE | # MA0GCSqGSIb3DQEBCwUABIICADVOLTuNxeEnBOfZpb7Nv4uf91W/Ho5i99zenDSJ | ||||||
| # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc | # x5QHVs+bKXmgc3a7/SSsliAT3zygHc7cH4zARbCZePLTivByKmeG08Ka35eyR+FK | ||||||
| # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 | # awSNrI/X+eVIC6nw/egCwviBC1NAG8jHGkuScbHeiiGajvS6lp3ORML7UexMuE4w | ||||||
| # IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1 | # 9SEumoghljCLZMwCSvw+3WxhQoBEZroR8u+PID2RdD0vi85FjKPWcZZijVLqHeFi | ||||||
| # WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu | # TnuFqwRCLTV0MV+dDCbjwXneIqV+AVlnqb9iDMr3ZhISlRcy9XJNpY5vQBj/wqUW | ||||||
| # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv | # vefrmpdz0LNkdtXYThPkyl3mha2KsoQi5SA9zSjlAjFgY3ppmXvi3Frbfqk+iL+f | ||||||
| # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC | # l/Qc4+B71jG4t28lTWKteJiHqo+6AUXK2rlAl0d74yvhO6N8lMMtXhdJc8JABYn1 | ||||||
| # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O | # v2/KKZn5RvPFF8QP7Ac1saIe1+gUFNcsYOLaMm/xl8E6kefWwZnm5Rhm606g1AC/ | ||||||
| # 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn | # N5Wo08aAs0ymTPH91dEbmOURXLbA3vCyG7kbfgnhCs/j7oQHWaFDzEYuXDIA4ICT | ||||||
| # hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t | # dxPUTltbq3OWdp0PAS8JSEKPQFaOoQEnPa4adrXWxMvOmel8IGqJiQ+BPOaLQG64 | ||||||
| # 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq | # Qu2tMkH/5szb1fsEnCe8SJmy5ESF+kmpnLBtJ17Y9o+9nJHF5ddFmvzy+LUaIqDN | ||||||
| # D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP | # cOfH | ||||||
| # 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 |  | ||||||
| # SIG # End signature block | # 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 "       $script_name -h|-?|--help" | ||||||
|             echo "" |             echo "" | ||||||
|             echo "$script_name is a simple command line interface for obtaining dotnet cli." |             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 "" | ||||||
|             echo "Options:" |             echo "Options:" | ||||||
|             echo "  -c,--channel <CHANNEL>         Download from the channel specified, Defaults to \`$channel\`." |             echo "  -c,--channel <CHANNEL>         Download from the channel specified, Defaults to \`$channel\`." | ||||||
| @ -1694,10 +1698,10 @@ do | |||||||
|     shift |     shift | ||||||
| done | done | ||||||
| 
 | 
 | ||||||
| say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" | say_verbose "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_verbose "- 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_verbose "- 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 "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 | if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then | ||||||
|     message="Provide credentials via --feed-credential parameter." |     message="Provide credentials via --feed-credential parameter." | ||||||
| @ -1731,4 +1735,4 @@ fi | |||||||
| 
 | 
 | ||||||
| say "Note that the script does not resolve dependencies during installation." | 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 "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